Cuberite
A lightweight, fast and extensible game server for Minecraft
ByteBuffer.cpp
Go to the documentation of this file.
1 
2 // ByteBuffer.cpp
3 
4 // Implements the cByteBuffer class representing a ringbuffer of bytes
5 
6 #include "Globals.h"
7 
8 #include "ByteBuffer.h"
9 #include "Endianness.h"
10 #include "UUID.h"
11 #include "OSSupport/IsThread.h"
12 
13 
14 
15 
16 
20 // #define DEBUG_SINGLE_THREAD_ACCESS
21 
22 
23 
24 
25 
26 // If a string sent over the protocol is larger than this, a warning is emitted to the console
27 #define MAX_STRING_SIZE (512 KiB)
28 
29 #define NEEDBYTES(Num) if (!CanReadBytes(Num)) return false // Check if at least Num bytes can be read from the buffer, return false if not
30 #define PUTBYTES(Num) if (!CanWriteBytes(Num)) return false // Check if at least Num bytes can be written to the buffer, return false if not
31 
32 
33 
34 
35 
36 #ifdef DEBUG_SINGLE_THREAD_ACCESS
37 
41  class cSingleThreadAccessChecker
42  {
43  public:
44  cSingleThreadAccessChecker(std::thread::id * a_ThreadID) :
45  m_ThreadID(a_ThreadID)
46  {
47  ASSERT(
48  (*a_ThreadID == std::this_thread::get_id()) || // Either the object is used by current thread...
49  (*a_ThreadID == m_EmptyThreadID) // ... or by no thread at all
50  );
51 
52  // Mark as being used by this thread:
53  *m_ThreadID = std::this_thread::get_id();
54  }
55 
56  ~cSingleThreadAccessChecker()
57  {
58  // Mark as not being used by any thread:
59  *m_ThreadID = std::thread::id();
60  }
61 
62  protected:
64  std::thread::id * m_ThreadID;
65 
67  static std::thread::id m_EmptyThreadID;
68  };
69 
70  std::thread::id cSingleThreadAccessChecker::m_EmptyThreadID;
71 
72  #define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID);
73 
74 #else
75  #define CHECK_THREAD
76 #endif
77 
78 
79 
80 
81 
83 // cByteBuffer:
84 
85 cByteBuffer::cByteBuffer(size_t a_BufferSize) :
86  m_Buffer(new std::byte[a_BufferSize + 1]),
87  m_BufferSize(a_BufferSize + 1),
88  m_DataStart(0),
89  m_WritePos(0),
90  m_ReadPos(0)
91 {
92  // Allocating one byte more than the buffer size requested, so that we can distinguish between
93  // completely-full and completely-empty states
94 }
95 
96 
97 
98 
99 
101 {
102  CheckValid();
103  delete[] m_Buffer;
104  m_Buffer = nullptr;
105 }
106 
107 
108 
109 
110 
111 bool cByteBuffer::Write(const void * a_Bytes, size_t a_Count)
112 {
114  CheckValid();
115 
116  // Store the current free space for a check after writing:
117  size_t CurFreeSpace = GetFreeSpace();
118  #ifndef NDEBUG
119  size_t CurReadableSpace = GetReadableSpace();
120  size_t WrittenBytes = 0;
121  #endif
122 
123  if (CurFreeSpace < a_Count)
124  {
125  return false;
126  }
128  size_t TillEnd = m_BufferSize - m_WritePos;
129  const char * Bytes = static_cast<const char *>(a_Bytes);
130  if (TillEnd <= a_Count)
131  {
132  // Need to wrap around the ringbuffer end
133  if (TillEnd > 0)
134  {
135  memcpy(m_Buffer + m_WritePos, Bytes, TillEnd);
136  Bytes += TillEnd;
137  a_Count -= TillEnd;
138  #ifndef NDEBUG
139  WrittenBytes = TillEnd;
140  #endif
141  }
142  m_WritePos = 0;
143  }
144 
145  // We're guaranteed that we'll fit in a single write op
146  if (a_Count > 0)
147  {
148  memcpy(m_Buffer + m_WritePos, Bytes, a_Count);
149  m_WritePos += a_Count;
150  #ifndef NDEBUG
151  WrittenBytes += a_Count;
152  #endif
153  }
154 
155  ASSERT(GetFreeSpace() == CurFreeSpace - WrittenBytes);
156  ASSERT(GetReadableSpace() == CurReadableSpace + WrittenBytes);
157  return true;
158 }
159 
160 
161 
162 
163 
164 size_t cByteBuffer::GetFreeSpace(void) const
165 {
167  CheckValid();
168  if (m_WritePos >= m_DataStart)
169  {
170  // Wrap around the buffer end:
173  return m_BufferSize - m_WritePos + m_DataStart - 1;
174  }
175  // Single free space partition:
178  return m_DataStart - m_WritePos - 1;
179 }
180 
181 
182 
183 
184 
185 size_t cByteBuffer::GetUsedSpace(void) const
186 {
188  CheckValid();
190  ASSERT((m_BufferSize - GetFreeSpace()) >= 1);
191  return m_BufferSize - GetFreeSpace() - 1;
192 }
193 
194 
195 
196 
197 
199 {
201  CheckValid();
202  if (m_ReadPos > m_WritePos)
203  {
204  // Wrap around the buffer end:
206  return m_BufferSize - m_ReadPos + m_WritePos;
207  }
208  // Single readable space partition:
210  return m_WritePos - m_ReadPos;
211 }
212 
213 
214 
215 
216 
217 bool cByteBuffer::CanReadBytes(size_t a_Count) const
218 {
220  CheckValid();
221  return (a_Count <= GetReadableSpace());
222 }
223 
224 
225 
226 
227 
228 bool cByteBuffer::CanWriteBytes(size_t a_Count) const
229 {
231  CheckValid();
232  return (a_Count <= GetFreeSpace());
233 }
234 
235 
236 
237 
238 
240 {
242  CheckValid();
243  NEEDBYTES(1);
244  ReadBuf(&a_Value, 1);
245  return true;
246 }
247 
248 
249 
250 
251 
253 {
255  CheckValid();
256  NEEDBYTES(1);
257  ReadBuf(&a_Value, 1);
258  return true;
259 }
260 
261 
262 
263 
264 
266 {
268  CheckValid();
269  NEEDBYTES(2);
270  UInt16 val;
271  ReadBuf(&val, 2);
272  val = ntohs(val);
273  memcpy(&a_Value, &val, 2);
274  return true;
275 }
276 
277 
278 
279 
280 
282 {
284  CheckValid();
285  NEEDBYTES(2);
286  ReadBuf(&a_Value, 2);
287  a_Value = ntohs(a_Value);
288  return true;
289 }
290 
291 
292 
293 
294 
296 {
298  CheckValid();
299  NEEDBYTES(4);
300  UInt32 val;
301  ReadBuf(&val, 4);
302  val = ntohl(val);
303  memcpy(&a_Value, &val, 4);
304  return true;
305 }
306 
307 
308 
309 
310 
312 {
314  CheckValid();
315  NEEDBYTES(4);
316  ReadBuf(&a_Value, 4);
317  a_Value = ntohl(a_Value);
318  return true;
319 }
320 
321 
322 
323 
324 
326 {
328  CheckValid();
329  NEEDBYTES(8);
330  ReadBuf(&a_Value, 8);
331  a_Value = NetworkToHostLong8(&a_Value);
332  return true;
333 }
334 
335 
336 
337 
338 
340 {
342  CheckValid();
343  NEEDBYTES(8);
344  ReadBuf(&a_Value, 8);
345  a_Value = NetworkToHostULong8(&a_Value);
346  return true;
347 }
348 
349 
350 
351 
352 
353 bool cByteBuffer::ReadBEFloat(float & a_Value)
354 {
356  CheckValid();
357  NEEDBYTES(4);
358  ReadBuf(&a_Value, 4);
359  a_Value = NetworkToHostFloat4(&a_Value);
360  return true;
361 }
362 
363 
364 
365 
366 
367 bool cByteBuffer::ReadBEDouble(double & a_Value)
368 {
370  CheckValid();
371  NEEDBYTES(8);
372  ReadBuf(&a_Value, 8);
373  a_Value = NetworkToHostDouble8(&a_Value);
374  return true;
375 }
376 
377 
378 
379 
380 
381 bool cByteBuffer::ReadBool(bool & a_Value)
382 {
384  CheckValid();
385  NEEDBYTES(1);
386  UInt8 Value = 0;
387  ReadBuf(&Value, 1);
388  a_Value = (Value != 0);
389  return true;
390 }
391 
392 
393 
394 
395 
397 {
399  CheckValid();
400  UInt32 Value = 0;
401  int Shift = 0;
402  unsigned char b = 0;
403  do
404  {
405  NEEDBYTES(1);
406  ReadBuf(&b, 1);
407  Value = Value | ((static_cast<UInt32>(b & 0x7f)) << Shift);
408  Shift += 7;
409  } while ((b & 0x80) != 0);
410  a_Value = Value;
411  return true;
412 }
413 
414 
415 
416 
417 
419 {
421  CheckValid();
422  UInt64 Value = 0;
423  int Shift = 0;
424  unsigned char b = 0;
425  do
426  {
427  NEEDBYTES(1);
428  ReadBuf(&b, 1);
429  Value = Value | ((static_cast<UInt64>(b & 0x7f)) << Shift);
430  Shift += 7;
431  } while ((b & 0x80) != 0);
432  a_Value = Value;
433  return true;
434 }
435 
436 
437 
438 
439 
441 {
443  CheckValid();
444  UInt32 Size = 0;
445  if (!ReadVarInt(Size))
446  {
447  return false;
448  }
449  if (Size > MAX_STRING_SIZE)
450  {
451  LOGWARNING("%s: String too large: %u (%u KiB)", __FUNCTION__, Size, Size / 1024);
452  }
453  ContiguousByteBuffer Buffer;
454  if (!ReadSome(Buffer, static_cast<size_t>(Size)))
455  {
456  return false;
457  }
458  // "Convert" a UTF-8 encoded string into system-native char.
459  // This isn't great, better would be to use codecvt:
460  a_Value = { reinterpret_cast<const char *>(Buffer.data()), Buffer.size() };
461  return true;
462 }
463 
464 
465 
466 
467 
468 bool cByteBuffer::ReadLEInt(int & a_Value)
469 {
471  CheckValid();
472  NEEDBYTES(4);
473  ReadBuf(&a_Value, 4);
474 
475  #ifdef IS_BIG_ENDIAN
476  // Convert:
477  a_Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000);
478  #endif
479 
480  return true;
481 }
482 
483 
484 
485 
486 
487 bool cByteBuffer::ReadXYZPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
488 {
490  UInt64 Value;
491  if (!ReadBEUInt64(Value))
492  {
493  return false;
494  }
495 
496  // Convert the 64 received bits into 3 coords:
497  UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits
498  UInt32 BlockYRaw = (Value >> 26) & 0x0fff; // Middle 12 bits
499  UInt32 BlockZRaw = (Value & 0x03ffffff); // Bottom 26 bits
500 
501  // If the highest bit in the number's range is set, convert the number into negative:
502  a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : -(0x04000000 - static_cast<int>(BlockXRaw));
503  a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : -(0x01000 - static_cast<int>(BlockYRaw));
504  a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : -(0x04000000 - static_cast<int>(BlockZRaw));
505  return true;
506 }
507 
508 
509 
510 
511 
513 {
514  return ReadXYZPosition64(a_Position.x, a_Position.y, a_Position.z);
515 }
516 
517 
518 
519 
520 
521 bool cByteBuffer::ReadXZYPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
522 {
524  UInt64 Value;
525  if (!ReadBEUInt64(Value))
526  {
527  return false;
528  }
529 
530  // Convert the 64 received bits into 3 coords:
531  UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits
532  UInt32 BlockZRaw = (Value >> 12) & 0x03ffffff; // Middle 26 bits
533  UInt32 BlockYRaw = (Value & 0x0fff); // Bottom 12 bits
534 
535  // If the highest bit in the number's range is set, convert the number into negative:
536  a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : (static_cast<int>(BlockXRaw) - 0x04000000);
537  a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : (static_cast<int>(BlockYRaw) - 0x01000);
538  a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : (static_cast<int>(BlockZRaw) - 0x04000000);
539  return true;
540 }
541 
542 
543 
544 
545 
547 {
548  return ReadXZYPosition64(a_Position.x, a_Position.y, a_Position.z);
549 }
550 
551 
552 
553 
554 
556 {
558 
559  std::array<Byte, 16> UUIDBuf;
560  if (!ReadBuf(UUIDBuf.data(), UUIDBuf.size()))
561  {
562  return false;
563  }
564 
565  a_Value.FromRaw(UUIDBuf);
566  return true;
567 }
568 
569 
570 
571 
572 
574 {
576  CheckValid();
577  PUTBYTES(1);
578  return WriteBuf(&a_Value, 1);
579 }
580 
581 
582 
583 
584 
585 bool cByteBuffer::WriteBEInt8(const std::byte a_Value)
586 {
588  CheckValid();
589  PUTBYTES(1);
590  return WriteBuf(&a_Value, 1);
591 }
592 
593 
594 
595 
596 
598 {
600  CheckValid();
601  PUTBYTES(1);
602  return WriteBuf(&a_Value, 1);
603 }
604 
605 
606 
607 
608 
610 {
612  CheckValid();
613  PUTBYTES(2);
614  UInt16 val;
615  memcpy(&val, &a_Value, 2);
616  val = htons(val);
617  return WriteBuf(&val, 2);
618 }
619 
620 
621 
622 
623 
625 {
627  CheckValid();
628  PUTBYTES(2);
629  a_Value = htons(a_Value);
630  return WriteBuf(&a_Value, 2);
631 }
632 
633 
634 
635 
636 
638 {
640  CheckValid();
641  PUTBYTES(4);
642  UInt32 Converted = HostToNetwork4(&a_Value);
643  return WriteBuf(&Converted, 4);
644 }
645 
646 
647 
648 
649 
651 {
653  CheckValid();
654  PUTBYTES(4);
655  UInt32 Converted = HostToNetwork4(&a_Value);
656  return WriteBuf(&Converted, 4);
657 }
658 
659 
660 
661 
662 
664 {
666  CheckValid();
667  PUTBYTES(8);
668  UInt64 Converted = HostToNetwork8(&a_Value);
669  return WriteBuf(&Converted, 8);
670 }
671 
672 
673 
674 
675 
677 {
679  CheckValid();
680  PUTBYTES(8);
681  UInt64 Converted = HostToNetwork8(&a_Value);
682  return WriteBuf(&Converted, 8);
683 }
684 
685 
686 
687 
688 
689 bool cByteBuffer::WriteBEFloat(float a_Value)
690 {
692  CheckValid();
693  PUTBYTES(4);
694  UInt32 Converted = HostToNetwork4(&a_Value);
695  return WriteBuf(&Converted, 4);
696 }
697 
698 
699 
700 
701 
702 bool cByteBuffer::WriteBEDouble(double a_Value)
703 {
705  CheckValid();
706  PUTBYTES(8);
707  UInt64 Converted = HostToNetwork8(&a_Value);
708  return WriteBuf(&Converted, 8);
709 }
710 
711 
712 
713 
714 
715 bool cByteBuffer::WriteBool(bool a_Value)
716 {
718  CheckValid();
719  UInt8 val = a_Value ? 1 : 0;
720  return Write(&val, 1);
721 }
722 
723 
724 
725 
726 
728 {
730  CheckValid();
731 
732  // A 32-bit integer can be encoded by at most 5 bytes:
733  unsigned char b[5];
734  size_t idx = 0;
735  do
736  {
737  b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
738  a_Value = a_Value >> 7;
739  idx++;
740  } while (a_Value > 0);
741 
742  return WriteBuf(b, idx);
743 }
744 
745 
746 
747 
748 
750 {
752  CheckValid();
753 
754  // A 64-bit integer can be encoded by at most 10 bytes:
755  unsigned char b[10];
756  size_t idx = 0;
757  do
758  {
759  b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
760  a_Value = a_Value >> 7;
761  idx++;
762  } while (a_Value > 0);
763 
764  return WriteBuf(b, idx);
765 }
766 
767 
768 
769 
770 
772 {
774  CheckValid();
775  PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early.
776  bool res = WriteVarInt32(static_cast<UInt32>(a_Value.size()));
777  if (!res)
778  {
779  return false;
780  }
781  return WriteBuf(a_Value.data(), a_Value.size());
782 }
783 
784 
785 
786 
787 
788 bool cByteBuffer::WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
789 {
791  CheckValid();
792  return WriteBEUInt64(
793  ((static_cast<UInt64>(a_BlockX) & 0x3FFFFFF) << 38) |
794  ((static_cast<UInt64>(a_BlockY) & 0xFFF) << 26) |
795  (static_cast<UInt64>(a_BlockZ) & 0x3FFFFFF)
796  );
797 }
798 
799 
800 
801 
802 
803 bool cByteBuffer::WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
804 {
806  CheckValid();
807  return WriteBEUInt64(
808  ((static_cast<UInt64>(a_BlockX) & 0x3FFFFFF) << 38) |
809  ((static_cast<UInt64>(a_BlockZ) & 0x3FFFFFF) << 12) |
810  (static_cast<UInt64>(a_BlockY) & 0xFFF)
811  );
812 }
813 
814 
815 
816 
817 
818 bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count)
819 {
821  CheckValid();
822  NEEDBYTES(a_Count);
823  char * Dst = static_cast<char *>(a_Buffer); // So that we can do byte math
825  size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos;
826  if (BytesToEndOfBuffer <= a_Count)
827  {
828  // Reading across the ringbuffer end, read the first part and adjust parameters:
829  if (BytesToEndOfBuffer > 0)
830  {
831  memcpy(Dst, m_Buffer + m_ReadPos, BytesToEndOfBuffer);
832  Dst += BytesToEndOfBuffer;
833  a_Count -= BytesToEndOfBuffer;
834  }
835  m_ReadPos = 0;
836  }
837 
838  // Read the rest of the bytes in a single read (guaranteed to fit):
839  if (a_Count > 0)
840  {
841  memcpy(Dst, m_Buffer + m_ReadPos, a_Count);
842  m_ReadPos += a_Count;
843  }
844  return true;
845 }
846 
847 
848 
849 
850 
851 bool cByteBuffer::WriteBuf(const void * a_Buffer, size_t a_Count)
852 {
854  CheckValid();
855  PUTBYTES(a_Count);
856  const char * Src = static_cast<const char *>(a_Buffer); // So that we can do byte math
858  size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos;
859  if (BytesToEndOfBuffer <= a_Count)
860  {
861  // Reading across the ringbuffer end, read the first part and adjust parameters:
862  memcpy(m_Buffer + m_WritePos, Src, BytesToEndOfBuffer);
863  Src += BytesToEndOfBuffer;
864  a_Count -= BytesToEndOfBuffer;
865  m_WritePos = 0;
866  }
867 
868  // Read the rest of the bytes in a single read (guaranteed to fit):
869  if (a_Count > 0)
870  {
871  memcpy(m_Buffer + m_WritePos, Src, a_Count);
872  m_WritePos += a_Count;
873  }
874  return true;
875 }
876 
877 
878 
879 
880 
881 bool cByteBuffer::WriteBuf(size_t a_Count, unsigned char a_Value)
882 {
884  CheckValid();
885  PUTBYTES(a_Count);
887  size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos;
888  if (BytesToEndOfBuffer <= a_Count)
889  {
890  // Reading across the ringbuffer end, read the first part and adjust parameters:
891  memset(m_Buffer + m_WritePos, a_Value, BytesToEndOfBuffer);
892  a_Count -= BytesToEndOfBuffer;
893  m_WritePos = 0;
894  }
895 
896  // Read the rest of the bytes in a single read (guaranteed to fit):
897  if (a_Count > 0)
898  {
899  memset(m_Buffer + m_WritePos, a_Value, a_Count);
900  m_WritePos += a_Count;
901  }
902  return true;
903 }
904 
905 
906 
907 
908 
909 bool cByteBuffer::ReadSome(ContiguousByteBuffer & a_String, size_t a_Count)
910 {
912  CheckValid();
913  NEEDBYTES(a_Count);
914  a_String.clear();
915  a_String.reserve(a_Count);
917  size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos;
918  if (BytesToEndOfBuffer <= a_Count)
919  {
920  // Reading across the ringbuffer end, read the first part and adjust parameters:
921  if (BytesToEndOfBuffer > 0)
922  {
923  a_String.assign(m_Buffer + m_ReadPos, BytesToEndOfBuffer);
924  ASSERT(a_Count >= BytesToEndOfBuffer);
925  a_Count -= BytesToEndOfBuffer;
926  }
927  m_ReadPos = 0;
928  }
929 
930  // Read the rest of the bytes in a single read (guaranteed to fit):
931  if (a_Count > 0)
932  {
933  a_String.append(m_Buffer + m_ReadPos, a_Count);
934  m_ReadPos += a_Count;
935  }
936  return true;
937 }
938 
939 
940 
941 
942 
943 bool cByteBuffer::SkipRead(size_t a_Count)
944 {
946  CheckValid();
947  if (!CanReadBytes(a_Count))
948  {
949  return false;
950  }
951  AdvanceReadPos(a_Count);
952  return true;
953 }
954 
955 
956 
957 
958 
960 {
962  CheckValid();
963  ReadSome(a_Data, GetReadableSpace());
964 }
965 
966 
967 
968 
969 
970 bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes)
971 {
973  if (!a_Dst.CanWriteBytes(a_NumBytes) || !CanReadBytes(a_NumBytes))
974  {
975  // There's not enough source bytes or space in the dest BB
976  return false;
977  }
978  char buf[1024];
979  // > 0 without generating warnings about unsigned comparisons where size_t is unsigned
980  while (a_NumBytes != 0)
981  {
982  size_t num = (a_NumBytes > sizeof(buf)) ? sizeof(buf) : a_NumBytes;
983  VERIFY(ReadBuf(buf, num));
984  VERIFY(a_Dst.Write(buf, num));
985  ASSERT(a_NumBytes >= num);
986  a_NumBytes -= num;
987  }
988  return true;
989 }
990 
991 
992 
993 
994 
996 {
998  CheckValid();
1000 }
1001 
1002 
1003 
1004 
1005 
1007 {
1008  CHECK_THREAD
1009  CheckValid();
1011 }
1012 
1013 
1014 
1015 
1016 
1018 {
1019  // Return the data between m_DataStart and m_ReadPos (the data that has been read but not committed)
1020  // Used by ProtoProxy to repeat communication twice, once for parsing and the other time for the remote party
1021  CHECK_THREAD
1022  CheckValid();
1023  size_t DataStart = m_DataStart;
1024  if (m_ReadPos < m_DataStart)
1025  {
1026  // Across the ringbuffer end, read the first part and adjust next part's start:
1028  a_Out.append(m_Buffer + m_DataStart, m_BufferSize - m_DataStart);
1029  DataStart = 0;
1030  }
1031  ASSERT(m_ReadPos >= DataStart);
1032  a_Out.append(m_Buffer + DataStart, m_ReadPos - DataStart);
1033 }
1034 
1035 
1036 
1037 
1038 
1039 void cByteBuffer::AdvanceReadPos(size_t a_Count)
1040 {
1041  CHECK_THREAD
1042  CheckValid();
1043  m_ReadPos += a_Count;
1044  if (m_ReadPos >= m_BufferSize)
1045  {
1047  }
1048 }
1049 
1050 
1051 
1052 
1053 
1054 void cByteBuffer::CheckValid(void) const
1055 {
1058 }
1059 
1060 
1061 
1062 
1063 
1065 {
1066  size_t Count = 0;
1067 
1068  do
1069  {
1070  // If the value cannot be expressed in 7 bits, it needs to take up another byte
1071  Count++;
1072  a_Value >>= 7;
1073  } while (a_Value != 0);
1074 
1075  return Count;
1076 }
cByteBuffer::ReadBEUInt16
bool ReadBEUInt16(UInt16 &a_Value)
Definition: ByteBuffer.cpp:281
cByteBuffer::ReadAll
void ReadAll(ContiguousByteBuffer &a_Data)
Reads all available data into a_Data.
Definition: ByteBuffer.cpp:959
cUUID
Definition: UUID.h:10
cByteBuffer::AdvanceReadPos
void AdvanceReadPos(size_t a_Count)
Advances the m_ReadPos by a_Count bytes.
Definition: ByteBuffer.cpp:1039
Vector3::x
T x
Definition: Vector3.h:17
cByteBuffer::ReadUUID
bool ReadUUID(cUUID &a_Value)
Definition: ByteBuffer.cpp:555
ContiguousByteBuffer
std::basic_string< std::byte > ContiguousByteBuffer
Definition: Globals.h:372
cByteBuffer::ReadAgain
void ReadAgain(ContiguousByteBuffer &a_Out)
Re-reads the data that has been read since the last commit to the current readpos.
Definition: ByteBuffer.cpp:1017
cByteBuffer::WriteBEFloat
bool WriteBEFloat(float a_Value)
Definition: ByteBuffer.cpp:689
cByteBuffer::m_ReadPos
size_t m_ReadPos
Definition: ByteBuffer.h:155
cByteBuffer::ReadVarInt
bool ReadVarInt(T &a_Value)
Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short,...
Definition: ByteBuffer.h:81
cByteBuffer::GetReadableSpace
size_t GetReadableSpace(void) const
Returns the number of bytes that are currently available for reading (may be less than UsedSpace due ...
Definition: ByteBuffer.cpp:198
cByteBuffer::WriteBuf
bool WriteBuf(const void *a_Buffer, size_t a_Count)
Writes a_Count bytes into a_Buffer; returns true if successful.
Definition: ByteBuffer.cpp:851
cByteBuffer::ReadVarUTF8String
bool ReadVarUTF8String(AString &a_Value)
Definition: ByteBuffer.cpp:440
NetworkToHostDouble8
double NetworkToHostDouble8(const void *a_Value)
Definition: Endianness.h:36
cByteBuffer::ReadBEInt8
bool ReadBEInt8(Int8 &a_Value)
Definition: ByteBuffer.cpp:239
UUID.h
UInt16
unsigned short UInt16
Definition: Globals.h:155
cByteBuffer::WriteVarInt32
bool WriteVarInt32(UInt32 a_Value)
Definition: ByteBuffer.cpp:727
cByteBuffer::CanReadBytes
bool CanReadBytes(size_t a_Count) const
Returns true if the specified amount of bytes are available for reading.
Definition: ByteBuffer.cpp:217
cByteBuffer::ReadToByteBuffer
bool ReadToByteBuffer(cByteBuffer &a_Dst, size_t a_NumBytes)
Reads the specified number of bytes and writes it into the destinatio bytebuffer.
Definition: ByteBuffer.cpp:970
NetworkToHostLong8
Int64 NetworkToHostLong8(const void *a_Value)
Definition: Endianness.h:50
ByteBuffer.h
cByteBuffer::CanWriteBytes
bool CanWriteBytes(size_t a_Count) const
Returns true if the specified amount of bytes are available for writing.
Definition: ByteBuffer.cpp:228
Globals.h
UInt32
unsigned int UInt32
Definition: Globals.h:154
cByteBuffer::m_DataStart
size_t m_DataStart
Definition: ByteBuffer.h:153
cByteBuffer::ReadBEUInt32
bool ReadBEUInt32(UInt32 &a_Value)
Definition: ByteBuffer.cpp:311
cByteBuffer::ReadBool
bool ReadBool(bool &a_Value)
Definition: ByteBuffer.cpp:381
Endianness.h
ASSERT
#define ASSERT(x)
Definition: Globals.h:273
cByteBuffer::ReadXYZPosition64
bool ReadXYZPosition64(int &a_BlockX, int &a_BlockY, int &a_BlockZ)
Definition: ByteBuffer.cpp:487
cByteBuffer::ReadVarInt64
bool ReadVarInt64(UInt64 &a_Value)
Definition: ByteBuffer.cpp:418
Vector3::z
T z
Definition: Vector3.h:17
cByteBuffer::WriteBEInt64
bool WriteBEInt64(Int64 a_Value)
Definition: ByteBuffer.cpp:663
cByteBuffer::ReadBEInt16
bool ReadBEInt16(Int16 &a_Value)
Definition: ByteBuffer.cpp:265
MAX_STRING_SIZE
#define MAX_STRING_SIZE
When defined, each access to a cByteBuffer object is checked whether it's done in the same thread.
Definition: ByteBuffer.cpp:27
cByteBuffer::CheckValid
void CheckValid(void) const
Checks if the internal state is valid (read and write positions in the correct bounds) using ASSERTs.
Definition: ByteBuffer.cpp:1054
std
Definition: FastNBT.h:131
cByteBuffer::ReadBEUInt64
bool ReadBEUInt64(UInt64 &a_Value)
Definition: ByteBuffer.cpp:339
CHECK_THREAD
#define CHECK_THREAD
Definition: ByteBuffer.cpp:75
cByteBuffer::WriteBEInt8
bool WriteBEInt8(Int8 a_Value)
Definition: ByteBuffer.cpp:573
cByteBuffer::WriteVarInt64
bool WriteVarInt64(UInt64 a_Value)
Definition: ByteBuffer.cpp:749
cByteBuffer::WriteBEUInt64
bool WriteBEUInt64(UInt64 a_Value)
Definition: ByteBuffer.cpp:676
cByteBuffer
An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes ar...
Definition: ByteBuffer.h:31
NEEDBYTES
#define NEEDBYTES(Num)
Definition: ByteBuffer.cpp:29
cByteBuffer::ReadBuf
bool ReadBuf(void *a_Buffer, size_t a_Count)
Reads a_Count bytes into a_Buffer; returns true if successful.
Definition: ByteBuffer.cpp:818
IsThread.h
VERIFY
#define VERIFY(x)
Definition: Globals.h:277
cByteBuffer::ReadBEDouble
bool ReadBEDouble(double &a_Value)
Definition: ByteBuffer.cpp:367
cByteBuffer::WriteBEDouble
bool WriteBEDouble(double a_Value)
Definition: ByteBuffer.cpp:702
cByteBuffer::ReadBEInt32
bool ReadBEInt32(Int32 &a_Value)
Definition: ByteBuffer.cpp:295
cByteBuffer::GetVarIntSize
static size_t GetVarIntSize(UInt32 a_Value)
Gets the number of bytes that are needed to represent the given VarInt.
Definition: ByteBuffer.cpp:1064
Int32
signed int Int32
Definition: Globals.h:149
cByteBuffer::ReadBEInt64
bool ReadBEInt64(Int64 &a_Value)
Definition: ByteBuffer.cpp:325
cByteBuffer::GetFreeSpace
size_t GetFreeSpace(void) const
Returns the number of bytes that can be successfully written to the ringbuffer.
Definition: ByteBuffer.cpp:164
cByteBuffer::ResetRead
void ResetRead(void)
Restarts next reading operation at the start of the ringbuffer.
Definition: ByteBuffer.cpp:1006
cByteBuffer::GetUsedSpace
size_t GetUsedSpace(void) const
Returns the number of bytes that are currently in the ringbuffer.
Definition: ByteBuffer.cpp:185
cByteBuffer::ReadBEFloat
bool ReadBEFloat(float &a_Value)
Definition: ByteBuffer.cpp:353
cByteBuffer::ReadVarInt32
bool ReadVarInt32(UInt32 &a_Value)
Definition: ByteBuffer.cpp:396
cByteBuffer::CommitRead
void CommitRead(void)
Removes the bytes that have been read from the ringbuffer.
Definition: ByteBuffer.cpp:995
cByteBuffer::m_Buffer
std::byte * m_Buffer
Definition: ByteBuffer.h:150
HostToNetwork8
UInt64 HostToNetwork8(const void *a_Value)
Definition: Endianness.h:12
cByteBuffer::ReadSome
bool ReadSome(ContiguousByteBuffer &a_String, size_t a_Count)
Reads a_Count bytes into a_String; returns true if successful.
Definition: ByteBuffer.cpp:909
cByteBuffer::~cByteBuffer
~cByteBuffer()
Definition: ByteBuffer.cpp:100
cByteBuffer::m_BufferSize
size_t m_BufferSize
Definition: ByteBuffer.h:151
cByteBuffer::WriteXYZPosition64
bool WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
Definition: ByteBuffer.cpp:788
Int8
signed char Int8
Definition: Globals.h:151
cByteBuffer::ReadBEUInt8
bool ReadBEUInt8(UInt8 &a_Value)
Definition: ByteBuffer.cpp:252
LOGWARNING
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
cByteBuffer::WriteBEInt16
bool WriteBEInt16(Int16 a_Value)
Definition: ByteBuffer.cpp:609
Int64
signed long long Int64
Definition: Globals.h:148
cByteBuffer::m_WritePos
size_t m_WritePos
Definition: ByteBuffer.h:154
cUUID::FromRaw
void FromRaw(const std::array< Byte, 16 > &a_Raw)
Assigns from raw memory representation, respecting UUID variant.
Definition: UUID.cpp:238
cByteBuffer::cByteBuffer
cByteBuffer(size_t a_BufferSize)
Definition: ByteBuffer.cpp:85
cByteBuffer::WriteBool
bool WriteBool(bool a_Value)
Definition: ByteBuffer.cpp:715
cByteBuffer::SkipRead
bool SkipRead(size_t a_Count)
Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer.
Definition: ByteBuffer.cpp:943
cByteBuffer::WriteBEInt32
bool WriteBEInt32(Int32 a_Value)
Definition: ByteBuffer.cpp:637
cByteBuffer::WriteBEUInt16
bool WriteBEUInt16(UInt16 a_Value)
Definition: ByteBuffer.cpp:624
Vector3::y
T y
Definition: Vector3.h:17
UInt8
unsigned char UInt8
Definition: Globals.h:156
HostToNetwork4
UInt32 HostToNetwork4(const void *a_Value)
Definition: Endianness.h:24
cByteBuffer::WriteBEUInt32
bool WriteBEUInt32(UInt32 a_Value)
Definition: ByteBuffer.cpp:650
cByteBuffer::WriteXZYPosition64
bool WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
Definition: ByteBuffer.cpp:803
cByteBuffer::Write
bool Write(const void *a_Bytes, size_t a_Count)
Writes the bytes specified to the ringbuffer.
Definition: ByteBuffer.cpp:111
NetworkToHostULong8
UInt64 NetworkToHostULong8(const void *a_Value)
Definition: Endianness.h:62
cByteBuffer::WriteVarUTF8String
bool WriteVarUTF8String(const AString &a_Value)
Definition: ByteBuffer.cpp:771
AString
std::string AString
Definition: StringUtils.h:11
Vector3< int >
NetworkToHostFloat4
float NetworkToHostFloat4(const void *a_Value)
Definition: Endianness.h:74
PUTBYTES
#define PUTBYTES(Num)
Definition: ByteBuffer.cpp:30
UInt64
unsigned long long UInt64
Definition: Globals.h:153
Int16
signed short Int16
Definition: Globals.h:150
cByteBuffer::ReadXZYPosition64
bool ReadXZYPosition64(int &a_BlockX, int &a_BlockY, int &a_BlockZ)
Definition: ByteBuffer.cpp:521
cByteBuffer::ReadLEInt
bool ReadLEInt(int &a_Value)
Definition: ByteBuffer.cpp:468
cByteBuffer::WriteBEUInt8
bool WriteBEUInt8(UInt8 a_Value)
Definition: ByteBuffer.cpp:597