-
Notifications
You must be signed in to change notification settings - Fork 1
/
common.c
155 lines (120 loc) · 3.04 KB
/
common.c
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "common.h"
#include "system.h"
#define kLFSRMagic 0xC2DF
static UWORD random();
static struct {
UBYTE uppercase_lut[1 << kBitsPerByte];
UWORD prng_seed;
} g;
Status common_init() {
Status status = StatusOK;
for (UWORD i = 0; i < ARRAY_NELEMS(g.uppercase_lut); ++ i) {
BOOL lowercase = (i >= 'a') && (i <= 'z');
g.uppercase_lut[i] = (UBYTE)(lowercase ? (i - ('a' - 'A')) : i);
}
ULONG time_micros = 0;
ASSERT(system_time_micros(&time_micros));
g.prng_seed = (UWORD)time_micros;
cleanup:
return status;
}
void memory_clear(APTR base,
ULONG size) {
UBYTE* start = base;
UBYTE* end = base + size;
for (UBYTE* byte = start; byte != end; ++ byte) {
*byte = 0;
}
}
UWORD string_length(STRPTR str) {
UWORD len;
for (len = 0; str[len]; ++ len);
return len;
}
void string_copy(STRPTR dst,
STRPTR src) {
while (*(dst ++) = *(src ++));
}
void string_to_upper(STRPTR str) {
for (UWORD i = 0; str[i]; ++ i) {
str[i] = g.uppercase_lut[str[i]];
}
}
BOOL string_has_suffix(STRPTR name,
UBYTE* suffix,
UWORD suffix_len) {
UWORD name_len = string_length(name);
if (name_len <= suffix_len) {
return FALSE;
}
STRPTR suffix_start = name + (name_len - suffix_len);
for (UWORD i = 0; i < suffix_len; ++ i) {
if (suffix_start[i] != suffix[i]) {
return FALSE;
}
}
return TRUE;
}
BOOL string_has_prefix(STRPTR name,
UBYTE* prefix,
UWORD prefix_len) {
UWORD name_len = string_length(name);
if (name_len <= prefix_len) {
return FALSE;
}
for (UWORD i = 0; i < prefix_len; ++ i) {
if (name[i] != prefix[i]) {
return FALSE;
}
}
return TRUE;
}
void string_append_path(STRPTR base,
STRPTR subdir) {
UWORD base_len = string_length(base);
if (subdir[0] == '/') {
UWORD trim_to = base_len - 1;
while ((base[trim_to - 1] != '/') && (base[trim_to - 1] != ':') && (trim_to > 0)) {
-- trim_to;
}
base[trim_to] = '\0';
}
else {
UWORD base_len = string_length(base);
UWORD subdir_len = string_length(subdir);
STRPTR separator = base[0] ? "/" : ":";
string_copy(base + base_len, subdir);
string_copy(base + base_len + subdir_len, separator);
}
}
void print_error(STRPTR str) {
system_print_error(str);
}
UWORD random_mod4() {
static UWORD last_random = 0;
if (last_random == 0) {
last_random = random();
}
// Use all 16 bits of random number to form 2 bit values.
// Skipping bits can otherwise lead to unwanted correlation.
UWORD random4 = last_random & 3;
last_random >>= 2;
return random4;
}
static UWORD random() {
// LFSR PRNG (http://codebase64.org/doku.php?id=base:small_fast_16-bit_prng)
if (g.prng_seed == 0) {
g.prng_seed ^= kLFSRMagic;
}
else if (g.prng_seed == 0x8000) {
g.prng_seed = 0;
}
else {
UWORD carry = g.prng_seed & 0x8000;
g.prng_seed <<= 1;
if (carry) {
g.prng_seed ^= kLFSRMagic;
}
}
return g.prng_seed;
}