aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/x86/ByteWriter.h
blob: d38f0c951f76757581d163a71aef8af01f7f7537 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma once
#include "foundation/types.h"
#include "foundation/endian.h"
/* this is separated out to processor-specific types for a few reasons 

1) Unaligned writes are fast/easy on x86, slow on some platforms (ARM, x64), very slow on a few (Itanium) and crash on others (PowerPC)
2) ARM is very good at *ptr++, x86 is very good at ptr[offset]
3) Endian issues
*/
typedef struct ByteWriter
{
	uint8_t *data;
	size_t data_length;
	size_t offset;
} ByteWriter, *nu_bytewriter_t;

/* --------- Construction & Utility --------- */
#define BYTEWRITER_INIT(data, length) { (uint8_t *)data, length, 0 }

inline static uint32_t bw_bytes_written(nu_bytewriter_t bw)
{
	return bw->offset;
}

/* --------- Little Endian writers --------- */
inline static void bytewriter_fourcc_string(nu_bytewriter_t bw, const char *fourcc)
{
	bw->data[bw->offset] = fourcc[0];
	bw->data[bw->offset+1] = fourcc[1];
	bw->data[bw->offset+2] = fourcc[2];
	bw->data[bw->offset+3] = fourcc[3];
	bw->offset += 4;
}

inline static void bytewriter_uint32_le(nu_bytewriter_t bw, uint32_t value)
{
	*(uint32_t *)(&bw->data[bw->offset]) = value;
	bw->offset+=4;
}

inline static void bytewriter_uint16_le(nu_bytewriter_t bw, uint16_t value)
{
	*(uint16_t *)(&bw->data[bw->offset]) = value;
	bw->offset+=2;
}

/* --------- Big Endian writers --------- */
inline static void bytewriter_uint32_be(nu_bytewriter_t bw, uint32_t value)
{
	*(uint32_t *)(&bw->data[bw->offset]) = _byteswap_ulong(value);
	bw->offset+=4;
}

inline static void bytewriter_uint24_be(nu_bytewriter_t bw, uint32_t value)
{
	bw->data[bw->offset] = (uint8_t)(value >> 16) & 0xFF;
	bw->data[bw->offset+1] = (uint8_t)(value >>  8) & 0xFF;
	bw->data[bw->offset+2] = (uint8_t)value & 0xFF;
	bw->offset+=3;
}

inline static void bytewriter_uint16_le(nu_bytewriter_t bw, uint16_t value)
{
	*(uint16_t *)(&bw->data[bw->offset]) = value;
	bw->offset+=2;
}

/* --------- Neutral Endian writers --------- */
inline static void bytewriter_uint32_zero(nu_bytewriter_t bw)
{
	*(uint32_t *)(&bw->data[bw->offset]) = 0;
	bw->offset+=4;
}

inline static void bytewriter_uint32_nzero(nu_bytewriter_t bw, uint32_t num_zeroes)
{
	memset(bw->data, 0, num_zeroes*4);
	bw->offset+=num_zeroes*4;
}

inline static void bytewriter_uint8(nu_bytewriter_t bw, uint8_t value)
{
	*(uint8_t *)&bw->data[bw->offset] = value;
	bw->offset++;
}