Horizon Official Technical Documentation
ByteBuffer.hpp
Go to the documentation of this file.
1/***************************************************
2 * _ _ _ *
3 * | | | | (_) *
4 * | |_| | ___ _ __ _ _______ _ __ *
5 * | _ |/ _ \| '__| |_ / _ \| '_ \ *
6 * | | | | (_) | | | |/ / (_) | | | | *
7 * \_| |_/\___/|_| |_/___\___/|_| |_| *
8 ***************************************************
9 * This file is part of Horizon (c).
10 *
11 * Copyright (c) 2019 Sagun K. (sagunxp@gmail.com).
12 * Copyright (c) 2019 Horizon Dev Team.
13 *
14 * Base Author - Sagun K. (sagunxp@gmail.com)
15 *
16 * This library is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this library. If not, see <http://www.gnu.org/licenses/>.
28 **************************************************/
29
30#ifndef HORIZON_NETWORKING_BYTEBUFFER_HPP
31#define HORIZON_NETWORKING_BYTEBUFFER_HPP
32
33#include "ByteConverter.hpp"
34
35#include <type_traits>
36#include <stdlib.h>
37#include <string>
38#include <cstring>
39#include <vector>
40#include <cmath>
41#include <assert.h>
42#include <list>
43#include <map>
44#include <cstdio>
45
46// Root of ByteBuffer exception hierarchy
47class ByteBufferException : public std::exception
48{
49public:
51
52 char const* what() const throw() override { return msg_.c_str(); }
53
54protected:
55 std::string & message() throw() { return msg_; }
56
57private:
58 std::string msg_;
59};
60
62{
63public:
64 ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize);
65
67};
68
70{
71public:
72 ByteBufferSourceException(size_t pos, size_t size, size_t valueSize);
73
75};
76
78{
79public:
80 const static size_t DEFAULT_SIZE = 0x1000; // Reserve 4096 bytes.
81
82 // constructor
84 : _rpos(0), _wpos(0)
85 {
86 _storage.reserve(DEFAULT_SIZE);
87 }
88
90 : _rpos(0), _wpos(0)
91 {
92 _storage.reserve(reserve);
93 }
94
96 : _rpos(buf._rpos), _wpos(buf._wpos), _storage(std::move(buf._storage))
97 { }
98
99 ByteBuffer(ByteBuffer& buf, size_t len)
100 : _rpos(0)
101 {
102 _storage.resize(len);
103 // copy len bytes from buf
104 std::memcpy(&_storage[_wpos], buf.contents(), len);
105 _wpos = len;
106 buf._rpos += len;
107 }
108
109 ByteBuffer(ByteBuffer const& right)
110 : _rpos(right._rpos), _wpos(right._wpos), _storage(right._storage)
111 { }
112
114 {
115 if (this != &right)
116 {
117 _rpos = right._rpos;
118 _wpos = right._wpos;
119 _storage = right._storage;
120 }
121
122 return *this;
123 }
124
125 virtual ~ByteBuffer()
126 { }
127
128 void clear()
129 {
130 _storage.clear();
131 reset();
132 }
133
134 void reset()
135 {
136 _wpos = 0;
137 _rpos = 0;
138 }
139
140 template <typename T> void append(T value)
141 {
142 append((uint8_t *)&value, sizeof(value));
143 }
144
145 template <typename T> void put(size_t pos, T value)
146 {
147 static_assert(std::is_fundamental<T>::value, "append(compound)");
148 put(pos, (uint8_t *)&value, sizeof(value));
149 }
150
151 ByteBuffer &operator<<(uint8_t value)
152 {
153 append<uint8_t>(value);
154 return *this;
155 }
156
157 ByteBuffer &operator<<(uint16_t value)
158 {
159 append<uint16_t>(value);
160 return *this;
161 }
162
163 ByteBuffer &operator<<(uint32_t value)
164 {
165 append<uint32_t>(value);
166 return *this;
167 }
168
169 ByteBuffer &operator<<(uint64_t value)
170 {
171 append<uint64_t>(value);
172 return *this;
173 }
174
175 // signed as in 2e complement
176 ByteBuffer &operator<<(int8_t value)
177 {
178 append<int8_t>(value);
179 return *this;
180 }
181
182 ByteBuffer &operator<<(int16_t value)
183 {
184 append<int16_t>(value);
185 return *this;
186 }
187
188 ByteBuffer &operator<<(int32_t value)
189 {
190 append<int32_t>(value);
191 return *this;
192 }
193
194 ByteBuffer &operator<<(int64_t value)
195 {
196 append<int64_t>(value);
197 return *this;
198 }
199
200 // floating points
201 ByteBuffer &operator<<(float value)
202 {
203 append<float>(value);
204 return *this;
205 }
206
207 ByteBuffer &operator<<(double value)
208 {
209 append<double>(value);
210 return *this;
211 }
212
213 ByteBuffer &operator>>(bool &value)
214 {
215 value = read<char>() > 0 ? true : false;
216 return *this;
217 }
218
219 ByteBuffer &operator>>(uint8_t &value)
220 {
221 value = static_cast<int>(read<unsigned char>());
222 return *this;
223 }
224
225 ByteBuffer &operator>>(uint16_t &value)
226 {
227 value = read<unsigned short>();
228 return *this;
229 }
230
231 ByteBuffer &operator>>(uint32_t &value)
232 {
233 value = read<unsigned int>();
234 return *this;
235 }
236
237 ByteBuffer &operator>>(uint64_t &value)
238 {
239 value = read<unsigned long>();
240 return *this;
241 }
242
243 //signed as in 2e complement
244 ByteBuffer &operator>>(int8_t &value)
245 {
246 value = static_cast<int>(read<signed char>());
247 return *this;
248 }
249
250 ByteBuffer &operator>>(int16_t &value)
251 {
252 value = read<short>();
253 return *this;
254 }
255
256 ByteBuffer &operator>>(int32_t &value)
257 {
258 value = read<int>();
259 return *this;
260 }
261
262 ByteBuffer &operator>>(int64_t &value)
263 {
264 value = read<long>();
265 return *this;
266 }
267
268 ByteBuffer &operator>>(float &value)
269 {
270 value = read<float>();
271 if (!std::isfinite(value))
272 throw ByteBufferException();
273 return *this;
274 }
275
276 ByteBuffer &operator>>(double &value)
277 {
278 value = read<double>();
279 if (!std::isfinite(value))
280 throw ByteBufferException();
281 return *this;
282 }
283
284 uint8_t& operator[](size_t const pos)
285 {
286 if (pos >= maximum_length())
287 throw ByteBufferPositionException(false, pos, 1, maximum_length());
288 return _storage[pos];
289 }
290
291 uint8_t const& operator[](size_t const pos) const
292 {
293 if (pos >= maximum_length())
294 throw ByteBufferPositionException(false, pos, 1, maximum_length());
295 return _storage[pos];
296 }
297
298 size_t rpos() const { return _rpos; }
299
300 size_t rpos(size_t rpos_)
301 {
302 _rpos = rpos_;
303 return _rpos;
304 }
305
306 uint8_t* contents()
307 {
308 if (_storage.empty())
309 throw ByteBufferException();
310 return _storage.data();
311 }
312
313 uint8_t const* contents() const
314 {
315 if (_storage.empty())
316 throw ByteBufferException();
317 return _storage.data();
318 }
319
320 void finish_reading() { _rpos = wpos(); }
321 void read_completed(size_t bytes) { _rpos += bytes; }
322 void write_completed(size_t bytes) { _wpos += bytes; }
323
324 size_t wpos() const { return _wpos; }
325
326 uint8_t *get_base_pointer() { return _storage.data(); }
327 uint8_t *get_read_pointer() { return get_base_pointer() + _rpos; }
328 uint8_t *get_write_pointer() { return get_base_pointer() + _wpos; }
329
330 std::string to_string() { return std::string(get_read_pointer(), get_write_pointer()); }
331
332 size_t maximum_length() const { return _storage.size(); }
333 size_t active_length() const { return _wpos - _rpos; }
334 size_t remaining_space() const { return _storage.size() - _wpos; }
335
336 bool is_empty() const { return _storage.empty(); }
337
338 // Discards inactive data
339 void flush()
340 {
341 if (_rpos) {
342 if (_rpos != _wpos)
344 _wpos -= _rpos;
345 _rpos = 0;
346 }
347 }
348
349 // Ensures there's "some" free space, make sure to call normalize() before this
351 {
352 // resize buffer if it's already full
353 if (remaining_space() == 0)
354 _storage.resize(_storage.size() * 3 / 2);
355 }
356
357 void resize(size_t new_size)
358 {
359 _storage.resize(new_size);
360 }
361
362 void reserve(size_t ressize)
363 {
364 if (ressize > maximum_length())
365 _storage.reserve(ressize);
366 }
367
368 template<typename T>
369 void read_skip() { read_skip(sizeof(T)); }
370
371 void read_skip(size_t skip)
372 {
373 if (_rpos + skip > maximum_length())
374 throw ByteBufferPositionException(false, _rpos, skip, maximum_length());
375 _rpos += skip;
376 }
377
378 template <typename T>
380 {
381 T r = read<T>(_rpos);
382 _rpos += sizeof(T);
383 return r;
384 }
385
386 template <typename T> T read(size_t pos) const
387 {
388 if (pos + sizeof(T) > maximum_length())
389 throw ByteBufferPositionException(false, pos, sizeof(T), maximum_length());
390 T val = *(reinterpret_cast<T const*>(& _storage[pos]));
391 return val;
392 }
393
394 void read(char *dest, size_t len)
395 {
396 if (_rpos + len > maximum_length())
398 std::memcpy((void *) dest, &_storage[_rpos], len);
399 _rpos += len;
400 }
401
402 void read(ByteBuffer &buf, size_t len)
403 {
404 std::memcpy(&buf._storage[buf._wpos], &_storage[_rpos], len);
405 buf._wpos += len;
406 _rpos += len;
407 }
408
409 void append(const char *src, size_t size)
410 {
411 append((const uint8_t *)src, size);
412 }
413
414 void append(std::string string)
415 {
416 append(string.c_str(), string.size());
417 }
418
419 template<class T>
420 void append(const T *src, size_t size)
421 {
422 append((const uint8_t *) src, size);
423 }
424
425 template<class T, class SubT>
426 void append(const T *t, size_t t_size, const SubT *sub_t, int count)
427 {
428 append((const uint8_t *) t, t_size);
429 append((const uint8_t *) sub_t, sizeof(SubT) * count);
430 }
431
432 void append(const uint8_t *src, size_t cnt)
433 {
434 if (!cnt)
436
437 if (!src)
439
440 assert(maximum_length() < 10000000);
441
442 size_t const newSize = _wpos + cnt;
443 if (_storage.capacity() < newSize) // custom memory allocation rules
444 {
445 if (newSize < 100)
446 _storage.reserve(300);
447 else if (newSize < 750)
448 _storage.reserve(2500);
449 else if (newSize < 6000)
450 _storage.reserve(10000);
451 else
452 _storage.reserve(400000);
453 }
454
455 if (_storage.size() < newSize)
456 _storage.resize(newSize);
457 std::memcpy(&_storage[_wpos], src, cnt);
458 _wpos = newSize;
459 }
460
461 void append(const ByteBuffer& buffer)
462 {
463 if (buffer.wpos())
464 append(buffer.contents(), buffer.wpos());
465 }
466
467 void put(size_t pos, const uint8_t *src, size_t cnt)
468 {
469 if (pos + cnt > maximum_length())
470 throw ByteBufferPositionException(true, pos, cnt, maximum_length());
471
472 if (!src)
474
475 std::memcpy(&_storage[pos], src, cnt);
476 }
477
478 void print_storage() const;
479
480 void textlike() const;
481
482 void hexlike() const;
483
484 template<typename SizeT = uint16_t, typename std::enable_if<std::is_integral<SizeT>::value>::type* = nullptr>
485 void emplace_size(std::size_t pos = 2)
486 {
487 _storage.emplace(_storage.begin() + pos, 0);
488 _storage.emplace(_storage.begin() + pos + 1, 0);
489 _wpos += 2;
490 put(pos, (uint8_t *) &_wpos, sizeof(SizeT));
491 }
492
493protected:
494 size_t _rpos{0}, _wpos{0};
495 std::vector<uint8_t> _storage;
496};
497
498template<>
499inline void ByteBuffer::read_skip<char const*>()
500{
501 read_skip<char*>();
502}
503
504template<>
505inline void ByteBuffer::read_skip<std::string>()
506{
507 read_skip<char*>();
508}
509
510#endif /* HORIZON_NETWORKING_BYTEBUFFER_HPP */
Definition: ByteBuffer.hpp:48
std::string & message()
Definition: ByteBuffer.hpp:55
std::string msg_
Definition: ByteBuffer.hpp:58
char const * what() const override
Definition: ByteBuffer.hpp:52
~ByteBufferException()
Definition: ByteBuffer.hpp:50
Definition: ByteBuffer.hpp:62
~ByteBufferPositionException()
Definition: ByteBuffer.hpp:66
ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize)
Definition: ByteBuffer.cpp:35
Definition: ByteBuffer.hpp:70
~ByteBufferSourceException()
Definition: ByteBuffer.hpp:74
ByteBufferSourceException(size_t pos, size_t size, size_t valueSize)
Definition: ByteBuffer.cpp:47
Definition: ByteBuffer.hpp:78
size_t _wpos
Definition: ByteBuffer.hpp:494
void append(const char *src, size_t size)
Definition: ByteBuffer.hpp:409
virtual ~ByteBuffer()
Definition: ByteBuffer.hpp:125
void ensure_free_space()
Definition: ByteBuffer.hpp:350
size_t remaining_space() const
Definition: ByteBuffer.hpp:334
uint8_t const & operator[](size_t const pos) const
Definition: ByteBuffer.hpp:291
void read_skip()
Definition: ByteBuffer.hpp:369
uint8_t * get_base_pointer()
Definition: ByteBuffer.hpp:326
void resize(size_t new_size)
Definition: ByteBuffer.hpp:357
ByteBuffer & operator>>(int16_t &value)
Definition: ByteBuffer.hpp:250
ByteBuffer & operator<<(double value)
Definition: ByteBuffer.hpp:207
void reset()
Definition: ByteBuffer.hpp:134
ByteBuffer(size_t reserve)
Definition: ByteBuffer.hpp:89
void put(size_t pos, T value)
Definition: ByteBuffer.hpp:145
ByteBuffer(ByteBuffer const &right)
Definition: ByteBuffer.hpp:109
size_t rpos() const
Definition: ByteBuffer.hpp:298
ByteBuffer & operator<<(uint64_t value)
Definition: ByteBuffer.hpp:169
ByteBuffer & operator>>(int32_t &value)
Definition: ByteBuffer.hpp:256
void reserve(size_t ressize)
Definition: ByteBuffer.hpp:362
void append(std::string string)
Definition: ByteBuffer.hpp:414
ByteBuffer & operator>>(uint8_t &value)
Definition: ByteBuffer.hpp:219
ByteBuffer & operator>>(float &value)
Definition: ByteBuffer.hpp:268
ByteBuffer & operator=(ByteBuffer const &right)
Definition: ByteBuffer.hpp:113
ByteBuffer & operator>>(uint64_t &value)
Definition: ByteBuffer.hpp:237
bool is_empty() const
Definition: ByteBuffer.hpp:336
void read_completed(size_t bytes)
Definition: ByteBuffer.hpp:321
T read(size_t pos) const
Definition: ByteBuffer.hpp:386
uint8_t * get_write_pointer()
Definition: ByteBuffer.hpp:328
void hexlike() const
Definition: ByteBuffer.cpp:86
void print_storage() const
Definition: ByteBuffer.cpp:59
void read_skip(size_t skip)
Definition: ByteBuffer.hpp:371
uint8_t const * contents() const
Definition: ByteBuffer.hpp:313
ByteBuffer & operator>>(int8_t &value)
Definition: ByteBuffer.hpp:244
uint8_t * get_read_pointer()
Definition: ByteBuffer.hpp:327
void append(const ByteBuffer &buffer)
Definition: ByteBuffer.hpp:461
void append(T value)
Definition: ByteBuffer.hpp:140
ByteBuffer & operator<<(float value)
Definition: ByteBuffer.hpp:201
ByteBuffer & operator>>(uint32_t &value)
Definition: ByteBuffer.hpp:231
ByteBuffer(ByteBuffer &buf, size_t len)
Definition: ByteBuffer.hpp:99
ByteBuffer & operator<<(uint16_t value)
Definition: ByteBuffer.hpp:157
void append(const T *src, size_t size)
Definition: ByteBuffer.hpp:420
void flush()
Definition: ByteBuffer.hpp:339
ByteBuffer(ByteBuffer &&buf)
Definition: ByteBuffer.hpp:95
void append(const uint8_t *src, size_t cnt)
Definition: ByteBuffer.hpp:432
uint8_t & operator[](size_t const pos)
Definition: ByteBuffer.hpp:284
size_t wpos() const
Definition: ByteBuffer.hpp:324
ByteBuffer & operator<<(int8_t value)
Definition: ByteBuffer.hpp:176
ByteBuffer & operator<<(int64_t value)
Definition: ByteBuffer.hpp:194
uint8_t * contents()
Definition: ByteBuffer.hpp:306
static const size_t DEFAULT_SIZE
Definition: ByteBuffer.hpp:80
void textlike() const
Definition: ByteBuffer.cpp:71
ByteBuffer & operator<<(uint32_t value)
Definition: ByteBuffer.hpp:163
size_t rpos(size_t rpos_)
Definition: ByteBuffer.hpp:300
std::vector< uint8_t > _storage
Definition: ByteBuffer.hpp:495
void read(char *dest, size_t len)
Definition: ByteBuffer.hpp:394
void append(const T *t, size_t t_size, const SubT *sub_t, int count)
Definition: ByteBuffer.hpp:426
void emplace_size(std::size_t pos=2)
Definition: ByteBuffer.hpp:485
ByteBuffer & operator<<(uint8_t value)
Definition: ByteBuffer.hpp:151
void clear()
Definition: ByteBuffer.hpp:128
void write_completed(size_t bytes)
Definition: ByteBuffer.hpp:322
ByteBuffer & operator>>(int64_t &value)
Definition: ByteBuffer.hpp:262
size_t _rpos
Definition: ByteBuffer.hpp:494
ByteBuffer & operator>>(uint16_t &value)
Definition: ByteBuffer.hpp:225
ByteBuffer()
Definition: ByteBuffer.hpp:83
void put(size_t pos, const uint8_t *src, size_t cnt)
Definition: ByteBuffer.hpp:467
ByteBuffer & operator>>(bool &value)
Definition: ByteBuffer.hpp:213
size_t active_length() const
Definition: ByteBuffer.hpp:333
std::string to_string()
Definition: ByteBuffer.hpp:330
ByteBuffer & operator>>(double &value)
Definition: ByteBuffer.hpp:276
void read(ByteBuffer &buf, size_t len)
Definition: ByteBuffer.hpp:402
size_t maximum_length() const
Definition: ByteBuffer.hpp:332
ByteBuffer & operator<<(int32_t value)
Definition: ByteBuffer.hpp:188
T read()
Definition: ByteBuffer.hpp:379
void finish_reading()
Definition: ByteBuffer.hpp:320
ByteBuffer & operator<<(int16_t value)
Definition: ByteBuffer.hpp:182
size_t count(GridTypeListContainer< SPECIFIC_TYPE > const &elements, SPECIFIC_TYPE *)
Definition: GridReferenceContainer.hpp:100