Commit 81cb79620a361d7047c72be27d1ede48d5da4e93
1 parent
3a055d5b
Refactor `is::OffsetBuffer` to remove dependency on `BufferInputSource`, improvi…
…ng encapsulation and maintainability.
Showing
3 changed files
with
110 additions
and
18 deletions
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 | + | |
| 8 | 13 | BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) : |
| 9 | 14 | own_memory(own_memory), |
| 10 | 15 | description(description), |
| ... | ... | @@ -139,3 +144,86 @@ BufferInputSource::unreadCh(char ch) |
| 139 | 144 | --cur_offset; |
| 140 | 145 | } |
| 141 | 146 | } |
| 147 | + | |
| 148 | +qpdf_offset_t | |
| 149 | +is::OffsetBuffer::findAndSkipNextEOL_internal() | |
| 150 | +{ | |
| 151 | + if (cur_offset < 0) { | |
| 152 | + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); | |
| 153 | + } | |
| 154 | + qpdf_offset_t end_pos = max_offset; | |
| 155 | + if (cur_offset >= end_pos) { | |
| 156 | + last_offset = end_pos + global_offset; | |
| 157 | + cur_offset = end_pos; | |
| 158 | + return end_pos; | |
| 159 | + } | |
| 160 | + | |
| 161 | + qpdf_offset_t result = 0; | |
| 162 | + unsigned char const* buffer = buf->getBuffer(); | |
| 163 | + unsigned char const* end = buffer + end_pos; | |
| 164 | + unsigned char const* p = buffer + cur_offset; | |
| 165 | + | |
| 166 | + while (p < end && !(*p == '\r' || *p == '\n')) { | |
| 167 | + ++p; | |
| 168 | + } | |
| 169 | + if (p < end) { | |
| 170 | + result = p - buffer; | |
| 171 | + cur_offset = result + 1; | |
| 172 | + ++p; | |
| 173 | + while (cur_offset < end_pos && (*p == '\r' || *p == '\n')) { | |
| 174 | + ++p; | |
| 175 | + ++cur_offset; | |
| 176 | + } | |
| 177 | + } else { | |
| 178 | + cur_offset = end_pos; | |
| 179 | + result = end_pos; | |
| 180 | + } | |
| 181 | + return result; | |
| 182 | +} | |
| 183 | + | |
| 184 | +void | |
| 185 | +is::OffsetBuffer::seek_internal(qpdf_offset_t offset, int whence) | |
| 186 | +{ | |
| 187 | + switch (whence) { | |
| 188 | + case SEEK_SET: | |
| 189 | + cur_offset = offset; | |
| 190 | + break; | |
| 191 | + | |
| 192 | + case SEEK_END: | |
| 193 | + QIntC::range_check(max_offset, offset); | |
| 194 | + cur_offset = max_offset + offset; | |
| 195 | + break; | |
| 196 | + | |
| 197 | + case SEEK_CUR: | |
| 198 | + QIntC::range_check(cur_offset, offset); | |
| 199 | + cur_offset += offset; | |
| 200 | + break; | |
| 201 | + | |
| 202 | + default: | |
| 203 | + throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek"); | |
| 204 | + break; | |
| 205 | + } | |
| 206 | + | |
| 207 | + if (cur_offset < 0) { | |
| 208 | + throw std::runtime_error(description + ": seek before beginning of buffer"); | |
| 209 | + } | |
| 210 | +} | |
| 211 | + | |
| 212 | +size_t | |
| 213 | +is::OffsetBuffer::read(char* buffer, size_t length) | |
| 214 | +{ | |
| 215 | + if (cur_offset < 0) { | |
| 216 | + throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); | |
| 217 | + } | |
| 218 | + qpdf_offset_t end_pos = max_offset; | |
| 219 | + if (cur_offset >= end_pos) { | |
| 220 | + last_offset = end_pos + global_offset; | |
| 221 | + return 0; | |
| 222 | + } | |
| 223 | + | |
| 224 | + last_offset = cur_offset + global_offset; | |
| 225 | + size_t len = std::min(QIntC::to_size(end_pos - cur_offset), length); | |
| 226 | + memcpy(buffer, buf->getBuffer() + cur_offset, len); | |
| 227 | + cur_offset += QIntC::to_offset(len); | |
| 228 | + return len; | |
| 229 | +} | ... | ... |
libqpdf/QPDFObjectHandle.cc
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> |
| ... | ... | @@ -14,7 +14,9 @@ namespace qpdf::is |
| 14 | 14 | { |
| 15 | 15 | public: |
| 16 | 16 | OffsetBuffer(std::string const& description, Buffer* buf, qpdf_offset_t global_offset) : |
| 17 | - proxied(description, buf), | |
| 17 | + description(description), | |
| 18 | + buf(buf), | |
| 19 | + max_offset(buf ? static_cast<qpdf_offset_t>(buf->getSize()) : 0), | |
| 18 | 20 | global_offset(global_offset) |
| 19 | 21 | { |
| 20 | 22 | if (global_offset < 0) { |
| ... | ... | @@ -28,53 +30,55 @@ namespace qpdf::is |
| 28 | 30 | qpdf_offset_t |
| 29 | 31 | findAndSkipNextEOL() final |
| 30 | 32 | { |
| 31 | - return proxied.findAndSkipNextEOL() + global_offset; | |
| 33 | + return findAndSkipNextEOL_internal() + global_offset; | |
| 32 | 34 | } |
| 33 | 35 | |
| 34 | 36 | std::string const& |
| 35 | 37 | getName() const final |
| 36 | 38 | { |
| 37 | - return proxied.getName(); | |
| 39 | + return description; | |
| 38 | 40 | } |
| 39 | 41 | |
| 40 | 42 | qpdf_offset_t |
| 41 | 43 | tell() final |
| 42 | 44 | { |
| 43 | - return proxied.tell() + global_offset; | |
| 45 | + return cur_offset + global_offset; | |
| 44 | 46 | } |
| 45 | 47 | |
| 46 | 48 | void |
| 47 | 49 | seek(qpdf_offset_t offset, int whence) final |
| 48 | 50 | { |
| 49 | 51 | if (whence == SEEK_SET) { |
| 50 | - proxied.seek(offset - global_offset, whence); | |
| 52 | + seek_internal(offset - global_offset, whence); | |
| 51 | 53 | } else { |
| 52 | - proxied.seek(offset, whence); | |
| 54 | + seek_internal(offset, whence); | |
| 53 | 55 | } |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | 58 | void |
| 57 | 59 | rewind() final |
| 58 | 60 | { |
| 59 | - seek(0, SEEK_SET); | |
| 61 | + seek_internal(0, SEEK_SET); | |
| 60 | 62 | } |
| 61 | 63 | |
| 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 | - } | |
| 64 | + size_t read(char* buffer, size_t length) final; | |
| 69 | 65 | |
| 70 | 66 | void |
| 71 | 67 | unreadCh(char ch) final |
| 72 | 68 | { |
| 73 | - proxied.unreadCh(ch); | |
| 69 | + if (cur_offset > 0) { | |
| 70 | + --cur_offset; | |
| 71 | + } | |
| 74 | 72 | } |
| 75 | 73 | |
| 76 | 74 | private: |
| 77 | - BufferInputSource proxied; | |
| 75 | + qpdf_offset_t findAndSkipNextEOL_internal(); | |
| 76 | + void seek_internal(qpdf_offset_t offset, int whence); | |
| 77 | + | |
| 78 | + std::string description; | |
| 79 | + Buffer* buf; | |
| 80 | + qpdf_offset_t cur_offset{0}; | |
| 81 | + qpdf_offset_t max_offset; | |
| 78 | 82 | qpdf_offset_t global_offset; |
| 79 | 83 | }; |
| 80 | 84 | ... | ... |