base64.c - ics2txt - convert icalendar .ics file to plain text | |
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
base64.c (3039B) | |
--- | |
1 #include "base64.h" | |
2 #include <assert.h> | |
3 #include <stddef.h> | |
4 #include <stdint.h> | |
5 #include <string.h> | |
6 | |
7 static char encode_map[64] = | |
8 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
9 | |
10 void | |
11 base64_encode(char const *s, size_t slen, char *d, size_t *dlen) | |
12 { | |
13 char const *sbeg = s, *send = s + slen, *dbeg = d; | |
14 unsigned char x; | |
15 | |
16 while (s < send) { | |
17 switch ((s - sbeg) % 3) { | |
18 case 0: /* AAAAAABB bbbbcccc ccdddddd */ | |
19 assert((size_t)(d - dbeg) + 1 < *dlen); | |
20 *d++ = encode_map[*s >> 2]; | |
21 x = *s << 4 & 0x3f; | |
22 break; | |
23 case 1: /* aaaaaabb BBBBCCCC ccdddddd */ | |
24 assert((size_t)(d - dbeg) + 1 < *dlen); | |
25 *d++ = encode_map[x | (*s >> 4)]; | |
26 x = (*s << 2) & 0x3f; | |
27 break; | |
28 case 2: /* aaaaaabb bbbbcccc CCDDDDDD */ | |
29 assert((size_t)(d - dbeg) + 2 < *dlen); | |
30 *d++ = encode_map[x | (*s >> 6)]; | |
31 *d++ = encode_map[*s & 0x3f]; | |
32 break; | |
33 } | |
34 s++; | |
35 } | |
36 | |
37 /* flush extra content in 'x' */ | |
38 assert((size_t)(d - dbeg) + 1 < *dlen); | |
39 if ((s - sbeg) % 3 != 2) | |
40 *d++ = encode_map[x]; | |
41 | |
42 /* pad the end with '=' */ | |
43 while ((d - dbeg) % 4 != 0) { | |
44 assert((size_t)(d - dbeg) + 1 < *dlen); | |
45 *d++ = '='; | |
46 } | |
47 | |
48 *dlen = d - dbeg; | |
49 } | |
50 | |
51 static int8_t decode_map[256] = { | |
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, | |
55 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, | |
56 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
57 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | |
58 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | |
59 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, | |
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
68 }; | |
69 | |
70 int | |
71 base64_decode(char const *s, size_t *slen, char *d, size_t *dlen) | |
72 { | |
73 char const *sbeg = s, *send = sbeg + *slen, *dbeg = d; | |
74 | |
75 for (; s + 3 < send; s += 4) { | |
76 int8_t x0 = decode_map[(unsigned)s[0]]; | |
77 int8_t x1 = decode_map[(unsigned)s[1]]; | |
78 int8_t x2 = decode_map[(unsigned)s[2]]; | |
79 int8_t x3 = decode_map[(unsigned)s[3]]; | |
80 uint32_t x = (x0 << 18) | (x1 << 12) | (x2 << 6) | (x3 <… | |
81 | |
82 assert((size_t)(d - dbeg) + 3 < *dlen); | |
83 *d++ = x >> 16; | |
84 *d++ = x >> 8 & 0xff; | |
85 *d++ = x & 0xff; | |
86 | |
87 /* only "xxxx" or "xxx=" or "xx==" allowed */ | |
88 if (s[0] == '=' || s[1] == '=' || (s[2] == '=' && s[3] !… | |
89 return -2; | |
90 if (s[2] == '=') | |
91 d--; | |
92 if (s[3] == '=') { | |
93 d--; | |
94 break; | |
95 } | |
96 | |
97 if (x0 < 0 || x1 < 0 || x2 < 0 || x3 < 0) | |
98 return -1; | |
99 } | |
100 | |
101 *slen = s - sbeg; | |
102 *dlen = d - dbeg; | |
103 return 0; | |
104 } |