Commit ca80db6fc1fe96f3da234390ac27fdc8a0a1ec58
Committed by
GitHub
Merge pull request #1496 from m-holger/obis
Refactor is::OffsetBuffer and BufferInputSource
Showing
13 changed files
with
255 additions
and
84 deletions
include/qpdf/BufferInputSource.hh
| ... | ... | @@ -23,6 +23,8 @@ |
| 23 | 23 | #include <qpdf/Buffer.hh> |
| 24 | 24 | #include <qpdf/InputSource.hh> |
| 25 | 25 | |
| 26 | +#include <memory> | |
| 27 | + | |
| 26 | 28 | class QPDF_DLL_CLASS BufferInputSource: public InputSource |
| 27 | 29 | { |
| 28 | 30 | public: |
| ... | ... | @@ -52,11 +54,17 @@ class QPDF_DLL_CLASS BufferInputSource: public InputSource |
| 52 | 54 | void unreadCh(char ch) override; |
| 53 | 55 | |
| 54 | 56 | private: |
| 57 | +#ifndef QPDF_FUTURE | |
| 55 | 58 | bool own_memory; |
| 56 | 59 | std::string description; |
| 57 | 60 | Buffer* buf; |
| 58 | 61 | qpdf_offset_t cur_offset; |
| 59 | 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 | 70 | #endif // QPDF_BUFFERINPUTSOURCE_HH | ... | ... |
include/qpdf/QPDF.hh
| ... | ... | @@ -95,7 +95,8 @@ class QPDF |
| 95 | 95 | |
| 96 | 96 | // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except |
| 97 | 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 | 100 | QPDF_DLL |
| 100 | 101 | void processMemoryFile( |
| 101 | 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 | 1351 | void setParsedOffset(qpdf_offset_t offset); |
| 1352 | 1352 | void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); |
| 1353 | 1353 | static void parseContentStream_data( |
| 1354 | - std::shared_ptr<Buffer>, | |
| 1354 | + std::string_view stream_data, | |
| 1355 | 1355 | std::string const& description, |
| 1356 | 1356 | ParserCallbacks* callbacks, |
| 1357 | 1357 | QPDF* context); | ... | ... |
libqpdf/BufferInputSource.cc
| 1 | 1 | #include <qpdf/BufferInputSource.hh> |
| 2 | +#include <qpdf/InputSource_private.hh> | |
| 2 | 3 | |
| 4 | +#include <qpdf/Buffer.hh> | |
| 3 | 5 | #include <qpdf/QIntC.hh> |
| 6 | + | |
| 4 | 7 | #include <algorithm> |
| 5 | 8 | #include <cstring> |
| 6 | 9 | #include <sstream> |
| 7 | 10 | |
| 11 | +using namespace qpdf; | |
| 12 | + | |
| 13 | +#ifndef QPDF_FUTURE | |
| 14 | + | |
| 8 | 15 | BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) : |
| 9 | 16 | own_memory(own_memory), |
| 10 | 17 | description(description), |
| ... | ... | @@ -139,3 +146,166 @@ BufferInputSource::unreadCh(char ch) |
| 139 | 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 | 2 | |
| 3 | 3 | #include <qpdf/JSON_writer.hh> |
| 4 | 4 | |
| 5 | -#include <qpdf/BufferInputSource.hh> | |
| 5 | +#include <qpdf/InputSource_private.hh> | |
| 6 | 6 | #include <qpdf/Pl_Base64.hh> |
| 7 | 7 | #include <qpdf/Pl_Concatenate.hh> |
| 8 | 8 | #include <qpdf/Pl_String.hh> |
| ... | ... | @@ -1348,7 +1348,7 @@ JSON::parse(InputSource& is, Reactor* reactor) |
| 1348 | 1348 | JSON |
| 1349 | 1349 | JSON::parse(std::string const& s) |
| 1350 | 1350 | { |
| 1351 | - BufferInputSource bis("json input", s); | |
| 1351 | + is::OffsetBuffer bis("json input", s); | |
| 1352 | 1352 | JSONParser jp(bis, nullptr); |
| 1353 | 1353 | return jp.parse(); |
| 1354 | 1354 | } | ... | ... |
libqpdf/Pl_QPDFTokenizer.cc
| 1 | 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 | 5 | #include <qpdf/QTC.hh> |
| 6 | + | |
| 5 | 7 | #include <stdexcept> |
| 6 | 8 | |
| 9 | +using namespace qpdf; | |
| 10 | + | |
| 7 | 11 | class Pl_QPDFTokenizer::Members |
| 8 | 12 | { |
| 9 | 13 | public: |
| ... | ... | @@ -13,7 +17,8 @@ class Pl_QPDFTokenizer::Members |
| 13 | 17 | |
| 14 | 18 | QPDFObjectHandle::TokenFilter* filter{nullptr}; |
| 15 | 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 | 24 | Pl_QPDFTokenizer::Pl_QPDFTokenizer( |
| ... | ... | @@ -39,8 +44,7 @@ Pl_QPDFTokenizer::write(unsigned char const* data, size_t len) |
| 39 | 44 | void |
| 40 | 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 | 48 | std::string empty; |
| 45 | 49 | while (true) { |
| 46 | 50 | auto token = m->tokenizer.readToken(input, empty, true); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -11,7 +11,6 @@ |
| 11 | 11 | #include <sstream> |
| 12 | 12 | #include <vector> |
| 13 | 13 | |
| 14 | -#include <qpdf/BufferInputSource.hh> | |
| 15 | 14 | #include <qpdf/FileInputSource.hh> |
| 16 | 15 | #include <qpdf/InputSource_private.hh> |
| 17 | 16 | #include <qpdf/OffsetInputSource.hh> |
| ... | ... | @@ -259,12 +258,8 @@ void |
| 259 | 258 | QPDF::processMemoryFile( |
| 260 | 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 | 265 | void | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 4 | 4 | |
| 5 | -#include <qpdf/InputSource_private.hh> | |
| 6 | 5 | #include <qpdf/JSON_writer.hh> |
| 7 | 6 | #include <qpdf/Pipeline_private.hh> |
| 8 | 7 | #include <qpdf/Pl_Buffer.hh> |
| ... | ... | @@ -1452,10 +1451,7 @@ QPDFObjectHandle |
| 1452 | 1451 | QPDFObjectHandle::parse( |
| 1453 | 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 | 1455 | auto result = QPDFParser::parse(input, object_description, context); |
| 1460 | 1456 | size_t offset = QIntC::to_size(input.tell()); |
| 1461 | 1457 | while (offset < object_str.length()) { |
| ... | ... | @@ -1549,11 +1545,11 @@ void |
| 1549 | 1545 | QPDFObjectHandle::parseContentStream_internal( |
| 1550 | 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 | 1550 | std::string all_description; |
| 1554 | 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 | 1553 | try { |
| 1558 | 1554 | parseContentStream_data(stream_data, all_description, callbacks, getOwningQPDF()); |
| 1559 | 1555 | } catch (TerminateParsing&) { |
| ... | ... | @@ -1564,13 +1560,13 @@ QPDFObjectHandle::parseContentStream_internal( |
| 1564 | 1560 | |
| 1565 | 1561 | void |
| 1566 | 1562 | QPDFObjectHandle::parseContentStream_data( |
| 1567 | - std::shared_ptr<Buffer> stream_data, | |
| 1563 | + std::string_view stream_data, | |
| 1568 | 1564 | std::string const& description, |
| 1569 | 1565 | ParserCallbacks* callbacks, |
| 1570 | 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 | 1570 | Tokenizer tokenizer; |
| 1575 | 1571 | tokenizer.allowEOF(); |
| 1576 | 1572 | auto sp_description = QPDFParser::make_description(description, "content"); | ... | ... |
libqpdf/QPDFParser.cc
libqpdf/QPDF_Stream.cc
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | #include <qpdf/ContentNormalizer.hh> |
| 4 | 4 | #include <qpdf/JSON_writer.hh> |
| 5 | 5 | #include <qpdf/Pipeline.hh> |
| 6 | +#include <qpdf/Pipeline_private.hh> | |
| 6 | 7 | #include <qpdf/Pl_Base64.hh> |
| 7 | 8 | #include <qpdf/Pl_Buffer.hh> |
| 8 | 9 | #include <qpdf/Pl_Count.hh> |
| ... | ... | @@ -319,10 +320,11 @@ qpdf::Stream::setDictDescription() |
| 319 | 320 | } |
| 320 | 321 | } |
| 321 | 322 | |
| 322 | -std::shared_ptr<Buffer> | |
| 323 | +std::string | |
| 323 | 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 | 328 | bool filtered; |
| 327 | 329 | pipeStreamData(&buf, &filtered, 0, decode_level, false, false); |
| 328 | 330 | if (!filtered) { |
| ... | ... | @@ -334,13 +336,14 @@ Stream::getStreamData(qpdf_stream_decode_level_e decode_level) |
| 334 | 336 | "getStreamData called on unfilterable stream"); |
| 335 | 337 | } |
| 336 | 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 | 343 | Stream::getRawStreamData() |
| 342 | 344 | { |
| 343 | - Pl_Buffer buf("stream data buffer"); | |
| 345 | + std::string result; | |
| 346 | + pl::String buf(result); | |
| 344 | 347 | if (!pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false)) { |
| 345 | 348 | throw QPDFExc( |
| 346 | 349 | qpdf_e_unsupported, |
| ... | ... | @@ -350,7 +353,7 @@ Stream::getRawStreamData() |
| 350 | 353 | "error getting raw stream data"); |
| 351 | 354 | } |
| 352 | 355 | QTC::TC("qpdf", "QPDF_Stream getRawStreamData"); |
| 353 | - return buf.getBufferSharedPointer(); | |
| 356 | + return result; | |
| 354 | 357 | } |
| 355 | 358 | |
| 356 | 359 | bool |
| ... | ... | @@ -683,13 +686,13 @@ QPDFObjectHandle::isRootMetadata() const |
| 683 | 686 | std::shared_ptr<Buffer> |
| 684 | 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 | 692 | std::shared_ptr<Buffer> |
| 690 | 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 | 698 | bool | ... | ... |
libqpdf/QPDF_objects.cc
| ... | ... | @@ -2,19 +2,7 @@ |
| 2 | 2 | |
| 3 | 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 | 5 | #include <qpdf/InputSource_private.hh> |
| 17 | -#include <qpdf/OffsetInputSource.hh> | |
| 18 | 6 | #include <qpdf/Pipeline.hh> |
| 19 | 7 | #include <qpdf/QPDFExc.hh> |
| 20 | 8 | #include <qpdf/QPDFLogger.hh> |
| ... | ... | @@ -25,6 +13,13 @@ |
| 25 | 13 | #include <qpdf/QUtil.hh> |
| 26 | 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 | 23 | using namespace qpdf; |
| 29 | 24 | using namespace std::literals; |
| 30 | 25 | |
| ... | ... | @@ -1676,13 +1671,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number) |
| 1676 | 1671 | // id, offset, size |
| 1677 | 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 | 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 | 1682 | if (first >= end_offset) { |
| 1688 | 1683 | throw damagedPDF( |
| ... | ... | @@ -1763,8 +1758,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) |
| 1763 | 1758 | auto entry = m->xref_table.find(og); |
| 1764 | 1759 | if (entry != m->xref_table.end() && entry->second.getType() == 2 && |
| 1765 | 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 | 1762 | auto oh = readObjectInStream(in, obj_stream_number, obj_id); |
| 1769 | 1763 | updateCache(og, oh.getObj(), end_before_space, end_after_space); |
| 1770 | 1764 | } else { | ... | ... |
libqpdf/qpdf/InputSource_private.hh
| 1 | 1 | #ifndef QPDF_INPUTSOURCE_PRIVATE_HH |
| 2 | 2 | #define QPDF_INPUTSOURCE_PRIVATE_HH |
| 3 | 3 | |
| 4 | -#include <qpdf/BufferInputSource.hh> | |
| 4 | +#include <qpdf/Buffer.hh> | |
| 5 | 5 | #include <qpdf/InputSource.hh> |
| 6 | 6 | |
| 7 | 7 | #include <limits> |
| ... | ... | @@ -13,8 +13,12 @@ namespace qpdf::is |
| 13 | 13 | class OffsetBuffer final: public InputSource |
| 14 | 14 | { |
| 15 | 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 | 22 | global_offset(global_offset) |
| 19 | 23 | { |
| 20 | 24 | if (global_offset < 0) { |
| ... | ... | @@ -23,58 +27,55 @@ namespace qpdf::is |
| 23 | 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 | 45 | std::string const& |
| 35 | 46 | getName() const final |
| 36 | 47 | { |
| 37 | - return proxied.getName(); | |
| 48 | + return description; | |
| 38 | 49 | } |
| 39 | 50 | |
| 40 | 51 | qpdf_offset_t |
| 41 | 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 | 59 | void |
| 57 | 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 | 67 | void |
| 71 | 68 | unreadCh(char ch) final |
| 72 | 69 | { |
| 73 | - proxied.unreadCh(ch); | |
| 70 | + if (pos > 0) { | |
| 71 | + --pos; | |
| 72 | + } | |
| 74 | 73 | } |
| 75 | 74 | |
| 76 | 75 | private: |
| 77 | - BufferInputSource proxied; | |
| 76 | + std::string description; | |
| 77 | + qpdf_offset_t pos{0}; | |
| 78 | + std::string_view view_; | |
| 78 | 79 | qpdf_offset_t global_offset; |
| 79 | 80 | }; |
| 80 | 81 | ... | ... |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| ... | ... | @@ -254,8 +254,8 @@ namespace qpdf |
| 254 | 254 | qpdf_stream_decode_level_e decode_level, |
| 255 | 255 | bool suppress_warnings, |
| 256 | 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 | 259 | void replaceStreamData( |
| 260 | 260 | std::shared_ptr<Buffer> data, |
| 261 | 261 | QPDFObjectHandle const& filter, | ... | ... |