-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathencoding.c
72 lines (56 loc) · 2.13 KB
/
encoding.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
#include "include/encoding.h"
#define LOOKUP_CANARY 255
//Encoding and decoding lookup tables table for each of the 2-bit values
char encode_lookup_tbl[] = { '\t', '\n', '\r', ' ' };
unsigned char decode_lookup_tbl[256];
// Build the decoding table, including a canary to help
// us detect invalid bytes. The buffer needs to be freed by
// the caller.
void alloc_decode_lookup_tbl(void) {
int x;
//Fill the entire array with our canary
for (x = 0; x < 256; x++) {
decode_lookup_tbl[x] = LOOKUP_CANARY;
}
//Add the four encoding characters by using the inverse
//of the encoding table
for (x = 0; x < 4; x++) {
decode_lookup_tbl[ encode_lookup_tbl[x] ] = x;
}
}
//Encode each 2 bits of the byte into whitespace
ssize_t ws_encode(const unsigned char *bytes_in, unsigned char *ws_out, const ssize_t bytes) {
int x, y;
for (x = 0; x < bytes; x++) {
for (y = 0; y < 4; y++) {
//For each two bits in the byte, look up its value (0 to 3) in the
//lookup table and add it to the outbound whitespace buffer, taking into
//account that each inbound byte becomes four outbound bytes
ws_out[(4 * x) + y] = encode_lookup_tbl[ (bytes_in[x] >> (2 * y)) & 0x03 ];
}
}
return x * 4;
}
//Decode each group of four bytes back into a single byte.
ssize_t ws_decode(const unsigned char *ws_in, unsigned char *bytes_out, const ssize_t bytes_read) {
int x, y;
unsigned char dibit;
for (x = 0; x < bytes_read; x += 4) {
//Ensure out destination byte is zeroed out.
*bytes_out = 0;
for (y = 0; y < 4; y++) {
//Pull each of the two bits of our outbound byte from
//four of the inbound bytes.
dibit = decode_lookup_tbl[ ws_in[x + y] ];
//Ensure our inbound whitespace byte is
//valid for our encoding
if (dibit == LOOKUP_CANARY) {
return 0;
}
//Or in the two bits at the appropriate position in the byte
*bytes_out |= dibit << (2 * y);
}
*bytes_out++;
}
return x / 4;
}