Commit ca80db6fc1fe96f3da234390ac27fdc8a0a1ec58

Authored by m-holger
Committed by GitHub
2 parents 3a055d5b 799080b0

Merge pull request #1496 from m-holger/obis

Refactor is::OffsetBuffer and BufferInputSource
include/qpdf/BufferInputSource.hh
@@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
23 #include <qpdf/Buffer.hh> 23 #include <qpdf/Buffer.hh>
24 #include <qpdf/InputSource.hh> 24 #include <qpdf/InputSource.hh>
25 25
  26 +#include <memory>
  27 +
26 class QPDF_DLL_CLASS BufferInputSource: public InputSource 28 class QPDF_DLL_CLASS BufferInputSource: public InputSource
27 { 29 {
28 public: 30 public:
@@ -52,11 +54,17 @@ class QPDF_DLL_CLASS BufferInputSource: public InputSource @@ -52,11 +54,17 @@ class QPDF_DLL_CLASS BufferInputSource: public InputSource
52 void unreadCh(char ch) override; 54 void unreadCh(char ch) override;
53 55
54 private: 56 private:
  57 +#ifndef QPDF_FUTURE
55 bool own_memory; 58 bool own_memory;
56 std::string description; 59 std::string description;
57 Buffer* buf; 60 Buffer* buf;
58 qpdf_offset_t cur_offset; 61 qpdf_offset_t cur_offset;
59 qpdf_offset_t max_offset; 62 qpdf_offset_t max_offset;
  63 +#else
  64 + class Members;
  65 +
  66 + std::unique_ptr<Members> m;
  67 +#endif
60 }; 68 };
61 69
62 #endif // QPDF_BUFFERINPUTSOURCE_HH 70 #endif // QPDF_BUFFERINPUTSOURCE_HH
include/qpdf/QPDF.hh
@@ -95,7 +95,8 @@ class QPDF @@ -95,7 +95,8 @@ class QPDF
95 95
96 // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except 96 // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except
97 // that the PDF file is in memory instead of on disk. The description appears in any warning or 97 // that the PDF file is in memory instead of on disk. The description appears in any warning or
98 - // error message in place of the file name. 98 + // error message in place of the file name. The buffer is owned by the caller and must remain
  99 + // valid for the lifetime of the QPDF object.
99 QPDF_DLL 100 QPDF_DLL
100 void processMemoryFile( 101 void processMemoryFile(
101 char const* description, char const* buf, size_t length, char const* password = nullptr); 102 char const* description, char const* buf, size_t length, char const* password = nullptr);
include/qpdf/QPDFObjectHandle.hh
@@ -1351,7 +1351,7 @@ class QPDFObjectHandle: public qpdf::BaseHandle @@ -1351,7 +1351,7 @@ class QPDFObjectHandle: public qpdf::BaseHandle
1351 void setParsedOffset(qpdf_offset_t offset); 1351 void setParsedOffset(qpdf_offset_t offset);
1352 void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); 1352 void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
1353 static void parseContentStream_data( 1353 static void parseContentStream_data(
1354 - std::shared_ptr<Buffer>, 1354 + std::string_view stream_data,
1355 std::string const& description, 1355 std::string const& description,
1356 ParserCallbacks* callbacks, 1356 ParserCallbacks* callbacks,
1357 QPDF* context); 1357 QPDF* context);
libqpdf/BufferInputSource.cc
1 #include <qpdf/BufferInputSource.hh> 1 #include <qpdf/BufferInputSource.hh>
  2 +#include <qpdf/InputSource_private.hh>
2 3
  4 +#include <qpdf/Buffer.hh>
3 #include <qpdf/QIntC.hh> 5 #include <qpdf/QIntC.hh>
  6 +
4 #include <algorithm> 7 #include <algorithm>
5 #include <cstring> 8 #include <cstring>
6 #include <sstream> 9 #include <sstream>
7 10
  11 +using namespace qpdf;
  12 +
  13 +#ifndef QPDF_FUTURE
  14 +
8 BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) : 15 BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) :
9 own_memory(own_memory), 16 own_memory(own_memory),
10 description(description), 17 description(description),
@@ -139,3 +146,166 @@ BufferInputSource::unreadCh(char ch) @@ -139,3 +146,166 @@ BufferInputSource::unreadCh(char ch)
139 --cur_offset; 146 --cur_offset;
140 } 147 }
141 } 148 }
  149 +
  150 +#else
  151 +
  152 +class BufferInputSource::Members
  153 +{
  154 + public:
  155 + Members(std::string const& description, Buffer* buf, bool own_memory) :
  156 + buf(own_memory ? buf : nullptr),
  157 + is(description,
  158 + buf && buf->getSize() > 0
  159 + ? std::string_view(reinterpret_cast<const char*>(buf->getBuffer()), buf->getSize())
  160 + : std::string_view())
  161 + {
  162 + }
  163 +
  164 + Members(std::string const& description, std::string const& str) :
  165 + content(str),
  166 + is(description, content)
  167 + {
  168 + }
  169 +
  170 + ~Members() = default;
  171 +
  172 + std::unique_ptr<Buffer> buf{nullptr};
  173 + std::string content;
  174 + is::OffsetBuffer is;
  175 +};
  176 +
  177 +BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) :
  178 + m(std::make_unique<Members>(description, buf, own_memory))
  179 +{
  180 +}
  181 +
  182 +BufferInputSource::BufferInputSource(std::string const& description, std::string const& contents) :
  183 + m(std::make_unique<Members>(description, contents))
  184 +{
  185 +}
  186 +BufferInputSource::~BufferInputSource() = default;
  187 +
  188 +qpdf_offset_t
  189 +BufferInputSource::findAndSkipNextEOL()
  190 +{
  191 + auto result = m->is.findAndSkipNextEOL();
  192 + last_offset = m->is.getLastOffset();
  193 + return result;
  194 +}
  195 +std::string const&
  196 +BufferInputSource::getName() const
  197 +{
  198 + return m->is.getName();
  199 +}
  200 +qpdf_offset_t
  201 +BufferInputSource::tell()
  202 +{
  203 + return m->is.tell();
  204 +}
  205 +void
  206 +BufferInputSource::seek(qpdf_offset_t offset, int whence)
  207 +{
  208 + m->is.seek(offset, whence);
  209 +}
  210 +void
  211 +BufferInputSource::rewind()
  212 +{
  213 + m->is.rewind();
  214 +}
  215 +size_t
  216 +BufferInputSource::read(char* buffer, size_t length)
  217 +{
  218 + auto result = m->is.read(buffer, length);
  219 + last_offset = m->is.getLastOffset();
  220 + return result;
  221 +}
  222 +void
  223 +BufferInputSource::unreadCh(char ch)
  224 +{
  225 + m->is.unreadCh(ch);
  226 +}
  227 +
  228 +#endif // QPDF_FUTURE
  229 +
  230 +qpdf_offset_t
  231 +is::OffsetBuffer::findAndSkipNextEOL()
  232 +{
  233 + if (pos < 0) {
  234 + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0");
  235 + }
  236 + auto end_pos = static_cast<qpdf_offset_t>(view_.size());
  237 + if (pos >= end_pos) {
  238 + last_offset = end_pos + global_offset;
  239 + pos = end_pos;
  240 + return end_pos + global_offset;
  241 + }
  242 +
  243 + qpdf_offset_t result = 0;
  244 + auto buffer = view_.begin();
  245 + auto end = view_.end();
  246 + auto p = buffer + static_cast<std::ptrdiff_t>(pos);
  247 +
  248 + while (p < end && !(*p == '\r' || *p == '\n')) {
  249 + ++p;
  250 + }
  251 + if (p < end) {
  252 + result = p - buffer;
  253 + pos = result + 1;
  254 + ++p;
  255 + while (pos < end_pos && (*p == '\r' || *p == '\n')) {
  256 + ++p;
  257 + ++pos;
  258 + }
  259 + } else {
  260 + pos = end_pos;
  261 + result = end_pos;
  262 + }
  263 + return result + global_offset;
  264 +}
  265 +
  266 +void
  267 +is::OffsetBuffer::seek(qpdf_offset_t offset, int whence)
  268 +{
  269 + switch (whence) {
  270 + case SEEK_SET:
  271 + pos = offset - global_offset;
  272 + break;
  273 +
  274 + case SEEK_END:
  275 + QIntC::range_check(static_cast<qpdf_offset_t>(view_.size()), offset);
  276 + pos = static_cast<qpdf_offset_t>(view_.size()) + offset;
  277 + break;
  278 +
  279 + case SEEK_CUR:
  280 + QIntC::range_check(pos, offset);
  281 + pos += offset;
  282 + break;
  283 +
  284 + default:
  285 + throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek");
  286 + break;
  287 + }
  288 +
  289 + if (pos < 0) {
  290 + throw std::runtime_error(description + ": seek before beginning of buffer");
  291 + }
  292 +}
  293 +
  294 +size_t
  295 +is::OffsetBuffer::read(char* buffer, size_t length)
  296 +{
  297 + if (pos < 0) {
  298 + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0");
  299 + }
  300 + auto end_pos = static_cast<qpdf_offset_t>(view_.size());
  301 + if (pos >= end_pos) {
  302 + last_offset = end_pos + global_offset;
  303 + return 0;
  304 + }
  305 +
  306 + last_offset = pos + global_offset;
  307 + size_t len = std::min(QIntC::to_size(end_pos - pos), length);
  308 + memcpy(buffer, view_.data() + pos, len);
  309 + pos += QIntC::to_offset(len);
  310 + return len;
  311 +}
libqpdf/JSON.cc
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 #include <qpdf/JSON_writer.hh> 3 #include <qpdf/JSON_writer.hh>
4 4
5 -#include <qpdf/BufferInputSource.hh> 5 +#include <qpdf/InputSource_private.hh>
6 #include <qpdf/Pl_Base64.hh> 6 #include <qpdf/Pl_Base64.hh>
7 #include <qpdf/Pl_Concatenate.hh> 7 #include <qpdf/Pl_Concatenate.hh>
8 #include <qpdf/Pl_String.hh> 8 #include <qpdf/Pl_String.hh>
@@ -1348,7 +1348,7 @@ JSON::parse(InputSource&amp; is, Reactor* reactor) @@ -1348,7 +1348,7 @@ JSON::parse(InputSource&amp; is, Reactor* reactor)
1348 JSON 1348 JSON
1349 JSON::parse(std::string const& s) 1349 JSON::parse(std::string const& s)
1350 { 1350 {
1351 - BufferInputSource bis("json input", s); 1351 + is::OffsetBuffer bis("json input", s);
1352 JSONParser jp(bis, nullptr); 1352 JSONParser jp(bis, nullptr);
1353 return jp.parse(); 1353 return jp.parse();
1354 } 1354 }
libqpdf/Pl_QPDFTokenizer.cc
1 #include <qpdf/Pl_QPDFTokenizer.hh> 1 #include <qpdf/Pl_QPDFTokenizer.hh>
2 2
3 -#include <qpdf/BufferInputSource.hh> 3 +#include <qpdf/InputSource_private.hh>
  4 +#include <qpdf/Pipeline_private.hh>
4 #include <qpdf/QTC.hh> 5 #include <qpdf/QTC.hh>
  6 +
5 #include <stdexcept> 7 #include <stdexcept>
6 8
  9 +using namespace qpdf;
  10 +
7 class Pl_QPDFTokenizer::Members 11 class Pl_QPDFTokenizer::Members
8 { 12 {
9 public: 13 public:
@@ -13,7 +17,8 @@ class Pl_QPDFTokenizer::Members @@ -13,7 +17,8 @@ class Pl_QPDFTokenizer::Members
13 17
14 QPDFObjectHandle::TokenFilter* filter{nullptr}; 18 QPDFObjectHandle::TokenFilter* filter{nullptr};
15 QPDFTokenizer tokenizer; 19 QPDFTokenizer tokenizer;
16 - Pl_Buffer buf{"tokenizer buffer"}; 20 + std::string buffer;
  21 + pl::String buf{"pl_tokenizer", nullptr, buffer};
17 }; 22 };
18 23
19 Pl_QPDFTokenizer::Pl_QPDFTokenizer( 24 Pl_QPDFTokenizer::Pl_QPDFTokenizer(
@@ -39,8 +44,7 @@ Pl_QPDFTokenizer::write(unsigned char const* data, size_t len) @@ -39,8 +44,7 @@ Pl_QPDFTokenizer::write(unsigned char const* data, size_t len)
39 void 44 void
40 Pl_QPDFTokenizer::finish() 45 Pl_QPDFTokenizer::finish()
41 { 46 {
42 - m->buf.finish();  
43 - auto input = BufferInputSource("tokenizer data", m->buf.getBuffer(), true); 47 + auto input = is::OffsetBuffer("tokenizer data", m->buffer);
44 std::string empty; 48 std::string empty;
45 while (true) { 49 while (true) {
46 auto token = m->tokenizer.readToken(input, empty, true); 50 auto token = m->tokenizer.readToken(input, empty, true);
libqpdf/QPDF.cc
@@ -11,7 +11,6 @@ @@ -11,7 +11,6 @@
11 #include <sstream> 11 #include <sstream>
12 #include <vector> 12 #include <vector>
13 13
14 -#include <qpdf/BufferInputSource.hh>  
15 #include <qpdf/FileInputSource.hh> 14 #include <qpdf/FileInputSource.hh>
16 #include <qpdf/InputSource_private.hh> 15 #include <qpdf/InputSource_private.hh>
17 #include <qpdf/OffsetInputSource.hh> 16 #include <qpdf/OffsetInputSource.hh>
@@ -259,12 +258,8 @@ void @@ -259,12 +258,8 @@ void
259 QPDF::processMemoryFile( 258 QPDF::processMemoryFile(
260 char const* description, char const* buf, size_t length, char const* password) 259 char const* description, char const* buf, size_t length, char const* password)
261 { 260 {
262 - processInputSource(  
263 - std::shared_ptr<InputSource>(  
264 - // line-break  
265 - new BufferInputSource(  
266 - description, new Buffer(QUtil::unsigned_char_pointer(buf), length), true)),  
267 - password); 261 + auto is = std::make_shared<is::OffsetBuffer>(description, std::string_view{buf, length});
  262 + processInputSource(is, password);
268 } 263 }
269 264
270 void 265 void
libqpdf/QPDFObjectHandle.cc
@@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
2 2
3 #include <qpdf/QPDFObjectHandle_private.hh> 3 #include <qpdf/QPDFObjectHandle_private.hh>
4 4
5 -#include <qpdf/InputSource_private.hh>  
6 #include <qpdf/JSON_writer.hh> 5 #include <qpdf/JSON_writer.hh>
7 #include <qpdf/Pipeline_private.hh> 6 #include <qpdf/Pipeline_private.hh>
8 #include <qpdf/Pl_Buffer.hh> 7 #include <qpdf/Pl_Buffer.hh>
@@ -1452,10 +1451,7 @@ QPDFObjectHandle @@ -1452,10 +1451,7 @@ QPDFObjectHandle
1452 QPDFObjectHandle::parse( 1451 QPDFObjectHandle::parse(
1453 QPDF* context, std::string const& object_str, std::string const& object_description) 1452 QPDF* context, std::string const& object_str, std::string const& object_description)
1454 { 1453 {
1455 - // BufferInputSource does not modify the input, but Buffer either requires a string& or copies  
1456 - // the string.  
1457 - Buffer buf(const_cast<std::string&>(object_str));  
1458 - auto input = BufferInputSource("parsed object", &buf); 1454 + auto input = is::OffsetBuffer("parsed object", object_str);
1459 auto result = QPDFParser::parse(input, object_description, context); 1455 auto result = QPDFParser::parse(input, object_description, context);
1460 size_t offset = QIntC::to_size(input.tell()); 1456 size_t offset = QIntC::to_size(input.tell());
1461 while (offset < object_str.length()) { 1457 while (offset < object_str.length()) {
@@ -1549,11 +1545,11 @@ void @@ -1549,11 +1545,11 @@ void
1549 QPDFObjectHandle::parseContentStream_internal( 1545 QPDFObjectHandle::parseContentStream_internal(
1550 std::string const& description, ParserCallbacks* callbacks) 1546 std::string const& description, ParserCallbacks* callbacks)
1551 { 1547 {
1552 - Pl_Buffer buf("concatenated stream data buffer"); 1548 + std::string stream_data;
  1549 + pl::String buf(stream_data);
1553 std::string all_description; 1550 std::string all_description;
1554 pipeContentStreams(&buf, description, all_description); 1551 pipeContentStreams(&buf, description, all_description);
1555 - auto stream_data = buf.getBufferSharedPointer();  
1556 - callbacks->contentSize(stream_data->getSize()); 1552 + callbacks->contentSize(stream_data.size());
1557 try { 1553 try {
1558 parseContentStream_data(stream_data, all_description, callbacks, getOwningQPDF()); 1554 parseContentStream_data(stream_data, all_description, callbacks, getOwningQPDF());
1559 } catch (TerminateParsing&) { 1555 } catch (TerminateParsing&) {
@@ -1564,13 +1560,13 @@ QPDFObjectHandle::parseContentStream_internal( @@ -1564,13 +1560,13 @@ QPDFObjectHandle::parseContentStream_internal(
1564 1560
1565 void 1561 void
1566 QPDFObjectHandle::parseContentStream_data( 1562 QPDFObjectHandle::parseContentStream_data(
1567 - std::shared_ptr<Buffer> stream_data, 1563 + std::string_view stream_data,
1568 std::string const& description, 1564 std::string const& description,
1569 ParserCallbacks* callbacks, 1565 ParserCallbacks* callbacks,
1570 QPDF* context) 1566 QPDF* context)
1571 { 1567 {
1572 - size_t stream_length = stream_data->getSize();  
1573 - auto input = BufferInputSource(description, stream_data.get()); 1568 + size_t stream_length = stream_data.size();
  1569 + auto input = is::OffsetBuffer(description, stream_data);
1574 Tokenizer tokenizer; 1570 Tokenizer tokenizer;
1575 tokenizer.allowEOF(); 1571 tokenizer.allowEOF();
1576 auto sp_description = QPDFParser::make_description(description, "content"); 1572 auto sp_description = QPDFParser::make_description(description, "content");
libqpdf/QPDFParser.cc
1 #include <qpdf/QPDFParser.hh> 1 #include <qpdf/QPDFParser.hh>
2 2
3 -#include <qpdf/BufferInputSource.hh>  
4 #include <qpdf/QPDF.hh> 3 #include <qpdf/QPDF.hh>
5 #include <qpdf/QPDFObjGen.hh> 4 #include <qpdf/QPDFObjGen.hh>
6 #include <qpdf/QPDFObjectHandle.hh> 5 #include <qpdf/QPDFObjectHandle.hh>
libqpdf/QPDF_Stream.cc
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 #include <qpdf/ContentNormalizer.hh> 3 #include <qpdf/ContentNormalizer.hh>
4 #include <qpdf/JSON_writer.hh> 4 #include <qpdf/JSON_writer.hh>
5 #include <qpdf/Pipeline.hh> 5 #include <qpdf/Pipeline.hh>
  6 +#include <qpdf/Pipeline_private.hh>
6 #include <qpdf/Pl_Base64.hh> 7 #include <qpdf/Pl_Base64.hh>
7 #include <qpdf/Pl_Buffer.hh> 8 #include <qpdf/Pl_Buffer.hh>
8 #include <qpdf/Pl_Count.hh> 9 #include <qpdf/Pl_Count.hh>
@@ -319,10 +320,11 @@ qpdf::Stream::setDictDescription() @@ -319,10 +320,11 @@ qpdf::Stream::setDictDescription()
319 } 320 }
320 } 321 }
321 322
322 -std::shared_ptr<Buffer> 323 +std::string
323 Stream::getStreamData(qpdf_stream_decode_level_e decode_level) 324 Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
324 { 325 {
325 - Pl_Buffer buf("stream data buffer"); 326 + std::string result;
  327 + pl::String buf(result);
326 bool filtered; 328 bool filtered;
327 pipeStreamData(&buf, &filtered, 0, decode_level, false, false); 329 pipeStreamData(&buf, &filtered, 0, decode_level, false, false);
328 if (!filtered) { 330 if (!filtered) {
@@ -334,13 +336,14 @@ Stream::getStreamData(qpdf_stream_decode_level_e decode_level) @@ -334,13 +336,14 @@ Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
334 "getStreamData called on unfilterable stream"); 336 "getStreamData called on unfilterable stream");
335 } 337 }
336 QTC::TC("qpdf", "QPDF_Stream getStreamData"); 338 QTC::TC("qpdf", "QPDF_Stream getStreamData");
337 - return buf.getBufferSharedPointer(); 339 + return result;
338 } 340 }
339 341
340 -std::shared_ptr<Buffer> 342 +std::string
341 Stream::getRawStreamData() 343 Stream::getRawStreamData()
342 { 344 {
343 - Pl_Buffer buf("stream data buffer"); 345 + std::string result;
  346 + pl::String buf(result);
344 if (!pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false)) { 347 if (!pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false)) {
345 throw QPDFExc( 348 throw QPDFExc(
346 qpdf_e_unsupported, 349 qpdf_e_unsupported,
@@ -350,7 +353,7 @@ Stream::getRawStreamData() @@ -350,7 +353,7 @@ Stream::getRawStreamData()
350 "error getting raw stream data"); 353 "error getting raw stream data");
351 } 354 }
352 QTC::TC("qpdf", "QPDF_Stream getRawStreamData"); 355 QTC::TC("qpdf", "QPDF_Stream getRawStreamData");
353 - return buf.getBufferSharedPointer(); 356 + return result;
354 } 357 }
355 358
356 bool 359 bool
@@ -683,13 +686,13 @@ QPDFObjectHandle::isRootMetadata() const @@ -683,13 +686,13 @@ QPDFObjectHandle::isRootMetadata() const
683 std::shared_ptr<Buffer> 686 std::shared_ptr<Buffer>
684 QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) 687 QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level)
685 { 688 {
686 - return as_stream(error).getStreamData(level); 689 + return std::make_shared<Buffer>(as_stream(error).getStreamData(level));
687 } 690 }
688 691
689 std::shared_ptr<Buffer> 692 std::shared_ptr<Buffer>
690 QPDFObjectHandle::getRawStreamData() 693 QPDFObjectHandle::getRawStreamData()
691 { 694 {
692 - return as_stream(error).getRawStreamData(); 695 + return std::make_shared<Buffer>(as_stream(error).getRawStreamData());
693 } 696 }
694 697
695 bool 698 bool
libqpdf/QPDF_objects.cc
@@ -2,19 +2,7 @@ @@ -2,19 +2,7 @@
2 2
3 #include <qpdf/QPDF_private.hh> 3 #include <qpdf/QPDF_private.hh>
4 4
5 -#include <array>  
6 -#include <atomic>  
7 -#include <cstring>  
8 -#include <limits>  
9 -#include <map>  
10 -#include <regex>  
11 -#include <sstream>  
12 -#include <vector>  
13 -  
14 -#include <qpdf/BufferInputSource.hh>  
15 -#include <qpdf/FileInputSource.hh>  
16 #include <qpdf/InputSource_private.hh> 5 #include <qpdf/InputSource_private.hh>
17 -#include <qpdf/OffsetInputSource.hh>  
18 #include <qpdf/Pipeline.hh> 6 #include <qpdf/Pipeline.hh>
19 #include <qpdf/QPDFExc.hh> 7 #include <qpdf/QPDFExc.hh>
20 #include <qpdf/QPDFLogger.hh> 8 #include <qpdf/QPDFLogger.hh>
@@ -25,6 +13,13 @@ @@ -25,6 +13,13 @@
25 #include <qpdf/QUtil.hh> 13 #include <qpdf/QUtil.hh>
26 #include <qpdf/Util.hh> 14 #include <qpdf/Util.hh>
27 15
  16 +#include <array>
  17 +#include <atomic>
  18 +#include <cstring>
  19 +#include <limits>
  20 +#include <map>
  21 +#include <vector>
  22 +
28 using namespace qpdf; 23 using namespace qpdf;
29 using namespace std::literals; 24 using namespace std::literals;
30 25
@@ -1676,13 +1671,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1676,13 +1671,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1676 // id, offset, size 1671 // id, offset, size
1677 std::vector<std::tuple<int, qpdf_offset_t, size_t>> offsets; 1672 std::vector<std::tuple<int, qpdf_offset_t, size_t>> offsets;
1678 1673
1679 - auto bp = obj_stream.getStreamData(qpdf_dl_specialized); 1674 + auto stream_data = obj_stream.getStreamData(qpdf_dl_specialized);
1680 1675
1681 - BufferInputSource input("", bp.get()); 1676 + is::OffsetBuffer input("", stream_data);
1682 1677
1683 - const auto b_size = bp->getSize(); 1678 + const auto b_size = stream_data.size();
1684 const auto end_offset = static_cast<qpdf_offset_t>(b_size); 1679 const auto end_offset = static_cast<qpdf_offset_t>(b_size);
1685 - auto b_start = bp->getBuffer(); 1680 + auto b_start = stream_data.data();
1686 1681
1687 if (first >= end_offset) { 1682 if (first >= end_offset) {
1688 throw damagedPDF( 1683 throw damagedPDF(
@@ -1763,8 +1758,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1763,8 +1758,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1763 auto entry = m->xref_table.find(og); 1758 auto entry = m->xref_table.find(og);
1764 if (entry != m->xref_table.end() && entry->second.getType() == 2 && 1759 if (entry != m->xref_table.end() && entry->second.getType() == 2 &&
1765 entry->second.getObjStreamNumber() == obj_stream_number) { 1760 entry->second.getObjStreamNumber() == obj_stream_number) {
1766 - Buffer obj_buffer{b_start + obj_offset, obj_size};  
1767 - is::OffsetBuffer in("", &obj_buffer, obj_offset); 1761 + is::OffsetBuffer in("", {b_start + obj_offset, obj_size}, obj_offset);
1768 auto oh = readObjectInStream(in, obj_stream_number, obj_id); 1762 auto oh = readObjectInStream(in, obj_stream_number, obj_id);
1769 updateCache(og, oh.getObj(), end_before_space, end_after_space); 1763 updateCache(og, oh.getObj(), end_before_space, end_after_space);
1770 } else { 1764 } else {
libqpdf/qpdf/InputSource_private.hh
1 #ifndef QPDF_INPUTSOURCE_PRIVATE_HH 1 #ifndef QPDF_INPUTSOURCE_PRIVATE_HH
2 #define QPDF_INPUTSOURCE_PRIVATE_HH 2 #define QPDF_INPUTSOURCE_PRIVATE_HH
3 3
4 -#include <qpdf/BufferInputSource.hh> 4 +#include <qpdf/Buffer.hh>
5 #include <qpdf/InputSource.hh> 5 #include <qpdf/InputSource.hh>
6 6
7 #include <limits> 7 #include <limits>
@@ -13,8 +13,12 @@ namespace qpdf::is @@ -13,8 +13,12 @@ namespace qpdf::is
13 class OffsetBuffer final: public InputSource 13 class OffsetBuffer final: public InputSource
14 { 14 {
15 public: 15 public:
16 - OffsetBuffer(std::string const& description, Buffer* buf, qpdf_offset_t global_offset) :  
17 - proxied(description, buf), 16 + OffsetBuffer(
  17 + std::string const& description,
  18 + std::string_view view,
  19 + qpdf_offset_t global_offset = 0) :
  20 + description(description),
  21 + view_(view),
18 global_offset(global_offset) 22 global_offset(global_offset)
19 { 23 {
20 if (global_offset < 0) { 24 if (global_offset < 0) {
@@ -23,58 +27,55 @@ namespace qpdf::is @@ -23,58 +27,55 @@ namespace qpdf::is
23 last_offset = global_offset; 27 last_offset = global_offset;
24 } 28 }
25 29
26 - ~OffsetBuffer() final = default;  
27 -  
28 - qpdf_offset_t  
29 - findAndSkipNextEOL() final 30 + OffsetBuffer(std::string const& description, Buffer* buf, qpdf_offset_t global_offset = 0) :
  31 + OffsetBuffer(
  32 + description,
  33 + {buf && buf->getSize()
  34 + ? std::string_view(
  35 + reinterpret_cast<const char*>(buf->getBuffer()), buf->getSize())
  36 + : std::string_view()},
  37 + global_offset)
30 { 38 {
31 - return proxied.findAndSkipNextEOL() + global_offset;  
32 } 39 }
33 40
  41 + ~OffsetBuffer() final = default;
  42 +
  43 + qpdf_offset_t findAndSkipNextEOL() final;
  44 +
34 std::string const& 45 std::string const&
35 getName() const final 46 getName() const final
36 { 47 {
37 - return proxied.getName(); 48 + return description;
38 } 49 }
39 50
40 qpdf_offset_t 51 qpdf_offset_t
41 tell() final 52 tell() final
42 { 53 {
43 - return proxied.tell() + global_offset; 54 + return pos + global_offset;
44 } 55 }
45 56
46 - void  
47 - seek(qpdf_offset_t offset, int whence) final  
48 - {  
49 - if (whence == SEEK_SET) {  
50 - proxied.seek(offset - global_offset, whence);  
51 - } else {  
52 - proxied.seek(offset, whence);  
53 - }  
54 - } 57 + void seek(qpdf_offset_t offset, int whence) final;
55 58
56 void 59 void
57 rewind() final 60 rewind() final
58 { 61 {
59 - seek(0, SEEK_SET); 62 + pos = 0;
60 } 63 }
61 64
62 - size_t  
63 - read(char* buffer, size_t length) final  
64 - {  
65 - size_t result = proxied.read(buffer, length);  
66 - setLastOffset(proxied.getLastOffset() + global_offset);  
67 - return result;  
68 - } 65 + size_t read(char* buffer, size_t length) final;
69 66
70 void 67 void
71 unreadCh(char ch) final 68 unreadCh(char ch) final
72 { 69 {
73 - proxied.unreadCh(ch); 70 + if (pos > 0) {
  71 + --pos;
  72 + }
74 } 73 }
75 74
76 private: 75 private:
77 - BufferInputSource proxied; 76 + std::string description;
  77 + qpdf_offset_t pos{0};
  78 + std::string_view view_;
78 qpdf_offset_t global_offset; 79 qpdf_offset_t global_offset;
79 }; 80 };
80 81
libqpdf/qpdf/QPDFObjectHandle_private.hh
@@ -254,8 +254,8 @@ namespace qpdf @@ -254,8 +254,8 @@ namespace qpdf
254 qpdf_stream_decode_level_e decode_level, 254 qpdf_stream_decode_level_e decode_level,
255 bool suppress_warnings, 255 bool suppress_warnings,
256 bool will_retry); 256 bool will_retry);
257 - std::shared_ptr<Buffer> getStreamData(qpdf_stream_decode_level_e level);  
258 - std::shared_ptr<Buffer> getRawStreamData(); 257 + std::string getStreamData(qpdf_stream_decode_level_e level);
  258 + std::string getRawStreamData();
259 void replaceStreamData( 259 void replaceStreamData(
260 std::shared_ptr<Buffer> data, 260 std::shared_ptr<Buffer> data,
261 QPDFObjectHandle const& filter, 261 QPDFObjectHandle const& filter,