Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
ByteBuffer.inl
Go to the documentation of this file.
1/*
2* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program; if not, write to the Free Software
16* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18/*
19Copyright (c) 2018 DIVIDE-Studio
20Copyright (c) 2009 Ionut Cava
21
22This file is part of DIVIDE Framework.
23
24Permission is hereby granted, free of charge, to any person obtaining a copy of
25this software
26and associated documentation files (the "Software"), to deal in the Software
27without restriction,
28including without limitation the rights to use, copy, modify, merge, publish,
29distribute, sublicense,
30and/or sell copies of the Software, and to permit persons to whom the Software
31is furnished to do so,
32subject to the following conditions:
33
34The above copyright notice and this permission notice shall be included in all
35copies or substantial portions of the Software.
36
37THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38IMPLIED,
39INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
40PARTICULAR PURPOSE AND NONINFRINGEMENT.
41IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
42DAMAGES OR OTHER LIABILITY,
43WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44CONNECTION WITH THE SOFTWARE
45OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46
47*/
48
49#ifndef DVD_CORE_BYTE_BUFFER_INL_
50#define DVD_CORE_BYTE_BUFFER_INL_
51
52namespace Divide
53{
54
55template<class T, size_t N>
56void ByteBuffer::addMarker(const T( &pattern )[N])
57{
58 for (const T& entry : pattern)
59 {
60 append<T>(entry);
61 }
62}
63
64template<class T, size_t N>
65void ByteBuffer::readSkipToMarker(const T( &pattern )[N])
66{
67 T tempMarker{0};
68 bool found = false;
69 do
70 {
71 while (bufferSize() >= sizeof(T) && tempMarker != pattern[0])
72 {
73 read<T>( tempMarker );
74 }
75
76 if (bufferSize() >= sizeof(T))
77 {
78 assert(tempMarker == pattern[0]);
79 found = true;
80 for (size_t i = 1u; i < N; ++i)
81 {
82 read<T>( tempMarker );
83 if (tempMarker != pattern[i])
84 {
85 found = false;
86 break;
87 }
88 }
89 }
90 } while (bufferSize() >= sizeof(T) && !found);
91
92 // We wanted to skip to a marker. None was found so we need to skip to the end!
93 if (!found)
94 {
95 Byte temp{};
96 // Consume a byte at a time until we reach the end.
97 while (!bufferEmpty())
98 {
99 read<Byte>(temp);
100 }
101 }
102}
103
104template <typename T>
105void ByteBuffer::put(const size_t pos, const T& value)
106{
107 put(pos, (Byte*)&value, sizeof(T));
108}
109
110
111template <typename T>
113{
114 append<T>(value);
115 return *this;
116}
117
118template <typename T>
120{
121 read<T>(value);
122 return *this;
123}
124
125template<>
127{
128 I8 temp{};
129 read<I8>(temp);
130 value = temp == I8_ONE;
131 return *this;
132}
133
134template<>
135inline ByteBuffer& ByteBuffer::operator>>(string& value)
136{
137 value.clear();
138
139 char c;
140 while (rpos() < storageSize())
141 {
142 read<char>(c);
143 if (c == U8_ZERO )
144 {
145 break;
146 }
147 value += c;
148 }
149
150 return *this;
151}
152
153template <typename T>
155{
156 readNoSkipFrom<T>(_rpos, value);
157}
158
159template <>
160inline void ByteBuffer::readNoSkip(bool& value) {
161 I8 temp{};
162 readNoSkipFrom<I8>(_rpos, temp);
163 value = temp == I8_ONE;
164}
165
166template <>
167inline void ByteBuffer::readNoSkip(string& value)
168{
169 value.clear();
170 size_t inc = 0;
171
172 char c;
173 // prevent crash at wrong string format in packet
174 while (rpos() < storageSize())
175 {
176 read<char>(c);
177 ++inc;
178 if (c == U8_ZERO )
179 {
180 break;
181 }
182 value += c;
183 }
184
185 _rpos -= inc;
186}
187
188template <>
190{
191 string temp{};
192 readNoSkip(temp);
193 value = ResourcePath(temp);
194}
195
196template <typename U>
198{
199 readSkip<U>();
200 return *this;
201}
202
203template <typename T>
205{
206 readSkip(sizeof(T));
207}
208
209template <>
210inline void ByteBuffer::readSkip<char *>()
211{
212 string temp;
213 *this >> temp;
214}
215
216template <>
217inline void ByteBuffer::readSkip<char const *>()
218{
219 readSkip<char *>();
220}
221
222template <>
223inline void ByteBuffer::readSkip<string>()
224{
225 readSkip<char *>();
226}
227
228inline void ByteBuffer::readSkip(const size_t skip) noexcept
229{
230 if (_rpos + skip > storageSize())
231 {
233 }
234
235 _rpos += skip;
236}
237
238template <typename T>
240{
241 readNoSkipFrom<T>(_rpos, out);
242 _rpos += sizeof(T);
243}
244
245template <typename T>
246void ByteBuffer::readNoSkipFrom(const size_t pos, T& out) const
247{
248 if (pos + sizeof(T) > storageSize())
249 {
251 }
252
253 std::memcpy(&out, &_storage[pos], sizeof(T));
254}
255
256inline void ByteBuffer::read(Byte *dest, const size_t len)
257{
258 if (_rpos + len > storageSize())
259 {
261 }
262
263 memcpy(dest, &_storage[_rpos], len);
264 _rpos += len;
265}
266
267inline void ByteBuffer::readPackXYZ(F32& x, F32& y, F32& z)
268{
269 U32 packed = 0;
270 *this >> packed;
271 x = ((packed & 0x7FF) << 21 >> 21) * 0.25f;
272 y = ((packed >> 11 & 0x7FF) << 21 >> 21) * 0.25f;
273 z = (packed >> 22 << 22 >> 22) * 0.25f;
274}
275
277{
278 U64 guid = 0;
279 U8 guidmark = 0;
280 *this >> guidmark;
281
282 for (I32 i = 0; i < 8; ++i)
283 {
284 if (guidmark & U8_ONE << i)
285 {
286 U8 bit;
287 *this >> bit;
288 guid |= static_cast<U64>(bit) << i * 8;
289 }
290 }
291
292 return guid;
293}
294
295
296inline void ByteBuffer::appendPackXYZ(const F32 x, const F32 y, const F32 z)
297{
298 U32 packed = 0u;
299 packed |= to_U32( to_I32(x / 0.25f) & 0x7FF);
300 packed |= to_U32((to_I32(y / 0.25f) & 0x7FF) << 11);
301 packed |= to_U32((to_I32(z / 0.25f) & 0x3FF) << 22);
302 *this << packed;
303}
304
306{
307 U8 packGUID[8 + 1];
308 packGUID[0] = 0u;
309 size_t size = 1;
310 for (U8 i = 0; guid != 0; ++i)
311 {
312 if (guid & 0xFF)
313 {
314 packGUID[0] |= U8_ONE << i;
315 packGUID[size] = to_U8(guid & 0xFF);
316 ++size;
317 }
318
319 guid >>= 8;
320 }
321
322 append(packGUID, size);
323}
324
325inline Byte ByteBuffer::operator[](const size_t pos) const{
326 Byte ret{};
327 readNoSkipFrom<Byte>( pos, ret );
328 return ret;
329}
330
331inline size_t ByteBuffer::rpos() const noexcept {
332 return _rpos;
333}
334
335inline size_t ByteBuffer::rpos(const size_t rpos_) noexcept {
336 _rpos = rpos_;
337 return _rpos;
338}
339
340inline size_t ByteBuffer::wpos() const noexcept {
341 return _wpos;
342}
343
344inline size_t ByteBuffer::wpos(const size_t wpos_) noexcept {
345 _wpos = wpos_;
346 return _wpos;
347}
348
349inline size_t ByteBuffer::bufferSize() const noexcept {
350 return _wpos >= _rpos ? _wpos - _rpos : 0u;
351}
352
353inline bool ByteBuffer::bufferEmpty() const noexcept {
354 return bufferSize() == 0u;
355}
356
357inline size_t ByteBuffer::storageSize() const noexcept {
358 return _storage.size();
359}
360
361inline bool ByteBuffer::storageEmpty() const noexcept {
362 return _storage.empty();
363}
364
365inline void ByteBuffer::resize(const size_t newsize) {
366 _storage.resize(newsize);
367 _rpos = 0;
368 _wpos = storageSize();
369}
370
371inline void ByteBuffer::reserve(const size_t resize) {
372 if (resize > storageSize()) {
373 _storage.reserve(resize);
374 }
375}
376
377inline const Byte* ByteBuffer::contents() const noexcept {
378 return _storage.data();
379}
380
381inline void ByteBuffer::put(const size_t pos, const Byte *src, const size_t cnt) {
382 if (pos + cnt > storageSize()) {
384 }
385 memcpy(&_storage[pos], src, cnt);
386}
387
388template <typename T>
389void ByteBuffer::append(const T& value) {
390 append((const Byte*)&value, sizeof(T));
391}
392
393template <typename T>
394void ByteBuffer::append(const T* src, const size_t cnt) {
395 return append((const Byte*)src, cnt * sizeof(T));
396}
397
398
399template<>
400inline void ByteBuffer::append(const string& str) {
401 append(str.c_str(), str.length());
403}
404
405template<>
406inline void ByteBuffer::append(const ResourcePath& str) {
407 append(str.string() );
408}
409
410template<>
411inline void ByteBuffer::append(const bool& value) {
412 append(value ? I8_ONE : I8_ZERO);
413}
414
415template<>
416inline void ByteBuffer::append(const ByteBuffer& buffer) {
417 if (buffer.wpos()) {
418 append(buffer.contents(), buffer.wpos());
419 }
420}
421
422//specializations
423template <typename T>
425 b << v.x;
426 b << v.y;
427 return b;
428}
429
430template <typename T>
432 b >> v.x;
433 b >> v.y;
434 return b;
435}
436
437template <typename T>
439 b << v.x;
440 b << v.y;
441 b << v.z;
442 return b;
443}
444
445template <typename T>
447 b >> v.x;
448 b >> v.y;
449 b >> v.z;
450 return b;
451}
452
453template <typename T>
455 b << v.x;
456 b << v.y;
457 b << v.z;
458 b << v.w;
459 return b;
460}
461
462template <typename T>
464 b >> v.x;
465 b >> v.y;
466 b >> v.z;
467 b >> v.w;
468 return b;
469}
470template <typename T>
472 b << q.X();
473 b << q.Y();
474 b << q.Z();
475 b << q.W();
476 return b;
477}
478
479template <typename T>
481 vec4<T> elems = {};
482 b >> elems.x; q.X(elems.x);
483 b >> elems.y; q.Y(elems.y);
484 b >> elems.z; q.Z(elems.z);
485 b >> elems.w; q.W(elems.w);
486
487 return b;
488}
489
490template <typename T>
492 for (U8 i = 0; i < 4; ++i) {
493 b << m[i];
494 }
495
496 return b;
497}
498
499template <typename T>
501 for (U8 i = 0; i < 4; ++i) {
502 b >> m[i];
503 }
504
505 return b;
506}
507
508template <typename T>
510 for (U8 i = 0; i < 9; ++i) {
511 b << m[i];
512 }
513
514 return b;
515}
516
517template <typename T>
519 for (U8 i = 0; i < 9; ++i) {
520 b >> m[i];
521 }
522
523 return b;
524}
525
526template <typename T>
528 for (U8 i = 0; i < 16; ++i) {
529 b << m[i];
530 }
531
532 return b;
533}
534
535template <typename T>
537 for (U8 i = 0; i < 16; ++i) {
538 b >> m[i];
539 }
540
541 return b;
542}
543template <typename T, size_t N>
544inline ByteBuffer &operator<<(ByteBuffer &b, const std::array<T, N>& v) {
545 b << static_cast<U64>(N);
546 b.append(v.data(), N);
547
548 return b;
549}
550
551template <typename T, size_t N>
552inline ByteBuffer &operator>>(ByteBuffer &b, std::array<T, N>& a) {
553 U64 size;
554 b >> size;
555 assert(size == static_cast<U64>(N));
556 b.read((Byte*)a.data(), N * sizeof(T));
557
558 return b;
559}
560
561template <size_t N>
562inline ByteBuffer &operator<<(ByteBuffer &b, const std::array<string, N>& a) {
563 b << static_cast<U64>(N);
564 for (const string& str : a) {
565 b << str;
566 }
567
568 return b;
569}
570
571template <size_t N>
572inline ByteBuffer &operator>>(ByteBuffer &b, std::array<string, N>& a) {
573 U64 size;
574 b >> size;
575 assert(size == static_cast<U64>(N));
576 for (string& str : a) {
577 b >> str;
578 }
579
580 return b;
581}
582
583template <typename T>
585 b << to_U32(v.size());
586 b.append(v.data(), v.size());
587
588 return b;
589}
590
591template <typename T>
593 U32 vsize;
594 b >> vsize;
595 v.resize(vsize);
596 b.read((Byte*)v.data(), vsize * sizeof(T));
597 return b;
598}
599
600template <>
602 b << to_U32(v.size());
603 for (const string& str : v) {
604 b << str;
605 }
606
607 return b;
608}
609
610template <>
612 U32 vsize;
613 b >> vsize;
614 v.resize(vsize);
615 for (string& str : v) {
616 b >> str;
617 }
618 return b;
619}
620template <typename T>
621inline ByteBuffer &operator<<(ByteBuffer &b, const std::list<T>& v) {
622 b << to_U32(v.size());
623 for (const T& i : v) {
624 b << i;
625 }
626 return b;
627}
628
629template <typename T>
630inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v) {
631 T t;
632 U32 vsize;
633 b >> vsize;
634 v.clear();
635 v.reverse(vsize);
636 while (vsize--) {
637 b >> t;
638 v.push_back(t);
639 }
640 return b;
641}
642
643template <typename K, typename V>
644inline ByteBuffer &operator<<(ByteBuffer &b, const eastl::map<K, V>& m) {
645 b << to_U32(m.size());
646 for (typename eastl::map<K, V>::value_type i : m) {
647 b << i.first;
648 b << i.second;
649 }
650 return b;
651}
652
653template <typename K, typename V>
654inline ByteBuffer &operator>>(ByteBuffer &b, eastl::map<K, V>& m) {
655 K k;
656 V v;
657 U32 msize;
658 b >> msize;
659 m.clear();
660 while (msize--) {
661 b >> k >> v;
662 m.insert(eastl::make_pair(k, v));
663 }
664 return b;
665}
666
668{
669 b << p.string();
670
671 return b;
672}
673
675{
676 string temp{};
677 b >> temp;
678 p = ResourcePath(temp);
679
680 return b;
681}
682
683template<size_t N>
684inline ByteBuffer& operator<<( ByteBuffer& b, const Str<N>& s )
685{
686 const string temp{ s.c_str() };
687 b << temp;
688
689 return b;
690}
691
692template<size_t N>
694{
695 string temp{};
696
697 b >> temp;
698 s = temp.c_str();
699
700 return b;
701}
702
703}
704
705#endif //DVD_CORE_BYTE_BUFFER_INL_
#define DIVIDE_UNEXPECTED_CALL()
ByteBuffer & operator<<(const T &value)
Appends 'value' to the buffer.
Definition: ByteBuffer.inl:112
size_t storageSize() const noexcept
Returns the total size (in bytes) of the underlying storage, regardles of wpos and rpos.
Definition: ByteBuffer.inl:357
void readNoSkip(T &value)
Reads sizeof(T) data from the buffer and saves it into 'value' but does NOT move the read head forwar...
Definition: ByteBuffer.inl:154
void readSkipToMarker(const T(&pattern)[N])
Skip (consume) everything in the buffer until we find the specified list of items....
Definition: ByteBuffer.inl:65
U64 readPackGUID()
Reads a packed U64 from the buffer and returns it. Reading moves the read head forward!
Definition: ByteBuffer.inl:276
const Byte * contents() const noexcept
Returns a raw pointer to the underlying storage data. Does NOT depend on the read head position!...
Definition: ByteBuffer.inl:377
size_t rpos() const noexcept
Returns the current read head position.
Definition: ByteBuffer.inl:331
void readNoSkipFrom(size_t pos, T &out) const
Reads sizeof(T) data from the buffer and returns it but does NOT move the read head forward!
Definition: ByteBuffer.inl:246
void resize(size_t newsize)
Resizes the underlying storage to 'newsize' bytes and resets the read and write head positions.
Definition: ByteBuffer.inl:365
void append(const Byte *src, size_t cnt)
Appends 'cnt' bytes from 'src' to the buffer.
Definition: ByteBuffer.cpp:33
void read(T &out)
Reads sizeof(T) data from the buffer and returns it. Reading moves the read head forward!
Definition: ByteBuffer.inl:239
size_t wpos() const noexcept
Returns the current write head position.
Definition: ByteBuffer.inl:340
void clear() noexcept
Resets the entire storage and the read and write positions.
Definition: ByteBuffer.cpp:28
bool storageEmpty() const noexcept
Returns true if the underlying storage is empty, regardless of wpos and rpos.
Definition: ByteBuffer.inl:361
vector< Byte > _storage
Definition: ByteBuffer.h:193
ByteBuffer & operator>>(T &value)
Reads sizeof(T) data from the buffer and saves its contents into 'value'. Reading moves the read head...
Definition: ByteBuffer.inl:119
void appendPackXYZ(F32 x, F32 y, F32 z)
Packes x,y and z into a single U32 and appends it to the buffer.
Definition: ByteBuffer.inl:296
void addMarker(const T(&pattern)[N])
Add a specific list of items in order to mark a special point in the buffer. Can be used for skipping...
Definition: ByteBuffer.inl:56
size_t bufferSize() const noexcept
Returns the size (in bytes) of the data inside of the buffer (wpos - rpos)
Definition: ByteBuffer.inl:349
void readSkip()
Moves the read head sizeof(T) units forward.
Definition: ByteBuffer.inl:204
void put(size_t pos, const T &value)
Inserts 'value' at the specified position overriding any existing data at that location....
Definition: ByteBuffer.inl:105
void appendPackGUID(U64 guid)
Packes guid into a multiple I32s and appends them to the buffer.
Definition: ByteBuffer.inl:305
Byte operator[](size_t pos) const
Read the byte at position 'pos' from the buffer without moving the read head.
Definition: ByteBuffer.inl:325
void reserve(size_t resize)
Reserves 'resize' bytes of additional storage in the underlying storage structure without changing th...
Definition: ByteBuffer.inl:371
void readPackXYZ(F32 &x, F32 &y, F32 &z)
Reads a packed U32 from the buffer and unpackes it into x,y,z. Reading moves the read head forward!
Definition: ByteBuffer.inl:267
bool bufferEmpty() const noexcept
Returns true if the read position and the write position are identical.
Definition: ByteBuffer.inl:353
T X() const noexcept
Definition: Quaternion.inl:608
T Y() const noexcept
Definition: Quaternion.inl:613
T Z() const noexcept
Definition: Quaternion.inl:618
T W() const noexcept
Definition: Quaternion.inl:623
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
std::byte Byte
constexpr U32 to_U32(const T value)
constexpr I8 I8_ZERO
int32_t I32
uint8_t U8
eastl::vector< Type > vector
Definition: Vector.h:42
ByteBuffer & operator<<(ByteBuffer &b, const vec2< T > &v)
Definition: ByteBuffer.inl:424
ByteBuffer & operator>>(ByteBuffer &b, vec2< T > &v)
Definition: ByteBuffer.inl:431
constexpr U8 to_U8(const T value)
constexpr I8 I8_ONE
constexpr U8 U8_ONE
constexpr I32 to_I32(const T value)
uint32_t U32
Project const SceneEntry & entry
Definition: DefaultScene.h:41
uint64_t U64
constexpr U8 U8_ZERO
StringReturnType< N > string() const noexcept
Definition: ResourcePath.h:64
Helper for using >> instead of readSkip()
Definition: ByteBuffer.h:68