master uint/magnolia / source / net / packet.c
  1#include <string.h>
  2
  3#include "net/packet.h"
  4
  5static i8 packet_read(PacketReader* reader, void* output, size_t size);
  6
  7/* read a number of bytes from packet, copy them to output.
  8   returns 1 on success, 0 on failure */
  9static i8 packet_read(PacketReader* reader, void* output, size_t size)
 10{
 11	if (reader->cursor > reader->size)
 12		return 0;
 13
 14	if (size > reader->size - reader->cursor)
 15		return 0;
 16
 17	memcpy(output, reader->data + reader->cursor, size);
 18	reader->cursor += size;
 19	return 1;
 20}
 21
 22PacketReader packet_reader_init(const void* data, size_t size)
 23{
 24	PacketReader reader = { data, size, 0 };
 25	return reader;
 26}
 27
 28i8 packet_read_u8(PacketReader* reader, u8* value)
 29{
 30	return packet_read(reader, value, 1);
 31}
 32
 33i8 packet_read_u16(PacketReader* reader, u16* value)
 34{
 35	u8 data[2];
 36
 37	if (!packet_read(reader, data, 2))
 38		return 0;
 39
 40	*value = ((u16)data[0] << 8) | (u16)data[1];
 41
 42	return 1;
 43}
 44
 45i8 packet_read_i32(PacketReader* reader, i32* value)
 46{
 47	u8  data[4];
 48	u32 result;
 49
 50	if (!packet_read(reader, data, 4))
 51		return 0;
 52
 53	result = ((u32)data[0] << 24) | ((u32)data[1] << 16) | ((u32)data[2] << 8) | (u32)data[3];
 54
 55	*value = (i32)result;
 56	return 1;
 57}
 58
 59i8 packet_read_u64(PacketReader* reader, u64* value)
 60{
 61	u8  data[8];
 62	u64 result;
 63	i32 i;
 64
 65	if (!packet_read(reader, data, 8))
 66		return 0;
 67
 68	result = 0;
 69
 70	for (i = 0; i < 8; i++)
 71		result = (result << 8) | data[i];
 72
 73	*value = result;
 74	return 1;
 75}
 76
 77i8 packet_read_f32(PacketReader* reader, float* value)
 78{
 79	i32 bits;
 80
 81	if (!packet_read_i32(reader, &bits))
 82		return 0;
 83
 84	memcpy(value, &bits, sizeof(*value));
 85	return 1;
 86}
 87
 88i8 packet_read_f64(PacketReader* reader, double* value)
 89{
 90	u64 bits;
 91
 92	if (!packet_read_u64(reader, &bits))
 93		return 0;
 94
 95	memcpy(value, &bits, sizeof(*value));
 96	return 1;
 97}
 98
 99i8 packet_read_varint(PacketReader* reader, i32* value)
100{
101	u32 result;
102	u8  byte;
103	i32 shift;
104
105	result = 0;
106
107	for (shift = 0; shift < 7 * 5; shift += 7) { /* varints have max 5 bytes */
108		if (!packet_read_u8(reader, &byte))
109			return 0;
110
111		result |= (u32)(byte & 0x7f) << shift;
112
113		if (!(byte & 0x80)) { /* last byte */
114			*value = (i32)result;
115			return 1;
116		}
117	}
118
119	return 0;
120}