| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#ifndef HORUS_ENCODE_H |
|
2
|
|
|
|
|
|
|
#define HORUS_ENCODE_H |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
/* |
|
5
|
|
|
|
|
|
|
* horus_encode.h - High-performance encoding: hex, Base64, Base32, Crockford |
|
6
|
|
|
|
|
|
|
* |
|
7
|
|
|
|
|
|
|
* Hex uses a uint16_t lookup table: one table lookup per byte produces |
|
8
|
|
|
|
|
|
|
* two hex characters. ~4x faster than sprintf("%02x"). |
|
9
|
|
|
|
|
|
|
*/ |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#include |
|
12
|
|
|
|
|
|
|
#include |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
/* ── Hex lookup tables (compile-time initialised) ───────────────── */ |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#define HEX_PAIR(hi, lo) (uint16_t)( ((uint16_t)(lo) << 8) | (uint16_t)(hi) ) |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
/* Helper macro to generate 16 entries for a given high nibble */ |
|
19
|
|
|
|
|
|
|
#define HEX_ROW(h, H) \ |
|
20
|
|
|
|
|
|
|
HEX_PAIR(h,'0'), HEX_PAIR(h,'1'), HEX_PAIR(h,'2'), HEX_PAIR(h,'3'), \ |
|
21
|
|
|
|
|
|
|
HEX_PAIR(h,'4'), HEX_PAIR(h,'5'), HEX_PAIR(h,'6'), HEX_PAIR(h,'7'), \ |
|
22
|
|
|
|
|
|
|
HEX_PAIR(h,'8'), HEX_PAIR(h,'9'), HEX_PAIR(h,'a'), HEX_PAIR(h,'b'), \ |
|
23
|
|
|
|
|
|
|
HEX_PAIR(h,'c'), HEX_PAIR(h,'d'), HEX_PAIR(h,'e'), HEX_PAIR(h,'f') |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#define HEX_ROW_UPPER(h, H) \ |
|
26
|
|
|
|
|
|
|
HEX_PAIR(h,'0'), HEX_PAIR(h,'1'), HEX_PAIR(h,'2'), HEX_PAIR(h,'3'), \ |
|
27
|
|
|
|
|
|
|
HEX_PAIR(h,'4'), HEX_PAIR(h,'5'), HEX_PAIR(h,'6'), HEX_PAIR(h,'7'), \ |
|
28
|
|
|
|
|
|
|
HEX_PAIR(h,'8'), HEX_PAIR(h,'9'), HEX_PAIR(h,'A'), HEX_PAIR(h,'B'), \ |
|
29
|
|
|
|
|
|
|
HEX_PAIR(h,'C'), HEX_PAIR(h,'D'), HEX_PAIR(h,'E'), HEX_PAIR(h,'F') |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
static const uint16_t horus_hex_lut[256] = { |
|
32
|
|
|
|
|
|
|
HEX_ROW('0', '0'), HEX_ROW('1', '1'), HEX_ROW('2', '2'), HEX_ROW('3', '3'), |
|
33
|
|
|
|
|
|
|
HEX_ROW('4', '4'), HEX_ROW('5', '5'), HEX_ROW('6', '6'), HEX_ROW('7', '7'), |
|
34
|
|
|
|
|
|
|
HEX_ROW('8', '8'), HEX_ROW('9', '9'), HEX_ROW('a', 'a'), HEX_ROW('b', 'b'), |
|
35
|
|
|
|
|
|
|
HEX_ROW('c', 'c'), HEX_ROW('d', 'd'), HEX_ROW('e', 'e'), HEX_ROW('f', 'f') |
|
36
|
|
|
|
|
|
|
}; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
static const uint16_t horus_hex_lut_upper[256] = { |
|
39
|
|
|
|
|
|
|
HEX_ROW_UPPER('0', '0'), HEX_ROW_UPPER('1', '1'), HEX_ROW_UPPER('2', '2'), HEX_ROW_UPPER('3', '3'), |
|
40
|
|
|
|
|
|
|
HEX_ROW_UPPER('4', '4'), HEX_ROW_UPPER('5', '5'), HEX_ROW_UPPER('6', '6'), HEX_ROW_UPPER('7', '7'), |
|
41
|
|
|
|
|
|
|
HEX_ROW_UPPER('8', '8'), HEX_ROW_UPPER('9', '9'), HEX_ROW_UPPER('A', 'A'), HEX_ROW_UPPER('B', 'B'), |
|
42
|
|
|
|
|
|
|
HEX_ROW_UPPER('C', 'C'), HEX_ROW_UPPER('D', 'D'), HEX_ROW_UPPER('E', 'E'), HEX_ROW_UPPER('F', 'F') |
|
43
|
|
|
|
|
|
|
}; |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
/* Write two hex chars for one byte */ |
|
46
|
|
|
|
|
|
|
static inline void horus_hex_byte(char *dst, unsigned char b, const uint16_t *lut) { |
|
47
|
|
|
|
|
|
|
memcpy(dst, &lut[b], 2); |
|
48
|
|
|
|
|
|
|
} |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
/* Encode 16 bytes to 32 hex chars */ |
|
51
|
|
|
|
|
|
|
static inline void horus_hex_encode(char *dst, const unsigned char *src, const uint16_t *lut) { |
|
52
|
|
|
|
|
|
|
int i; |
|
53
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) { |
|
54
|
|
|
|
|
|
|
horus_hex_byte(dst + i * 2, src[i], lut); |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
/* ── Hex decode ─────────────────────────────────────────────────── */ |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
static const unsigned char horus_hex_val[256] = { |
|
61
|
|
|
|
|
|
|
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, |
|
62
|
|
|
|
|
|
|
['4'] = 4, ['5'] = 5, ['6'] = 6, ['7'] = 7, |
|
63
|
|
|
|
|
|
|
['8'] = 8, ['9'] = 9, |
|
64
|
|
|
|
|
|
|
['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15, |
|
65
|
|
|
|
|
|
|
['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15, |
|
66
|
|
|
|
|
|
|
}; |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
static inline int horus_is_hex(char c) { |
|
69
|
|
|
|
|
|
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
static inline int horus_hex_decode(unsigned char *dst, const char *src, int nhex) { |
|
73
|
|
|
|
|
|
|
int i; |
|
74
|
|
|
|
|
|
|
for (i = 0; i < nhex; i += 2) { |
|
75
|
|
|
|
|
|
|
if (!horus_is_hex(src[i]) || !horus_is_hex(src[i+1])) |
|
76
|
|
|
|
|
|
|
return 0; |
|
77
|
|
|
|
|
|
|
dst[i/2] = (horus_hex_val[(unsigned char)src[i]] << 4) |
|
78
|
|
|
|
|
|
|
| horus_hex_val[(unsigned char)src[i+1]]; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
return 1; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
/* ── Base64 encoding (no padding, 22 chars for 16 bytes) ────────── */ |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
static const char horus_b64_alphabet[] = |
|
86
|
|
|
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
static inline void horus_base64_encode(char *dst, const unsigned char *src) { |
|
89
|
|
|
|
|
|
|
int i, j = 0; |
|
90
|
|
|
|
|
|
|
/* Process 3 bytes at a time -> 4 base64 chars */ |
|
91
|
|
|
|
|
|
|
for (i = 0; i + 2 < 16; i += 3) { |
|
92
|
|
|
|
|
|
|
unsigned int v = ((unsigned int)src[i] << 16) |
|
93
|
|
|
|
|
|
|
| ((unsigned int)src[i+1] << 8) |
|
94
|
|
|
|
|
|
|
| (unsigned int)src[i+2]; |
|
95
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[(v >> 18) & 0x3F]; |
|
96
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[(v >> 12) & 0x3F]; |
|
97
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[(v >> 6) & 0x3F]; |
|
98
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[v & 0x3F]; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
/* Last byte (16 % 3 = 1 remaining byte) */ |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
|
|
|
|
|
|
unsigned int v = (unsigned int)src[15] << 16; |
|
103
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[(v >> 18) & 0x3F]; |
|
104
|
|
|
|
|
|
|
dst[j++] = horus_b64_alphabet[(v >> 12) & 0x3F]; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
/* j == 22 */ |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
/* ── Base64 decoding ────────────────────────────────────────────── */ |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
static const unsigned char horus_b64_decode_table[256] = { |
|
112
|
|
|
|
|
|
|
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, |
|
113
|
|
|
|
|
|
|
['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, |
|
114
|
|
|
|
|
|
|
['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17, |
|
115
|
|
|
|
|
|
|
['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, |
|
116
|
|
|
|
|
|
|
['Y'] = 24, ['Z'] = 25, |
|
117
|
|
|
|
|
|
|
['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, |
|
118
|
|
|
|
|
|
|
['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, |
|
119
|
|
|
|
|
|
|
['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, |
|
120
|
|
|
|
|
|
|
['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49, |
|
121
|
|
|
|
|
|
|
['y'] = 50, ['z'] = 51, |
|
122
|
|
|
|
|
|
|
['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, |
|
123
|
|
|
|
|
|
|
['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63, |
|
124
|
|
|
|
|
|
|
}; |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
static inline int horus_base64_decode(unsigned char *dst, const char *src, int len) { |
|
127
|
|
|
|
|
|
|
int i, j = 0; |
|
128
|
|
|
|
|
|
|
/* Process 4 chars at a time -> 3 bytes */ |
|
129
|
|
|
|
|
|
|
for (i = 0; i + 3 < len; i += 4) { |
|
130
|
|
|
|
|
|
|
unsigned int v = ((unsigned int)horus_b64_decode_table[(unsigned char)src[i]] << 18) |
|
131
|
|
|
|
|
|
|
| ((unsigned int)horus_b64_decode_table[(unsigned char)src[i+1]] << 12) |
|
132
|
|
|
|
|
|
|
| ((unsigned int)horus_b64_decode_table[(unsigned char)src[i+2]] << 6) |
|
133
|
|
|
|
|
|
|
| (unsigned int)horus_b64_decode_table[(unsigned char)src[i+3]]; |
|
134
|
|
|
|
|
|
|
dst[j++] = (unsigned char)(v >> 16); |
|
135
|
|
|
|
|
|
|
dst[j++] = (unsigned char)(v >> 8); |
|
136
|
|
|
|
|
|
|
dst[j++] = (unsigned char)(v); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
/* Last 2 chars -> 1 byte (22 chars: 5 groups of 4 + 2 remaining) */ |
|
139
|
|
|
|
|
|
|
if (i + 1 < len) { |
|
140
|
|
|
|
|
|
|
unsigned int v = ((unsigned int)horus_b64_decode_table[(unsigned char)src[i]] << 18) |
|
141
|
|
|
|
|
|
|
| ((unsigned int)horus_b64_decode_table[(unsigned char)src[i+1]] << 12); |
|
142
|
|
|
|
|
|
|
dst[j++] = (unsigned char)(v >> 16); |
|
143
|
|
|
|
|
|
|
} |
|
144
|
|
|
|
|
|
|
return j; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
/* ── Base32 encoding (RFC 4648, 26 chars for 16 bytes) ──────────── */ |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
static const char horus_b32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
static inline void horus_base32_encode(char *dst, const unsigned char *src) { |
|
152
|
|
|
|
|
|
|
/* 16 bytes = 128 bits. 128 / 5 = 25 full groups + 3 bits. |
|
153
|
|
|
|
|
|
|
* With padding that's 26 chars (last char encodes 3 bits, padded). */ |
|
154
|
|
|
|
|
|
|
int i, bit_pos = 0, byte_pos = 0, j = 0; |
|
155
|
|
|
|
|
|
|
for (i = 0; i < 26; i++) { |
|
156
|
|
|
|
|
|
|
int val = 0; |
|
157
|
|
|
|
|
|
|
int bits_needed = 5; |
|
158
|
|
|
|
|
|
|
int bits_have = 0; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
while (bits_have < bits_needed && byte_pos < 16) { |
|
161
|
|
|
|
|
|
|
int bits_left_in_byte = 8 - bit_pos; |
|
162
|
|
|
|
|
|
|
int bits_to_take = bits_needed - bits_have; |
|
163
|
|
|
|
|
|
|
if (bits_to_take > bits_left_in_byte) |
|
164
|
|
|
|
|
|
|
bits_to_take = bits_left_in_byte; |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
val = (val << bits_to_take) | ((src[byte_pos] >> (bits_left_in_byte - bits_to_take)) & ((1 << bits_to_take) - 1)); |
|
167
|
|
|
|
|
|
|
bits_have += bits_to_take; |
|
168
|
|
|
|
|
|
|
bit_pos += bits_to_take; |
|
169
|
|
|
|
|
|
|
if (bit_pos >= 8) { |
|
170
|
|
|
|
|
|
|
bit_pos = 0; |
|
171
|
|
|
|
|
|
|
byte_pos++; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
/* Pad remaining bits with zero if we ran out of data */ |
|
175
|
|
|
|
|
|
|
if (bits_have < bits_needed) { |
|
176
|
|
|
|
|
|
|
val <<= (bits_needed - bits_have); |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
dst[j++] = horus_b32_alphabet[val & 0x1F]; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
/* ── Base32 decoding ────────────────────────────────────────────── */ |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
static const unsigned char horus_b32_decode_table[256] = { |
|
185
|
|
|
|
|
|
|
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, |
|
186
|
|
|
|
|
|
|
['F'] = 5, ['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, |
|
187
|
|
|
|
|
|
|
['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, |
|
188
|
|
|
|
|
|
|
['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, |
|
189
|
|
|
|
|
|
|
['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, |
|
190
|
|
|
|
|
|
|
['Z'] = 25, |
|
191
|
|
|
|
|
|
|
['2'] = 26, ['3'] = 27, ['4'] = 28, ['5'] = 29, ['6'] = 30, ['7'] = 31, |
|
192
|
|
|
|
|
|
|
/* lowercase aliases */ |
|
193
|
|
|
|
|
|
|
['a'] = 0, ['b'] = 1, ['c'] = 2, ['d'] = 3, ['e'] = 4, |
|
194
|
|
|
|
|
|
|
['f'] = 5, ['g'] = 6, ['h'] = 7, ['i'] = 8, ['j'] = 9, |
|
195
|
|
|
|
|
|
|
['k'] = 10, ['l'] = 11, ['m'] = 12, ['n'] = 13, ['o'] = 14, |
|
196
|
|
|
|
|
|
|
['p'] = 15, ['q'] = 16, ['r'] = 17, ['s'] = 18, ['t'] = 19, |
|
197
|
|
|
|
|
|
|
['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23, ['y'] = 24, |
|
198
|
|
|
|
|
|
|
['z'] = 25, |
|
199
|
|
|
|
|
|
|
}; |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
static inline int horus_base32_decode(unsigned char *dst, const char *src, int len) { |
|
202
|
|
|
|
|
|
|
int i, bit_pos = 0, byte_pos = 0; |
|
203
|
|
|
|
|
|
|
memset(dst, 0, 16); |
|
204
|
|
|
|
|
|
|
for (i = 0; i < len && byte_pos < 16; i++) { |
|
205
|
|
|
|
|
|
|
unsigned char val = horus_b32_decode_table[(unsigned char)src[i]]; |
|
206
|
|
|
|
|
|
|
int bits_left = 5; |
|
207
|
|
|
|
|
|
|
while (bits_left > 0 && byte_pos < 16) { |
|
208
|
|
|
|
|
|
|
int space = 8 - bit_pos; |
|
209
|
|
|
|
|
|
|
if (bits_left >= space) { |
|
210
|
|
|
|
|
|
|
dst[byte_pos] |= (val >> (bits_left - space)) & ((1 << space) - 1); |
|
211
|
|
|
|
|
|
|
bits_left -= space; |
|
212
|
|
|
|
|
|
|
bit_pos = 0; |
|
213
|
|
|
|
|
|
|
byte_pos++; |
|
214
|
|
|
|
|
|
|
} else { |
|
215
|
|
|
|
|
|
|
dst[byte_pos] |= (val & ((1 << bits_left) - 1)) << (space - bits_left); |
|
216
|
|
|
|
|
|
|
bit_pos += bits_left; |
|
217
|
|
|
|
|
|
|
bits_left = 0; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
} |
|
221
|
|
|
|
|
|
|
return byte_pos; |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
/* ── Crockford Base32 encoding (26 chars for 16 bytes) ──────────── */ |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
static const char horus_crockford_alphabet[] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; |
|
227
|
|
|
|
|
|
|
|
|
228
|
2858
|
|
|
|
|
|
static inline void horus_crockford_encode(char *dst, const unsigned char *src) { |
|
229
|
2858
|
|
|
|
|
|
int i, bit_pos = 0, byte_pos = 0, j = 0; |
|
230
|
77166
|
100
|
|
|
|
|
for (i = 0; i < 26; i++) { |
|
231
|
74308
|
|
|
|
|
|
int val = 0; |
|
232
|
74308
|
|
|
|
|
|
int bits_needed = 5; |
|
233
|
74308
|
|
|
|
|
|
int bits_have = 0; |
|
234
|
|
|
|
|
|
|
|
|
235
|
182912
|
100
|
|
|
|
|
while (bits_have < bits_needed && byte_pos < 16) { |
|
|
|
100
|
|
|
|
|
|
|
236
|
108604
|
|
|
|
|
|
int bits_left_in_byte = 8 - bit_pos; |
|
237
|
108604
|
|
|
|
|
|
int bits_to_take = bits_needed - bits_have; |
|
238
|
108604
|
100
|
|
|
|
|
if (bits_to_take > bits_left_in_byte) |
|
239
|
37154
|
|
|
|
|
|
bits_to_take = bits_left_in_byte; |
|
240
|
|
|
|
|
|
|
|
|
241
|
108604
|
|
|
|
|
|
val = (val << bits_to_take) | ((src[byte_pos] >> (bits_left_in_byte - bits_to_take)) & ((1 << bits_to_take) - 1)); |
|
242
|
108604
|
|
|
|
|
|
bits_have += bits_to_take; |
|
243
|
108604
|
|
|
|
|
|
bit_pos += bits_to_take; |
|
244
|
108604
|
100
|
|
|
|
|
if (bit_pos >= 8) { |
|
245
|
45728
|
|
|
|
|
|
bit_pos = 0; |
|
246
|
45728
|
|
|
|
|
|
byte_pos++; |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
} |
|
249
|
74308
|
100
|
|
|
|
|
if (bits_have < bits_needed) { |
|
250
|
2858
|
|
|
|
|
|
val <<= (bits_needed - bits_have); |
|
251
|
|
|
|
|
|
|
} |
|
252
|
74308
|
|
|
|
|
|
dst[j++] = horus_crockford_alphabet[val & 0x1F]; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
2858
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
/* ── Crockford Base32 decoding ──────────────────────────────────── */ |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
static const unsigned char horus_crockford_decode_table[256] = { |
|
259
|
|
|
|
|
|
|
['0'] = 0, ['O'] = 0, ['o'] = 0, |
|
260
|
|
|
|
|
|
|
['1'] = 1, ['I'] = 1, ['i'] = 1, ['L'] = 1, ['l'] = 1, |
|
261
|
|
|
|
|
|
|
['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5, ['6'] = 6, |
|
262
|
|
|
|
|
|
|
['7'] = 7, ['8'] = 8, ['9'] = 9, |
|
263
|
|
|
|
|
|
|
['A'] = 10, ['a'] = 10, |
|
264
|
|
|
|
|
|
|
['B'] = 11, ['b'] = 11, |
|
265
|
|
|
|
|
|
|
['C'] = 12, ['c'] = 12, |
|
266
|
|
|
|
|
|
|
['D'] = 13, ['d'] = 13, |
|
267
|
|
|
|
|
|
|
['E'] = 14, ['e'] = 14, |
|
268
|
|
|
|
|
|
|
['F'] = 15, ['f'] = 15, |
|
269
|
|
|
|
|
|
|
['G'] = 16, ['g'] = 16, |
|
270
|
|
|
|
|
|
|
['H'] = 17, ['h'] = 17, |
|
271
|
|
|
|
|
|
|
['J'] = 18, ['j'] = 18, |
|
272
|
|
|
|
|
|
|
['K'] = 19, ['k'] = 19, |
|
273
|
|
|
|
|
|
|
['M'] = 20, ['m'] = 20, |
|
274
|
|
|
|
|
|
|
['N'] = 21, ['n'] = 21, |
|
275
|
|
|
|
|
|
|
['P'] = 22, ['p'] = 22, |
|
276
|
|
|
|
|
|
|
['Q'] = 23, ['q'] = 23, |
|
277
|
|
|
|
|
|
|
['R'] = 24, ['r'] = 24, |
|
278
|
|
|
|
|
|
|
['S'] = 25, ['s'] = 25, |
|
279
|
|
|
|
|
|
|
['T'] = 26, ['t'] = 26, |
|
280
|
|
|
|
|
|
|
['V'] = 27, ['v'] = 27, |
|
281
|
|
|
|
|
|
|
['W'] = 28, ['w'] = 28, |
|
282
|
|
|
|
|
|
|
['X'] = 29, ['x'] = 29, |
|
283
|
|
|
|
|
|
|
['Y'] = 30, ['y'] = 30, |
|
284
|
|
|
|
|
|
|
['Z'] = 31, ['z'] = 31, |
|
285
|
|
|
|
|
|
|
}; |
|
286
|
|
|
|
|
|
|
|
|
287
|
107
|
|
|
|
|
|
static inline int horus_crockford_decode(unsigned char *dst, const char *src, int len) { |
|
288
|
107
|
|
|
|
|
|
int i, bit_pos = 0, byte_pos = 0; |
|
289
|
107
|
|
|
|
|
|
memset(dst, 0, 16); |
|
290
|
2889
|
100
|
|
|
|
|
for (i = 0; i < len && byte_pos < 16; i++) { |
|
|
|
50
|
|
|
|
|
|
|
291
|
2782
|
|
|
|
|
|
unsigned char val = horus_crockford_decode_table[(unsigned char)src[i]]; |
|
292
|
2782
|
|
|
|
|
|
int bits_left = 5; |
|
293
|
6848
|
100
|
|
|
|
|
while (bits_left > 0 && byte_pos < 16) { |
|
|
|
100
|
|
|
|
|
|
|
294
|
4066
|
|
|
|
|
|
int space = 8 - bit_pos; |
|
295
|
4066
|
100
|
|
|
|
|
if (bits_left >= space) { |
|
296
|
1712
|
|
|
|
|
|
dst[byte_pos] |= (val >> (bits_left - space)) & ((1 << space) - 1); |
|
297
|
1712
|
|
|
|
|
|
bits_left -= space; |
|
298
|
1712
|
|
|
|
|
|
bit_pos = 0; |
|
299
|
1712
|
|
|
|
|
|
byte_pos++; |
|
300
|
|
|
|
|
|
|
} else { |
|
301
|
2354
|
|
|
|
|
|
dst[byte_pos] |= (val & ((1 << bits_left) - 1)) << (space - bits_left); |
|
302
|
2354
|
|
|
|
|
|
bit_pos += bits_left; |
|
303
|
2354
|
|
|
|
|
|
bits_left = 0; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
} |
|
307
|
107
|
|
|
|
|
|
return byte_pos; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
#endif /* HORUS_ENCODE_H */ |