Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_UTILS_SPBUFFER_H_
25 : #define STAPPLER_CORE_UTILS_SPBUFFER_H_
26 :
27 : #include "SPIOBuffer.h"
28 : #include "SPStringStream.h"
29 : #include "SPUnicode.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler {
32 :
33 : template <typename Interface>
34 : class BufferTemplate : public Interface::AllocBaseType {
35 : public:
36 : using byte_type = uint8_t;
37 : static constexpr size_t defsize = 256;
38 :
39 75375 : BufferTemplate(size_t sz = defsize) {
40 75375 : _buffer.resize(sz, 0);
41 75375 : _ptr = (byte_type *)_buffer.data();
42 75375 : _end = _ptr + sz;
43 75375 : }
44 : BufferTemplate(const BufferTemplate & rhs) : _buffer(rhs._buffer) {
45 : _ptr = (byte_type *)(_buffer.data() + (rhs._ptr - rhs._buffer.data()));
46 : _end = (byte_type *)(_buffer.data() + _buffer.size());
47 : _input = rhs._input;
48 : }
49 25 : BufferTemplate(BufferTemplate && rhs) {
50 25 : auto size = rhs._ptr - rhs._buffer.data();
51 25 : _buffer = std::move(rhs._buffer);
52 25 : _ptr = (byte_type *)(_buffer.data() + size);
53 25 : _end = (byte_type *)(_buffer.data() + _buffer.size());
54 25 : _input = rhs._input;
55 25 : }
56 :
57 25 : BufferTemplate & operator=(const BufferTemplate & rhs) {
58 25 : auto size = rhs._ptr - rhs._buffer.data();
59 25 : _buffer = rhs._buffer;
60 25 : _ptr = (byte_type *)(_buffer.data() + size);
61 25 : _end = (byte_type *)(_buffer.data() + _buffer.size());
62 25 : _input = rhs._input;
63 25 : return *this;
64 : }
65 25 : BufferTemplate & operator=(BufferTemplate && rhs) {
66 25 : auto size = rhs._ptr - rhs._buffer.data();
67 25 : _buffer = std::move(rhs._buffer);
68 25 : _ptr = (byte_type *)(_buffer.data() + size);
69 25 : _end = (byte_type *)(_buffer.data() + _buffer.size());
70 25 : _input = rhs._input;
71 25 : return *this;
72 : }
73 :
74 : template <typename CharType, typename std::enable_if<sizeof(CharType) == 1>::type * = nullptr>
75 261575 : size_t put(const CharType *ptr, size_t len) {
76 925 : size_t ret = 0;
77 524250 : while (ret < len) {
78 262675 : const size_t bsize = _end - _ptr;
79 262675 : if (bsize) {
80 262100 : const size_t remaining = len - ret;
81 262100 : const size_t nlen = min(bsize, remaining);
82 262100 : memcpy((void *)_ptr, (const void *)ptr, nlen);
83 262100 : ret += nlen;
84 262100 : ptr += nlen;
85 262100 : _ptr += nlen;
86 : }
87 :
88 262675 : if (ret < len) {
89 1100 : overflow(len - ret);
90 : }
91 : }
92 261575 : if (_ptr > _buffer.data() + _input) {
93 261425 : _input = _ptr - _buffer.data();
94 : }
95 261575 : return ret;
96 : }
97 :
98 : size_t putc(char16_t c) {
99 : auto len = unicode::utf8EncodeLength(c);
100 : if (_end - _ptr < len) {
101 : overflow();
102 : }
103 : unicode::utf8EncodeBuf((char *)_ptr, c);
104 : _ptr += len;
105 :
106 : if (_ptr > _buffer.data() + _input) {
107 : _input = _ptr - _buffer.data();
108 : }
109 : return len;
110 : }
111 :
112 825 : size_t putc(char c) {
113 825 : if (_end == _ptr) {
114 0 : overflow();
115 : }
116 825 : *_ptr = *((byte_type *)&c);
117 825 : ++ _ptr;
118 :
119 825 : if (_ptr > _buffer.data() + _input) {
120 825 : _input = _ptr - _buffer.data();
121 : }
122 825 : return 1;
123 : }
124 :
125 : // toString interface adapter
126 : template <typename ... Args, std::enable_if_t<string::detail::IsFastToStringAvailable<Args...>::value> * = nullptr>
127 2056625 : StringView putStrings(Args && ... args) {
128 2056625 : auto size = string::detail::getBufferSize(std::forward<Args>(args)...);
129 2056625 : size_t emptyBytes = capacity() - (_ptr - _buffer.data());
130 2056625 : if (emptyBytes < size) {
131 139950 : overflow(emptyBytes);
132 : }
133 :
134 2056625 : char *start = (char *)_ptr;
135 2056625 : auto s = string::detail::writeBuffer(start, std::forward<Args>(args)...);
136 2056625 : if (s != size) {
137 0 : std::cout << "Invalid buffer size for toString<fast>\n";
138 0 : abort();
139 : }
140 2056625 : _ptr += s;
141 2056625 : if (_ptr > _buffer.data() + _input) {
142 2056625 : _input = _ptr - _buffer.data();
143 : }
144 :
145 2056625 : return StringView(start, s);
146 : }
147 :
148 : template <typename ... Args, std::enable_if_t<string::detail::IsFastToStringAvailable<Args...>::value> * = nullptr>
149 : StringView resetWithStrings(Args && ... args) {
150 : clear();
151 : return putStrings(std::forward<Args>(args)...);
152 : }
153 :
154 : template <typename Reader = StringView>
155 775 : Reader get() const {
156 775 : return Reader((const typename Reader::CharType *)_buffer.data(), _ptr - _buffer.data());
157 : }
158 :
159 : template <typename Reader = StringView>
160 25 : Reader pop(size_t len) {
161 25 : size_t sz = size();
162 25 : len = min(len, sz);
163 25 : Reader r((const typename Reader::CharType *)(_buffer.data() + sz - len), len);
164 25 : _ptr = (byte_type *)(_buffer.data() + sz - len);
165 25 : return r;
166 : }
167 :
168 : template <typename Reader = StringView>
169 25 : Reader read(size_t len) {
170 25 : size_t input = _input;
171 25 : size_t sz = size();
172 25 : len = min(len, input - sz);
173 25 : Reader r((const typename Reader::CharType *)(_buffer.data() + sz), len);
174 25 : return r;
175 : }
176 :
177 10900 : void clear() {
178 10900 : _ptr = (byte_type *)_buffer.data();
179 10900 : _input = 0;
180 10900 : }
181 :
182 175 : bool seek(size_t pos) {
183 175 : if (pos > _buffer.size()) {
184 25 : overflow(pos - _buffer.size());
185 : }
186 175 : _ptr = _buffer.data() + pos;
187 175 : if (_ptr > _buffer.data() + _input) {
188 25 : _input = _ptr - _buffer.data();
189 : }
190 175 : return true;
191 : }
192 :
193 2056700 : size_t capacity() const {
194 2056700 : return _buffer.size();
195 : }
196 :
197 3850 : size_t size() const {
198 3850 : return _ptr - _buffer.data();
199 : }
200 :
201 175 : size_t input() const {
202 175 : return _input;
203 : }
204 :
205 13600 : bool empty() const {
206 13600 : return _ptr == _buffer.data();
207 : }
208 :
209 72250 : auto str() const -> typename Interface::StringType {
210 72250 : return typename Interface::StringType((char *)_buffer.data(), _ptr - _buffer.data());
211 : }
212 :
213 50 : uint8_t * data() {
214 50 : return _buffer.data();
215 : }
216 :
217 50 : uint8_t * prepare(size_t & size) {
218 50 : clear();
219 50 : auto c = capacity();
220 50 : if (size > c) {
221 0 : size = c;
222 : }
223 50 : return _ptr;
224 : }
225 :
226 50 : void save(uint8_t *, size_t nbytes) {
227 50 : _ptr += nbytes;
228 50 : if (_ptr > _buffer.data() + _input) {
229 25 : _input = _ptr - _buffer.data();
230 : }
231 50 : }
232 :
233 : protected:
234 141050 : void overflow() {
235 141050 : auto size = _ptr - _buffer.data();
236 141050 : _buffer.resize(_buffer.size() * 2, 0);
237 141050 : _ptr = (byte_type *)(_buffer.data() + size);
238 141050 : _end = (byte_type *)(_buffer.data() + _buffer.size());
239 141050 : }
240 :
241 141075 : void overflow(size_t required) {
242 141075 : if (required < _buffer.size()) {
243 141050 : overflow();
244 : } else {
245 25 : auto size = _ptr - _buffer.data();
246 25 : _buffer.resize(_buffer.size() + required, 0);
247 25 : _ptr = (byte_type *)(_buffer.data() + size);
248 25 : _end = (byte_type *)(_buffer.data() + _buffer.size());
249 : }
250 141075 : }
251 :
252 : typename Interface::BytesType _buffer;
253 : uint8_t *_ptr = nullptr;
254 : uint8_t *_end = nullptr;
255 : size_t _input = 0;
256 : };
257 :
258 : template <size_t Size>
259 : class StackBuffer {
260 : public:
261 6669 : StackBuffer() { }
262 : StackBuffer(const StackBuffer & rhs) : _buf(rhs._buf), _size(rhs._size) { }
263 : StackBuffer(StackBuffer && rhs) : _buf(rhs._buf), _size(rhs._size) { }
264 :
265 : StackBuffer & operator=(const StackBuffer & rhs) {
266 : _buf = rhs._buf;
267 : _size = rhs._size;
268 : return *this;
269 : }
270 : StackBuffer & operator=(StackBuffer && rhs) {
271 : _buf = rhs._buf;
272 : _size = rhs._size;
273 : return *this;
274 : }
275 :
276 6875 : uint8_t & operator[] (size_t n) { return _buf[n]; }
277 : const uint8_t & operator[] (size_t n) const { return _buf[n]; }
278 :
279 : uint8_t & at(size_t n) { return _buf.at(n); }
280 : const uint8_t & at(size_t n) const { return _buf.at(n); }
281 :
282 445463 : size_t size() const { return _size; }
283 525 : size_t capacity() const { return Size; }
284 645269 : size_t remains() const { return Size - _size; }
285 :
286 : bool empty() const { return _size == 0; }
287 : bool full() const { return _size == Size; }
288 :
289 : void soft_clear() {
290 : _size = 0;
291 : }
292 :
293 647694 : void clear() {
294 647694 : memset(_buf.data(), 0, Size);
295 647694 : _size = 0;
296 647694 : }
297 :
298 436713 : uint8_t *data() { return _buf.data(); }
299 : const uint8_t *data() const { return _buf.data(); }
300 :
301 : size_t put(const uint8_t *ptr, size_t s) {
302 : if (s + _size > Size) {
303 : s = Size - _size;
304 : }
305 :
306 : memcpy(_buf.data() + _size, ptr, s);
307 : _size += s;
308 : return s;
309 : }
310 :
311 : size_t putc(uint8_t c) {
312 : return put(&c, 1);
313 : }
314 :
315 : template <typename Reader = StringView>
316 3500 : Reader get() const {
317 3500 : return Reader((const typename Reader::CharType *)_buf.data(), _size);
318 : }
319 :
320 642519 : uint8_t * prepare(size_t & size) {
321 642519 : clear();
322 642519 : return prepare_preserve(size);
323 : }
324 :
325 645269 : uint8_t * prepare_preserve(size_t & size) {
326 645269 : auto r = remains();
327 645269 : if (r < size) {
328 0 : size = r;
329 : }
330 645269 : return _buf.data() + _size;
331 : }
332 :
333 645269 : void save(uint8_t *data, size_t nbytes) {
334 645269 : _size += nbytes;
335 645269 : }
336 :
337 : protected:
338 : size_t _size = 0;
339 : std::array<uint8_t, Size> _buf;
340 : };
341 :
342 : }
343 :
344 : namespace STAPPLER_VERSIONIZED stappler::io {
345 :
346 : template <typename Interface>
347 : struct BufferTraits<stappler::BufferTemplate<Interface>> {
348 : using type = stappler::BufferTemplate<Interface>;
349 :
350 50 : static uint8_t * PrepareFn(void *ptr, size_t & size) {
351 50 : return ((type *)ptr)->prepare(size);
352 : }
353 :
354 : // save written bytes in buffer
355 50 : static void SaveFn(void *ptr, uint8_t *buf, size_t prepared, size_t nbytes) {
356 50 : ((type *)ptr)->save(buf, nbytes);
357 50 : }
358 :
359 25 : static size_t SizeFn(void *ptr) { return ((type *)ptr)->size(); }
360 25 : static size_t CapacityFn(void *ptr) { return ((type *)ptr)->capacity(); }
361 25 : static uint8_t *DataFn(void *ptr) { return ((type *)ptr)->data(); }
362 25 : static void ClearFn(void *ptr) { ((type *)ptr)->clear(); }
363 : };
364 :
365 : template <size_t Size>
366 : struct BufferTraits<StackBuffer<Size>> {
367 : using type = StackBuffer<Size>;
368 :
369 642519 : static uint8_t * PrepareFn(void *ptr, size_t & size) {
370 642519 : return ((type *)ptr)->prepare(size);
371 : }
372 :
373 : // save written bytes in buffer
374 642519 : static void SaveFn(void *ptr, uint8_t *buf, size_t source, size_t nbytes) {
375 642519 : ((type *)ptr)->save(buf, nbytes);
376 642519 : }
377 :
378 424750 : static size_t SizeFn(void *ptr) { return ((type *)ptr)->size(); }
379 100 : static size_t CapacityFn(void *ptr) { return ((type *)ptr)->capacity(); }
380 424750 : static uint8_t *DataFn(void *ptr) { return ((type *)ptr)->data(); }
381 0 : static void ClearFn(void *ptr) { ((type *)ptr)->clear(); }
382 : };
383 :
384 : }
385 :
386 : #endif /* STAPPLER_CORE_UTILS_SPBUFFER_H_ */
|