From 81cb79620a361d7047c72be27d1ede48d5da4e93 Mon Sep 17 00:00:00 2001 From: m-holger Date: Wed, 4 Jun 2025 10:38:05 +0100 Subject: [PATCH] Refactor `is::OffsetBuffer` to remove dependency on `BufferInputSource`, improving encapsulation and maintainability. --- libqpdf/BufferInputSource.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ libqpdf/QPDFObjectHandle.cc | 2 +- libqpdf/qpdf/InputSource_private.hh | 38 +++++++++++++++++++++----------------- 3 files changed, 110 insertions(+), 18 deletions(-) diff --git a/libqpdf/BufferInputSource.cc b/libqpdf/BufferInputSource.cc index dae96f8..e124854 100644 --- a/libqpdf/BufferInputSource.cc +++ b/libqpdf/BufferInputSource.cc @@ -1,10 +1,15 @@ #include +#include +#include #include + #include #include #include +using namespace qpdf; + BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) : own_memory(own_memory), description(description), @@ -139,3 +144,86 @@ BufferInputSource::unreadCh(char ch) --cur_offset; } } + +qpdf_offset_t +is::OffsetBuffer::findAndSkipNextEOL_internal() +{ + if (cur_offset < 0) { + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); + } + qpdf_offset_t end_pos = max_offset; + if (cur_offset >= end_pos) { + last_offset = end_pos + global_offset; + cur_offset = end_pos; + return end_pos; + } + + qpdf_offset_t result = 0; + unsigned char const* buffer = buf->getBuffer(); + unsigned char const* end = buffer + end_pos; + unsigned char const* p = buffer + cur_offset; + + while (p < end && !(*p == '\r' || *p == '\n')) { + ++p; + } + if (p < end) { + result = p - buffer; + cur_offset = result + 1; + ++p; + while (cur_offset < end_pos && (*p == '\r' || *p == '\n')) { + ++p; + ++cur_offset; + } + } else { + cur_offset = end_pos; + result = end_pos; + } + return result; +} + +void +is::OffsetBuffer::seek_internal(qpdf_offset_t offset, int whence) +{ + switch (whence) { + case SEEK_SET: + cur_offset = offset; + break; + + case SEEK_END: + QIntC::range_check(max_offset, offset); + cur_offset = max_offset + offset; + break; + + case SEEK_CUR: + QIntC::range_check(cur_offset, offset); + cur_offset += offset; + break; + + default: + throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek"); + break; + } + + if (cur_offset < 0) { + throw std::runtime_error(description + ": seek before beginning of buffer"); + } +} + +size_t +is::OffsetBuffer::read(char* buffer, size_t length) +{ + if (cur_offset < 0) { + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); + } + qpdf_offset_t end_pos = max_offset; + if (cur_offset >= end_pos) { + last_offset = end_pos + global_offset; + return 0; + } + + last_offset = cur_offset + global_offset; + size_t len = std::min(QIntC::to_size(end_pos - cur_offset), length); + memcpy(buffer, buf->getBuffer() + cur_offset, len); + cur_offset += QIntC::to_offset(len); + return len; +} diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 440e3e5..84d88d3 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -2,7 +2,7 @@ #include -#include +#include #include #include #include diff --git a/libqpdf/qpdf/InputSource_private.hh b/libqpdf/qpdf/InputSource_private.hh index 00d27c9..84ecc75 100644 --- a/libqpdf/qpdf/InputSource_private.hh +++ b/libqpdf/qpdf/InputSource_private.hh @@ -1,7 +1,7 @@ #ifndef QPDF_INPUTSOURCE_PRIVATE_HH #define QPDF_INPUTSOURCE_PRIVATE_HH -#include +#include #include #include @@ -14,7 +14,9 @@ namespace qpdf::is { public: OffsetBuffer(std::string const& description, Buffer* buf, qpdf_offset_t global_offset) : - proxied(description, buf), + description(description), + buf(buf), + max_offset(buf ? static_cast(buf->getSize()) : 0), global_offset(global_offset) { if (global_offset < 0) { @@ -28,53 +30,55 @@ namespace qpdf::is qpdf_offset_t findAndSkipNextEOL() final { - return proxied.findAndSkipNextEOL() + global_offset; + return findAndSkipNextEOL_internal() + global_offset; } std::string const& getName() const final { - return proxied.getName(); + return description; } qpdf_offset_t tell() final { - return proxied.tell() + global_offset; + return cur_offset + global_offset; } void seek(qpdf_offset_t offset, int whence) final { if (whence == SEEK_SET) { - proxied.seek(offset - global_offset, whence); + seek_internal(offset - global_offset, whence); } else { - proxied.seek(offset, whence); + seek_internal(offset, whence); } } void rewind() final { - seek(0, SEEK_SET); + seek_internal(0, SEEK_SET); } - size_t - read(char* buffer, size_t length) final - { - size_t result = proxied.read(buffer, length); - setLastOffset(proxied.getLastOffset() + global_offset); - return result; - } + size_t read(char* buffer, size_t length) final; void unreadCh(char ch) final { - proxied.unreadCh(ch); + if (cur_offset > 0) { + --cur_offset; + } } private: - BufferInputSource proxied; + qpdf_offset_t findAndSkipNextEOL_internal(); + void seek_internal(qpdf_offset_t offset, int whence); + + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset{0}; + qpdf_offset_t max_offset; qpdf_offset_t global_offset; }; -- libgit2 0.21.4