/src/qpdf/libqpdf/qpdf/InputSource_private.hh
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef QPDF_INPUTSOURCE_PRIVATE_HH |
2 | | #define QPDF_INPUTSOURCE_PRIVATE_HH |
3 | | |
4 | | #include <qpdf/BufferInputSource.hh> |
5 | | #include <qpdf/InputSource.hh> |
6 | | |
7 | | #include <limits> |
8 | | #include <sstream> |
9 | | #include <stdexcept> |
10 | | |
11 | | namespace qpdf::is |
12 | | { |
13 | | class OffsetBuffer final: public InputSource |
14 | | { |
15 | | public: |
16 | | OffsetBuffer(std::string const& description, Buffer* buf, qpdf_offset_t global_offset) : |
17 | 40.4k | proxied(description, buf), |
18 | 40.4k | global_offset(global_offset) |
19 | 40.4k | { |
20 | 40.4k | if (global_offset < 0) { |
21 | 55 | throw std::logic_error("is::OffsetBuffer constructed with negative offset"); |
22 | 55 | } |
23 | 40.3k | last_offset = global_offset; |
24 | 40.3k | } |
25 | | |
26 | 40.3k | ~OffsetBuffer() final = default; |
27 | | |
28 | | qpdf_offset_t |
29 | | findAndSkipNextEOL() final |
30 | 0 | { |
31 | 0 | return proxied.findAndSkipNextEOL() + global_offset; |
32 | 0 | } |
33 | | |
34 | | std::string const& |
35 | | getName() const final |
36 | 0 | { |
37 | 0 | return proxied.getName(); |
38 | 0 | } |
39 | | |
40 | | qpdf_offset_t |
41 | | tell() final |
42 | 6.93M | { |
43 | 6.93M | return proxied.tell() + global_offset; |
44 | 6.93M | } |
45 | | |
46 | | void |
47 | | seek(qpdf_offset_t offset, int whence) final |
48 | 6.88M | { |
49 | 6.88M | if (whence == SEEK_SET) { |
50 | 6.88M | proxied.seek(offset - global_offset, whence); |
51 | 6.88M | } else { |
52 | 0 | proxied.seek(offset, whence); |
53 | 0 | } |
54 | 6.88M | } |
55 | | |
56 | | void |
57 | | rewind() final |
58 | 0 | { |
59 | 0 | seek(0, SEEK_SET); |
60 | 0 | } |
61 | | |
62 | | size_t |
63 | | read(char* buffer, size_t length) final |
64 | 108k | { |
65 | 108k | size_t result = proxied.read(buffer, length); |
66 | 108k | setLastOffset(proxied.getLastOffset() + global_offset); |
67 | 108k | return result; |
68 | 108k | } |
69 | | |
70 | | void |
71 | | unreadCh(char ch) final |
72 | 0 | { |
73 | 0 | proxied.unreadCh(ch); |
74 | 0 | } |
75 | | |
76 | | private: |
77 | | BufferInputSource proxied; |
78 | | qpdf_offset_t global_offset; |
79 | | }; |
80 | | |
81 | | } // namespace qpdf::is |
82 | | |
83 | | inline size_t |
84 | | InputSource::read(std::string& str, size_t count, qpdf_offset_t at) |
85 | 57.0k | { |
86 | 57.0k | if (at >= 0) { |
87 | 45.1k | seek(at, SEEK_SET); |
88 | 45.1k | } |
89 | 57.0k | str.resize(count); |
90 | 57.0k | str.resize(read(str.data(), count)); |
91 | 57.0k | return str.size(); |
92 | 57.0k | } |
93 | | |
94 | | inline std::string |
95 | | InputSource::read(size_t count, qpdf_offset_t at) |
96 | 45.1k | { |
97 | 45.1k | std::string result(count, '\0'); |
98 | 45.1k | (void)read(result, count, at); |
99 | 45.1k | return result; |
100 | 45.1k | } |
101 | | |
102 | | inline void |
103 | | InputSource::loadBuffer() |
104 | 14.6M | { |
105 | 14.6M | buf_idx = 0; |
106 | 14.6M | buf_len = qpdf_offset_t(read(buffer, buf_size)); |
107 | | // NB read sets last_offset |
108 | 14.6M | buf_start = last_offset; |
109 | 14.6M | } |
110 | | |
111 | | inline qpdf_offset_t |
112 | | InputSource::fastTell() |
113 | 123M | { |
114 | 123M | if (buf_len == 0) { |
115 | 116k | loadBuffer(); |
116 | 123M | } else { |
117 | 123M | auto curr = tell(); |
118 | 123M | if (curr < buf_start || curr >= (buf_start + buf_len)) { |
119 | 14.5M | loadBuffer(); |
120 | 108M | } else { |
121 | 108M | last_offset = curr; |
122 | 108M | buf_idx = curr - buf_start; |
123 | 108M | } |
124 | 123M | } |
125 | 123M | return last_offset; |
126 | 123M | } |
127 | | |
128 | | inline bool |
129 | | InputSource::fastRead(char& ch) |
130 | 1.92G | { |
131 | | // Before calling fastRead, fastTell must be called to prepare the buffer. Once reading is |
132 | | // complete, fastUnread must be called to set the correct file position. |
133 | 1.92G | if (buf_idx < buf_len) { |
134 | 1.91G | ch = buffer[buf_idx]; |
135 | 1.91G | ++(buf_idx); |
136 | 1.91G | ++(last_offset); |
137 | 1.91G | return true; |
138 | | |
139 | 1.91G | } else if (buf_len == 0) { |
140 | 60.7k | return false; |
141 | 14.0M | } else { |
142 | 14.0M | seek(buf_start + buf_len, SEEK_SET); |
143 | 14.0M | fastTell(); |
144 | 14.0M | return fastRead(ch); |
145 | 14.0M | } |
146 | 1.92G | } |
147 | | |
148 | | inline void |
149 | | InputSource::fastUnread(bool back) |
150 | 109M | { |
151 | 109M | last_offset -= back ? 1 : 0; |
152 | 109M | seek(last_offset, SEEK_SET); |
153 | 109M | } |
154 | | |
155 | | #endif // QPDF_INPUTSOURCE_PRIVATE_HH |