FeatherMC/src/PacketReader.h

113 lines
2.8 KiB
C
Raw Normal View History

#pragma once
#include "Common.h"
2020-08-01 01:49:07 +01:00
#include "util/ByteUtil.h"
#include <cstdio>
#include <cstdint>
#include <string>
using std::string;
namespace Feather
{
// Class to read packet data, such as is produced by NetworkMessage
class PacketReader
{
public:
2020-07-28 05:40:47 +01:00
PacketReader(const uint8_t *const dataPtr)
2020-08-01 05:45:39 +01:00
: m_data(dataPtr), m_offset(0), m_length(ReadLength())
2020-07-28 01:26:46 +01:00
{
}
2020-08-01 01:49:07 +01:00
// Peek the next value to be read
// If big endian (the default), will reverse byte order.
template <typename T, Endian endianMode = Endian::Big>
inline T Peek()
{
2020-08-01 01:49:07 +01:00
T value = *reinterpret_cast<const T *const>(&m_data[m_offset]);
return (endianMode == Endian::Big) ? ReverseBytes<T>(value) : value;
}
2020-08-01 01:49:07 +01:00
// Read the next value
// If big endian (the default), will reverse byte order.
template <typename T, Endian endianMode = Endian::Big>
inline T Read()
{
2020-08-01 01:49:07 +01:00
T value = Peek<T, endianMode>();
m_offset += sizeof(T);
return value;
}
2020-08-01 01:49:07 +01:00
// Fast way to peek the next byte
inline uint8_t PeekByte() { return m_data[m_offset]; }
// Fast way to read a byte
inline uint8_t ReadByte() { return m_data[m_offset++]; }
2020-08-01 05:45:39 +01:00
inline int32_t ReadLength()
{
int32_t length = ReadVarInt();
// HACK: handle Legacy Server List Ping
if (length == 0xFE) {
if (PeekByte() == 0x01) {
return 2;
}
}
return length;
}
template <typename T = int32_t>
inline T ReadVarInt()
{
int32_t numRead = 0;
int32_t result = 0;
uint8_t read;
do
{
2020-08-01 01:49:07 +01:00
read = ReadByte();
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5)
{
// complain
//throw new RuntimeException("VarInt is too big");
}
} while ((read & 0b10000000) != 0);
return static_cast<T>(result);
}
string ReadString()
{
int size = ReadVarInt();
string str;
for (int i = 0; i < size; i++) {
2020-08-01 01:49:07 +01:00
str += ReadByte();
}
return str;
}
uint32_t Length() const { return m_length; }
private:
2020-07-28 05:40:47 +01:00
const uint8_t *const m_data;
2020-07-28 05:59:53 +01:00
uint32_t m_offset;
2020-07-28 05:29:02 +01:00
const uint32_t m_length;
};
2020-08-01 01:49:07 +01:00
// Use fast Read and Peek for uint8_t
template <>
inline uint8_t PacketReader::Peek<uint8_t>() { return PeekByte(); }
template<>
inline uint8_t PacketReader::Read<uint8_t>() { return ReadByte(); }
2020-08-01 00:57:33 +01:00
}