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 
218 {
219  return (-128 <= a_Value) && (a_Value <= 127);
220 }
221 
222 
223 
224 
225 
227 {
228  return (-32768 <= a_Value) && (a_Value <= 32767);
229 }
230 
231 
232 
233 
234 
235 bool cByteBuffer::CanReadBytes(size_t a_Count) const
236 {
238  CheckValid();
239  return (a_Count <= GetReadableSpace());
240 }
241 
242 
243 
244 
245 
246 bool cByteBuffer::CanWriteBytes(size_t a_Count) const
247 {
249  CheckValid();
250  return (a_Count <= GetFreeSpace());
251 }
252 
253 
254 
255 
256 
258 {
260  CheckValid();
261  NEEDBYTES(1);
262  ReadBuf(&a_Value, 1);
263  return true;
264 }
265 
266 
267 
268 
269 
271 {
273  CheckValid();
274  NEEDBYTES(1);
275  ReadBuf(&a_Value, 1);
276  return true;
277 }
278 
279 
280 
281 
282 
284 {
286  CheckValid();
287  NEEDBYTES(2);
288  UInt16 val;
289  ReadBuf(&val, 2);
290  val = ntohs(val);
291  memcpy(&a_Value, &val, 2);
292  return true;
293 }
294 
295 
296 
297 
298 
300 {
302  CheckValid();
303  NEEDBYTES(2);
304  ReadBuf(&a_Value, 2);
305  a_Value = ntohs(a_Value);
306  return true;
307 }
308 
309 
310 
311 
312 
314 {
316  CheckValid();
317  NEEDBYTES(4);
318  UInt32 val;
319  ReadBuf(&val, 4);
320  val = ntohl(val);
321  memcpy(&a_Value, &val, 4);
322  return true;
323 }
324 
325 
326 
327 
328 
330 {
332  CheckValid();
333  NEEDBYTES(4);
334  ReadBuf(&a_Value, 4);
335  a_Value = ntohl(a_Value);
336  return true;
337 }
338 
339 
340 
341 
342 
344 {
346  CheckValid();
347  NEEDBYTES(8);
348  ReadBuf(&a_Value, 8);
349  a_Value = NetworkToHostLong8(&a_Value);
350  return true;
351 }
352 
353 
354 
355 
356 
358 {
360  CheckValid();
361  NEEDBYTES(8);
362  ReadBuf(&a_Value, 8);
363  a_Value = NetworkToHostULong8(&a_Value);
364  return true;
365 }
366 
367 
368 
369 
370 
371 bool cByteBuffer::ReadBEFloat(float & a_Value)
372 {
374  CheckValid();
375  NEEDBYTES(4);
376  ReadBuf(&a_Value, 4);
377  a_Value = NetworkToHostFloat4(&a_Value);
378  return true;
379 }
380 
381 
382 
383 
384 
385 bool cByteBuffer::ReadBEDouble(double & a_Value)
386 {
388  CheckValid();
389  NEEDBYTES(8);
390  ReadBuf(&a_Value, 8);
391  a_Value = NetworkToHostDouble8(&a_Value);
392  return true;
393 }
394 
395 
396 
397 
398 
399 bool cByteBuffer::ReadBool(bool & a_Value)
400 {
402  CheckValid();
403  NEEDBYTES(1);
404  UInt8 Value = 0;
405  ReadBuf(&Value, 1);
406  a_Value = (Value != 0);
407  return true;
408 }
409 
410 
411 
412 
413 
415 {
417  CheckValid();
418  UInt32 Value = 0;
419  int Shift = 0;
420  unsigned char b = 0;
421  do
422  {
423  NEEDBYTES(1);
424  ReadBuf(&b, 1);
425  Value = Value | ((static_cast<UInt32>(b & 0x7f)) << Shift);
426  Shift += 7;
427  } while ((b & 0x80) != 0);
428  a_Value = Value;
429  return true;
430 }
431 
432 
433 
434 
435 
437 {
439  CheckValid();
440  UInt64 Value = 0;
441  int Shift = 0;
442  unsigned char b = 0;
443  do
444  {
445  NEEDBYTES(1);
446  ReadBuf(&b, 1);
447  Value = Value | ((static_cast<UInt64>(b & 0x7f)) << Shift);
448  Shift += 7;
449  } while ((b & 0x80) != 0);
450  a_Value = Value;
451  return true;
452 }
453 
454 
455 
456 
457 
459 {
461  CheckValid();
462  UInt32 Size = 0;
463  if (!ReadVarInt(Size))
464  {
465  return false;
466  }
467  if (Size > MAX_STRING_SIZE)
468  {
469  LOGWARNING("%s: String too large: %u (%u KiB)", __FUNCTION__, Size, Size / 1024);
470  }
471  ContiguousByteBuffer Buffer;
472  if (!ReadSome(Buffer, static_cast<size_t>(Size)))
473  {
474  return false;
475  }
476  // "Convert" a UTF-8 encoded string into system-native char.
477  // This isn't great, better would be to use codecvt:
478  a_Value = { reinterpret_cast<const char *>(Buffer.data()), Buffer.size() };
479  return true;
480 }
481 
482 
483 
484 
485 
486 bool cByteBuffer::ReadLEInt(int & a_Value)
487 {
489  CheckValid();
490  NEEDBYTES(4);
491  ReadBuf(&a_Value, 4);
492 
493  #ifdef IS_BIG_ENDIAN
494  // Convert:
495  a_Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000);
496  #endif
497 
498  return true;
499 }
500 
501 
502 
503 
504 
505 bool cByteBuffer::ReadXYZPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
506 {
508  UInt64 Value;
509  if (!ReadBEUInt64(Value))
510  {
511  return false;
512  }
513 
514  // Convert the 64 received bits into 3 coords:
515  UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits
516  UInt32 BlockYRaw = (Value >> 26) & 0x0fff; // Middle 12 bits
517  UInt32 BlockZRaw = (Value & 0x03ffffff); // Bottom 26 bits
518 
519  // If the highest bit in the number's range is set, convert the number into negative:
520  a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : -(0x04000000 - static_cast<int>(BlockXRaw));
521  a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : -(0x01000 - static_cast<int>(BlockYRaw));
522  a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : -(0x04000000 - static_cast<int>(BlockZRaw));
523  return true;
524 }
525 
526 
527 
528 
529 
531 {
532  return ReadXYZPosition64(a_Position.x, a_Position.y, a_Position.z);
533 }
534 
535 
536 
537 
538 
539 bool cByteBuffer::ReadXZYPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
540 {
542  UInt64 Value;
543  if (!ReadBEUInt64(Value))
544  {
545  return false;
546  }
547 
548  // Convert the 64 received bits into 3 coords:
549  UInt32 BlockXRaw = (Value >> 38) & 0x03ffffff; // Top 26 bits
550  UInt32 BlockZRaw = (Value >> 12) & 0x03ffffff; // Middle 26 bits
551  UInt32 BlockYRaw = (Value & 0x0fff); // Bottom 12 bits
552 
553  // If the highest bit in the number's range is set, convert the number into negative:
554  a_BlockX = ((BlockXRaw & 0x02000000) == 0) ? static_cast<int>(BlockXRaw) : (static_cast<int>(BlockXRaw) - 0x04000000);
555  a_BlockY = ((BlockYRaw & 0x0800) == 0) ? static_cast<int>(BlockYRaw) : (static_cast<int>(BlockYRaw) - 0x01000);
556  a_BlockZ = ((BlockZRaw & 0x02000000) == 0) ? static_cast<int>(BlockZRaw) : (static_cast<int>(BlockZRaw) - 0x04000000);
557  return true;
558 }
559 
560 
561 
562 
563 
565 {
566  return ReadXZYPosition64(a_Position.x, a_Position.y, a_Position.z);
567 }
568 
569 
570 
571 
572 
574 {
576 
577  std::array<Byte, 16> UUIDBuf;
578  if (!ReadBuf(UUIDBuf.data(), UUIDBuf.size()))
579  {
580  return false;
581  }
582 
583  a_Value.FromRaw(UUIDBuf);
584  return true;
585 }
586 
587 
588 
589 
590 
592 {
594  CheckValid();
595  PUTBYTES(1);
596  return WriteBuf(&a_Value, 1);
597 }
598 
599 
600 
601 
602 
603 bool cByteBuffer::WriteBEInt8(const std::byte a_Value)
604 {
606  CheckValid();
607  PUTBYTES(1);
608  return WriteBuf(&a_Value, 1);
609 }
610 
611 
612 
613 
614 
616 {
618  CheckValid();
619  PUTBYTES(1);
620  return WriteBuf(&a_Value, 1);
621 }
622 
623 
624 
625 
626 
628 {
630  CheckValid();
631  PUTBYTES(2);
632  UInt16 val;
633  memcpy(&val, &a_Value, 2);
634  val = htons(val);
635  return WriteBuf(&val, 2);
636 }
637 
638 
639 
640 
641 
643 {
645  CheckValid();
646  PUTBYTES(2);
647  a_Value = htons(a_Value);
648  return WriteBuf(&a_Value, 2);
649 }
650 
651 
652 
653 
654 
656 {
658  CheckValid();
659  PUTBYTES(4);
660  UInt32 Converted = HostToNetwork4(&a_Value);
661  return WriteBuf(&Converted, 4);
662 }
663 
664 
665 
666 
667 
669 {
671  CheckValid();
672  PUTBYTES(4);
673  UInt32 Converted = HostToNetwork4(&a_Value);
674  return WriteBuf(&Converted, 4);
675 }
676 
677 
678 
679 
680 
682 {
684  CheckValid();
685  PUTBYTES(8);
686  UInt64 Converted = HostToNetwork8(&a_Value);
687  return WriteBuf(&Converted, 8);
688 }
689 
690 
691 
692 
693 
695 {
697  CheckValid();
698  PUTBYTES(8);
699  UInt64 Converted = HostToNetwork8(&a_Value);
700  return WriteBuf(&Converted, 8);
701 }
702 
703 
704 
705 
706 
707 bool cByteBuffer::WriteBEFloat(float a_Value)
708 {
710  CheckValid();
711  PUTBYTES(4);
712  UInt32 Converted = HostToNetwork4(&a_Value);
713  return WriteBuf(&Converted, 4);
714 }
715 
716 
717 
718 
719 
720 bool cByteBuffer::WriteBEDouble(double a_Value)
721 {
723  CheckValid();
724  PUTBYTES(8);
725  UInt64 Converted = HostToNetwork8(&a_Value);
726  return WriteBuf(&Converted, 8);
727 }
728 
729 
730 
731 
732 
733 bool cByteBuffer::WriteBool(bool a_Value)
734 {
736  CheckValid();
737  UInt8 val = a_Value ? 1 : 0;
738  return Write(&val, 1);
739 }
740 
741 
742 
743 
744 
746 {
748  CheckValid();
749 
750  // A 32-bit integer can be encoded by at most 5 bytes:
751  unsigned char b[5];
752  size_t idx = 0;
753  do
754  {
755  b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
756  a_Value = a_Value >> 7;
757  idx++;
758  } while (a_Value > 0);
759 
760  return WriteBuf(b, idx);
761 }
762 
763 
764 
765 
766 
768 {
770  CheckValid();
771 
772  // A 64-bit integer can be encoded by at most 10 bytes:
773  unsigned char b[10];
774  size_t idx = 0;
775  do
776  {
777  b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
778  a_Value = a_Value >> 7;
779  idx++;
780  } while (a_Value > 0);
781 
782  return WriteBuf(b, idx);
783 }
784 
785 
786 
787 
788 
790 {
792  CheckValid();
793  PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early.
794  bool res = WriteVarInt32(static_cast<UInt32>(a_Value.size()));
795  if (!res)
796  {
797  return false;
798  }
799  return WriteBuf(a_Value.data(), a_Value.size());
800 }
801 
802 
803 
804 
805 
806 bool cByteBuffer::WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
807 {
809  CheckValid();
810  return WriteBEUInt64(
811  ((static_cast<UInt64>(a_BlockX) & 0x3FFFFFF) << 38) |
812  ((static_cast<UInt64>(a_BlockY) & 0xFFF) << 26) |
813  (static_cast<UInt64>(a_BlockZ) & 0x3FFFFFF)
814  );
815 }
816 
817 
818 
819 
820 
821 bool cByteBuffer::WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
822 {
824  CheckValid();
825  return WriteBEUInt64(
826  ((static_cast<UInt64>(a_BlockX) & 0x3FFFFFF) << 38) |
827  ((static_cast<UInt64>(a_BlockZ) & 0x3FFFFFF) << 12) |
828  (static_cast<UInt64>(a_BlockY) & 0xFFF)
829  );
830 }
831 
832 
833 
834 
835 
836 bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count)
837 {
839  CheckValid();
840  NEEDBYTES(a_Count);
841  char * Dst = static_cast<char *>(a_Buffer); // So that we can do byte math
843  size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos;
844  if (BytesToEndOfBuffer <= a_Count)
845  {
846  // Reading across the ringbuffer end, read the first part and adjust parameters:
847  if (BytesToEndOfBuffer > 0)
848  {
849  memcpy(Dst, m_Buffer + m_ReadPos, BytesToEndOfBuffer);
850  Dst += BytesToEndOfBuffer;
851  a_Count -= BytesToEndOfBuffer;
852  }
853  m_ReadPos = 0;
854  }
855 
856  // Read the rest of the bytes in a single read (guaranteed to fit):
857  if (a_Count > 0)
858  {
859  memcpy(Dst, m_Buffer + m_ReadPos, a_Count);
860  m_ReadPos += a_Count;
861  }
862  return true;
863 }
864 
865 
866 
867 
868 
869 bool cByteBuffer::WriteBuf(const void * a_Buffer, size_t a_Count)
870 {
872  CheckValid();
873  PUTBYTES(a_Count);
874  const char * Src = static_cast<const char *>(a_Buffer); // So that we can do byte math
876  size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos;
877  if (BytesToEndOfBuffer <= a_Count)
878  {
879  // Reading across the ringbuffer end, read the first part and adjust parameters:
880  memcpy(m_Buffer + m_WritePos, Src, BytesToEndOfBuffer);
881  Src += BytesToEndOfBuffer;
882  a_Count -= BytesToEndOfBuffer;
883  m_WritePos = 0;
884  }
885 
886  // Read the rest of the bytes in a single read (guaranteed to fit):
887  if (a_Count > 0)
888  {
889  memcpy(m_Buffer + m_WritePos, Src, a_Count);
890  m_WritePos += a_Count;
891  }
892  return true;
893 }
894 
895 
896 
897 
898 
899 bool cByteBuffer::WriteBuf(size_t a_Count, unsigned char a_Value)
900 {
902  CheckValid();
903  PUTBYTES(a_Count);
905  size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos;
906  if (BytesToEndOfBuffer <= a_Count)
907  {
908  // Reading across the ringbuffer end, read the first part and adjust parameters:
909  memset(m_Buffer + m_WritePos, a_Value, BytesToEndOfBuffer);
910  a_Count -= BytesToEndOfBuffer;
911  m_WritePos = 0;
912  }
913 
914  // Read the rest of the bytes in a single read (guaranteed to fit):
915  if (a_Count > 0)
916  {
917  memset(m_Buffer + m_WritePos, a_Value, a_Count);
918  m_WritePos += a_Count;
919  }
920  return true;
921 }
922 
923 
924 
925 
926 
927 bool cByteBuffer::ReadSome(ContiguousByteBuffer & a_String, size_t a_Count)
928 {
930  CheckValid();
931  NEEDBYTES(a_Count);
932  a_String.clear();
933  a_String.reserve(a_Count);
935  size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos;
936  if (BytesToEndOfBuffer <= a_Count)
937  {
938  // Reading across the ringbuffer end, read the first part and adjust parameters:
939  if (BytesToEndOfBuffer > 0)
940  {
941  a_String.assign(m_Buffer + m_ReadPos, BytesToEndOfBuffer);
942  ASSERT(a_Count >= BytesToEndOfBuffer);
943  a_Count -= BytesToEndOfBuffer;
944  }
945  m_ReadPos = 0;
946  }
947 
948  // Read the rest of the bytes in a single read (guaranteed to fit):
949  if (a_Count > 0)
950  {
951  a_String.append(m_Buffer + m_ReadPos, a_Count);
952  m_ReadPos += a_Count;
953  }
954  return true;
955 }
956 
957 
958 
959 
960 
961 bool cByteBuffer::SkipRead(size_t a_Count)
962 {
964  CheckValid();
965  if (!CanReadBytes(a_Count))
966  {
967  return false;
968  }
969  AdvanceReadPos(a_Count);
970  return true;
971 }
972 
973 
974 
975 
976 
978 {
980  CheckValid();
981  ReadSome(a_Data, GetReadableSpace());
982 }
983 
984 
985 
986 
987 
988 bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes)
989 {
991  if (!a_Dst.CanWriteBytes(a_NumBytes) || !CanReadBytes(a_NumBytes))
992  {
993  // There's not enough source bytes or space in the dest BB
994  return false;
995  }
996  char buf[1024];
997  // > 0 without generating warnings about unsigned comparisons where size_t is unsigned
998  while (a_NumBytes != 0)
999  {
1000  size_t num = (a_NumBytes > sizeof(buf)) ? sizeof(buf) : a_NumBytes;
1001  VERIFY(ReadBuf(buf, num));
1002  VERIFY(a_Dst.Write(buf, num));
1003  ASSERT(a_NumBytes >= num);
1004  a_NumBytes -= num;
1005  }
1006  return true;
1007 }
1008 
1009 
1010 
1011 
1012 
1014 {
1015  CHECK_THREAD
1016  CheckValid();
1018 }
1019 
1020 
1021 
1022 
1023 
1025 {
1026  CHECK_THREAD
1027  CheckValid();
1029 }
1030 
1031 
1032 
1033 
1034 
1036 {
1037  // Return the data between m_DataStart and m_ReadPos (the data that has been read but not committed)
1038  // Used by ProtoProxy to repeat communication twice, once for parsing and the other time for the remote party
1039  CHECK_THREAD
1040  CheckValid();
1041  size_t DataStart = m_DataStart;
1042  if (m_ReadPos < m_DataStart)
1043  {
1044  // Across the ringbuffer end, read the first part and adjust next part's start:
1046  a_Out.append(m_Buffer + m_DataStart, m_BufferSize - m_DataStart);
1047  DataStart = 0;
1048  }
1049  ASSERT(m_ReadPos >= DataStart);
1050  a_Out.append(m_Buffer + DataStart, m_ReadPos - DataStart);
1051 }
1052 
1053 
1054 
1055 
1056 
1057 void cByteBuffer::AdvanceReadPos(size_t a_Count)
1058 {
1059  CHECK_THREAD
1060  CheckValid();
1061  m_ReadPos += a_Count;
1062  if (m_ReadPos >= m_BufferSize)
1063  {
1065  }
1066 }
1067 
1068 
1069 
1070 
1071 
1072 void cByteBuffer::CheckValid(void) const
1073 {
1076 }
1077 
1078 
1079 
1080 
1081 
1083 {
1084  size_t Count = 0;
1085 
1086  do
1087  {
1088  // If the value cannot be expressed in 7 bits, it needs to take up another byte
1089  Count++;
1090  a_Value >>= 7;
1091  } while (a_Value != 0);
1092 
1093  return Count;
1094 }
#define NEEDBYTES(Num)
Definition: ByteBuffer.cpp:29
#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
#define CHECK_THREAD
Definition: ByteBuffer.cpp:75
#define PUTBYTES(Num)
Definition: ByteBuffer.cpp:30
UInt32 HostToNetwork4(const void *a_Value)
Definition: Endianness.h:24
Int64 NetworkToHostLong8(const void *a_Value)
Definition: Endianness.h:50
double NetworkToHostDouble8(const void *a_Value)
Definition: Endianness.h:36
UInt64 NetworkToHostULong8(const void *a_Value)
Definition: Endianness.h:62
float NetworkToHostFloat4(const void *a_Value)
Definition: Endianness.h:74
UInt64 HostToNetwork8(const void *a_Value)
Definition: Endianness.h:12
#define VERIFY(x)
Definition: Globals.h:280
unsigned int UInt32
Definition: Globals.h:157
signed long long Int64
Definition: Globals.h:151
signed short Int16
Definition: Globals.h:153
signed char Int8
Definition: Globals.h:154
signed int Int32
Definition: Globals.h:152
unsigned char UInt8
Definition: Globals.h:159
unsigned long long UInt64
Definition: Globals.h:156
#define ASSERT(x)
Definition: Globals.h:276
unsigned short UInt16
Definition: Globals.h:158
std::basic_string< std::byte > ContiguousByteBuffer
Definition: Globals.h:375
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
std::string AString
Definition: StringUtils.h:11
Definition: FastNBT.h:132
An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes ar...
Definition: ByteBuffer.h:32
size_t m_ReadPos
Definition: ByteBuffer.h:162
bool ReadBEUInt16(UInt16 &a_Value)
Definition: ByteBuffer.cpp:299
size_t m_WritePos
Definition: ByteBuffer.h:161
size_t GetUsedSpace(void) const
Returns the number of bytes that are currently in the ringbuffer.
Definition: ByteBuffer.cpp:185
bool WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
Definition: ByteBuffer.cpp:806
bool SkipRead(size_t a_Count)
Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer.
Definition: ByteBuffer.cpp:961
bool ReadBEUInt8(UInt8 &a_Value)
Definition: ByteBuffer.cpp:270
bool CanReadBytes(size_t a_Count) const
Returns true if the specified amount of bytes are available for reading.
Definition: ByteBuffer.cpp:235
bool WriteVarInt64(UInt64 a_Value)
Definition: ByteBuffer.cpp:767
static bool CanBEInt16Represent(int a_Value)
Returns if the given value can fit in a protocol big-endian 16 bit integer.
Definition: ByteBuffer.cpp:226
void CommitRead(void)
Removes the bytes that have been read from the ringbuffer.
bool ReadBEUInt64(UInt64 &a_Value)
Definition: ByteBuffer.cpp:357
size_t m_BufferSize
Definition: ByteBuffer.h:158
bool ReadBuf(void *a_Buffer, size_t a_Count)
Reads a_Count bytes into a_Buffer; returns true if successful.
Definition: ByteBuffer.cpp:836
bool ReadXZYPosition64(int &a_BlockX, int &a_BlockY, int &a_BlockZ)
Definition: ByteBuffer.cpp:539
void ReadAll(ContiguousByteBuffer &a_Data)
Reads all available data into a_Data.
Definition: ByteBuffer.cpp:977
bool ReadVarInt64(UInt64 &a_Value)
Definition: ByteBuffer.cpp:436
void CheckValid(void) const
Checks if the internal state is valid (read and write positions in the correct bounds) using ASSERTs.
bool WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
Definition: ByteBuffer.cpp:821
bool ReadUUID(cUUID &a_Value)
Definition: ByteBuffer.cpp:573
bool ReadBEFloat(float &a_Value)
Definition: ByteBuffer.cpp:371
void AdvanceReadPos(size_t a_Count)
Advances the m_ReadPos by a_Count bytes.
std::byte * m_Buffer
Definition: ByteBuffer.h:157
bool ReadLEInt(int &a_Value)
Definition: ByteBuffer.cpp:486
bool ReadBEInt64(Int64 &a_Value)
Definition: ByteBuffer.cpp:343
bool WriteBEUInt32(UInt32 a_Value)
Definition: ByteBuffer.cpp:668
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:988
size_t GetFreeSpace(void) const
Returns the number of bytes that can be successfully written to the ringbuffer.
Definition: ByteBuffer.cpp:164
bool WriteBEFloat(float a_Value)
Definition: ByteBuffer.cpp:707
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
bool WriteBEInt32(Int32 a_Value)
Definition: ByteBuffer.cpp:655
bool ReadBool(bool &a_Value)
Definition: ByteBuffer.cpp:399
bool WriteBEInt64(Int64 a_Value)
Definition: ByteBuffer.cpp:681
bool ReadVarInt32(UInt32 &a_Value)
Definition: ByteBuffer.cpp:414
bool WriteBEInt16(Int16 a_Value)
Definition: ByteBuffer.cpp:627
bool WriteBEUInt64(UInt64 a_Value)
Definition: ByteBuffer.cpp:694
bool CanWriteBytes(size_t a_Count) const
Returns true if the specified amount of bytes are available for writing.
Definition: ByteBuffer.cpp:246
bool ReadVarInt(T &a_Value)
Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short,...
Definition: ByteBuffer.h:88
bool WriteBuf(const void *a_Buffer, size_t a_Count)
Writes a_Count bytes into a_Buffer; returns true if successful.
Definition: ByteBuffer.cpp:869
bool ReadXYZPosition64(int &a_BlockX, int &a_BlockY, int &a_BlockZ)
Definition: ByteBuffer.cpp:505
bool WriteBool(bool a_Value)
Definition: ByteBuffer.cpp:733
void ReadAgain(ContiguousByteBuffer &a_Out)
Re-reads the data that has been read since the last commit to the current readpos.
bool WriteVarUTF8String(const AString &a_Value)
Definition: ByteBuffer.cpp:789
bool WriteBEInt8(Int8 a_Value)
Definition: ByteBuffer.cpp:591
bool WriteVarInt32(UInt32 a_Value)
Definition: ByteBuffer.cpp:745
static size_t GetVarIntSize(UInt32 a_Value)
Gets the number of bytes that are needed to represent the given VarInt.
bool ReadBEInt8(Int8 &a_Value)
Definition: ByteBuffer.cpp:257
bool ReadVarUTF8String(AString &a_Value)
Definition: ByteBuffer.cpp:458
bool ReadSome(ContiguousByteBuffer &a_String, size_t a_Count)
Reads a_Count bytes into a_String; returns true if successful.
Definition: ByteBuffer.cpp:927
bool ReadBEUInt32(UInt32 &a_Value)
Definition: ByteBuffer.cpp:329
bool ReadBEInt32(Int32 &a_Value)
Definition: ByteBuffer.cpp:313
size_t m_DataStart
Definition: ByteBuffer.h:160
void ResetRead(void)
Restarts next reading operation at the start of the ringbuffer.
bool Write(const void *a_Bytes, size_t a_Count)
Writes the bytes specified to the ringbuffer.
Definition: ByteBuffer.cpp:111
static bool CanBEInt8Represent(int a_Value)
Returns if the given value can fit in a protocol big-endian 8 bit integer.
Definition: ByteBuffer.cpp:217
bool WriteBEUInt16(UInt16 a_Value)
Definition: ByteBuffer.cpp:642
bool WriteBEUInt8(UInt8 a_Value)
Definition: ByteBuffer.cpp:615
cByteBuffer(size_t a_BufferSize)
Definition: ByteBuffer.cpp:85
bool ReadBEDouble(double &a_Value)
Definition: ByteBuffer.cpp:385
bool WriteBEDouble(double a_Value)
Definition: ByteBuffer.cpp:720
bool ReadBEInt16(Int16 &a_Value)
Definition: ByteBuffer.cpp:283
Definition: UUID.h:11
void FromRaw(const std::array< Byte, 16 > &a_Raw)
Assigns from raw memory representation, respecting UUID variant.
Definition: UUID.cpp:238
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17