/src/qpdf/libqpdf/BufferInputSource.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include <qpdf/BufferInputSource.hh> |
2 | | |
3 | | #include <qpdf/QIntC.hh> |
4 | | #include <algorithm> |
5 | | #include <cstring> |
6 | | #include <sstream> |
7 | | |
8 | | BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) : |
9 | 1.13M | own_memory(own_memory), |
10 | 1.13M | description(description), |
11 | 1.13M | buf(buf), |
12 | 1.13M | cur_offset(0), |
13 | 1.13M | max_offset(buf ? QIntC::to_offset(buf->getSize()) : 0) |
14 | 1.13M | { |
15 | 1.13M | } |
16 | | |
17 | | BufferInputSource::BufferInputSource(std::string const& description, std::string const& contents) : |
18 | 42.0k | own_memory(true), |
19 | 42.0k | description(description), |
20 | 42.0k | buf(new Buffer(contents.length())), |
21 | 42.0k | cur_offset(0), |
22 | 42.0k | max_offset(QIntC::to_offset(buf->getSize())) |
23 | 42.0k | { |
24 | 42.0k | memcpy(buf->getBuffer(), contents.c_str(), contents.length()); |
25 | 42.0k | } |
26 | | |
27 | | BufferInputSource::~BufferInputSource() |
28 | 1.17M | { |
29 | 1.17M | if (own_memory) { |
30 | 170k | delete buf; |
31 | 170k | } |
32 | 1.17M | } |
33 | | |
34 | | qpdf_offset_t |
35 | | BufferInputSource::findAndSkipNextEOL() |
36 | 26.1M | { |
37 | 26.1M | if (cur_offset < 0) { |
38 | 0 | throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); |
39 | 0 | } |
40 | 26.1M | qpdf_offset_t end_pos = max_offset; |
41 | 26.1M | if (cur_offset >= end_pos) { |
42 | 79.8k | last_offset = end_pos; |
43 | 79.8k | cur_offset = end_pos; |
44 | 79.8k | return end_pos; |
45 | 79.8k | } |
46 | | |
47 | 26.1M | qpdf_offset_t result = 0; |
48 | 26.1M | unsigned char const* buffer = buf->getBuffer(); |
49 | 26.1M | unsigned char const* end = buffer + end_pos; |
50 | 26.1M | unsigned char const* p = buffer + cur_offset; |
51 | | |
52 | 2.02G | while ((p < end) && !((*p == '\r') || (*p == '\n'))) { |
53 | 1.99G | ++p; |
54 | 1.99G | } |
55 | 26.1M | if (p < end) { |
56 | 25.9M | result = p - buffer; |
57 | 25.9M | cur_offset = result + 1; |
58 | 25.9M | ++p; |
59 | 46.4M | while ((cur_offset < end_pos) && ((*p == '\r') || (*p == '\n'))) { |
60 | 20.4M | ++p; |
61 | 20.4M | ++cur_offset; |
62 | 20.4M | } |
63 | 25.9M | } else { |
64 | 153k | cur_offset = end_pos; |
65 | 153k | result = end_pos; |
66 | 153k | } |
67 | 26.1M | return result; |
68 | 26.1M | } |
69 | | |
70 | | std::string const& |
71 | | BufferInputSource::getName() const |
72 | 11.2M | { |
73 | 11.2M | return description; |
74 | 11.2M | } |
75 | | |
76 | | qpdf_offset_t |
77 | | BufferInputSource::tell() |
78 | 477M | { |
79 | 477M | return cur_offset; |
80 | 477M | } |
81 | | |
82 | | void |
83 | | BufferInputSource::seek(qpdf_offset_t offset, int whence) |
84 | 375M | { |
85 | 375M | switch (whence) { |
86 | 373M | case SEEK_SET: |
87 | 373M | cur_offset = offset; |
88 | 373M | break; |
89 | | |
90 | 495k | case SEEK_END: |
91 | 495k | QIntC::range_check(max_offset, offset); |
92 | 495k | cur_offset = max_offset + offset; |
93 | 495k | break; |
94 | | |
95 | 1.55M | case SEEK_CUR: |
96 | 1.55M | QIntC::range_check(cur_offset, offset); |
97 | 1.55M | cur_offset += offset; |
98 | 1.55M | break; |
99 | | |
100 | 0 | default: |
101 | 0 | throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek"); |
102 | 0 | break; |
103 | 375M | } |
104 | | |
105 | 375M | if (cur_offset < 0) { |
106 | 4.10k | throw std::runtime_error(description + ": seek before beginning of buffer"); |
107 | 4.10k | } |
108 | 375M | } |
109 | | |
110 | | void |
111 | | BufferInputSource::rewind() |
112 | 0 | { |
113 | 0 | cur_offset = 0; |
114 | 0 | } |
115 | | |
116 | | size_t |
117 | | BufferInputSource::read(char* buffer, size_t length) |
118 | 54.4M | { |
119 | 54.4M | if (cur_offset < 0) { |
120 | 0 | throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); |
121 | 0 | } |
122 | 54.4M | qpdf_offset_t end_pos = max_offset; |
123 | 54.4M | if (cur_offset >= end_pos) { |
124 | 1.31M | last_offset = end_pos; |
125 | 1.31M | return 0; |
126 | 1.31M | } |
127 | | |
128 | 53.1M | last_offset = cur_offset; |
129 | 53.1M | size_t len = std::min(QIntC::to_size(end_pos - cur_offset), length); |
130 | 53.1M | memcpy(buffer, buf->getBuffer() + cur_offset, len); |
131 | 53.1M | cur_offset += QIntC::to_offset(len); |
132 | 53.1M | return len; |
133 | 54.4M | } |
134 | | |
135 | | void |
136 | | BufferInputSource::unreadCh(char ch) |
137 | 204k | { |
138 | 204k | if (cur_offset > 0) { |
139 | 204k | --cur_offset; |
140 | 204k | } |
141 | 204k | } |