Commit 81cb79620a361d7047c72be27d1ede48d5da4e93

Authored by m-holger
1 parent 3a055d5b

Refactor `is::OffsetBuffer` to remove dependency on `BufferInputSource`, improvi…

…ng encapsulation and maintainability.
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
... ... @@ -2,7 +2,7 @@
2 2  
3 3 #include <qpdf/QPDFObjectHandle_private.hh>
4 4  
5   -#include <qpdf/InputSource_private.hh>
  5 +#include <qpdf/BufferInputSource.hh>
6 6 #include <qpdf/JSON_writer.hh>
7 7 #include <qpdf/Pipeline_private.hh>
8 8 #include <qpdf/Pl_Buffer.hh>
... ...
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  
... ...