]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/port/u64.c
libc: add encode(2) variants for custom alphabets
[plan9front.git] / sys / src / libc / port / u64.c
1 #include <u.h>
2 #include <libc.h>
3
4 #define between(x,min,max)      (((min-1-x) & (x-max-1))>>8)
5
6 int
7 enc64chr(int o)
8 {
9         int c;
10
11         c  = between(o,  0, 25) & ('A'+o);
12         c |= between(o, 26, 51) & ('a'+(o-26));
13         c |= between(o, 52, 61) & ('0'+(o-52));
14         c |= between(o, 62, 62) & ('+');
15         c |= between(o, 63, 63) & ('/');
16         return c;
17 }
18
19 int
20 dec64chr(int c)
21 {
22         int o;
23
24         o  = between(c, 'A', 'Z') & (1+(c-'A'));
25         o |= between(c, 'a', 'z') & (1+26+(c-'a'));
26         o |= between(c, '0', '9') & (1+52+(c-'0'));
27         o |= between(c, '+', '+') & (1+62);
28         o |= between(c, '/', '/') & (1+63);
29         return o-1;
30 }
31
32 int
33 dec64x(uchar *out, int lim, char *in, int n, int (*chr)(int))
34 {
35         ulong b24;
36         uchar *start = out;
37         uchar *e = out + lim;
38         int i, c;
39
40         b24 = 0;
41         i = 0;
42         while(n-- > 0){
43                 c = chr(*in++);
44                 if(c < 0)
45                         continue;
46                 switch(i){
47                 case 0:
48                         b24 = c<<18;
49                         break;
50                 case 1:
51                         b24 |= c<<12;
52                         break;
53                 case 2:
54                         b24 |= c<<6;
55                         break;
56                 case 3:
57                         if(out + 3 > e)
58                                 goto exhausted;
59
60                         b24 |= c;
61                         *out++ = b24>>16;
62                         *out++ = b24>>8;
63                         *out++ = b24;
64                         i = 0;
65                         continue;
66                 }
67                 i++;
68         }
69         switch(i){
70         case 2:
71                 if(out + 1 > e)
72                         goto exhausted;
73                 *out++ = b24>>16;
74                 break;
75         case 3:
76                 if(out + 2 > e)
77                         goto exhausted;
78                 *out++ = b24>>16;
79                 *out++ = b24>>8;
80                 break;
81         }
82 exhausted:
83         return out - start;
84 }
85
86 int
87 enc64x(char *out, int lim, uchar *in, int n, int (*chr)(int))
88 {
89         int i;
90         ulong b24;
91         char *start = out;
92         char *e = out + lim;
93
94         for(i = n/3; i > 0; i--){
95                 b24 = *in++<<16;
96                 b24 |= *in++<<8;
97                 b24 |= *in++;
98                 if(out + 4 >= e)
99                         goto exhausted;
100                 *out++ = chr(b24>>18);
101                 *out++ = chr((b24>>12)&0x3f);
102                 *out++ = chr((b24>>6)&0x3f);
103                 *out++ = chr(b24&0x3f);
104         }
105
106         switch(n%3){
107         case 2:
108                 b24 = *in++<<16;
109                 b24 |= *in<<8;
110                 if(out + 4 >= e)
111                         goto exhausted;
112                 *out++ = chr(b24>>18);
113                 *out++ = chr((b24>>12)&0x3f);
114                 *out++ = chr((b24>>6)&0x3f);
115                 *out++ = '=';
116                 break;
117         case 1:
118                 b24 = *in<<16;
119                 if(out + 4 >= e)
120                         goto exhausted;
121                 *out++ = chr(b24>>18);
122                 *out++ = chr((b24>>12)&0x3f);
123                 *out++ = '=';
124                 *out++ = '=';
125                 break;
126         }
127 exhausted:
128         *out = 0;
129         return out - start;
130 }
131
132 int
133 enc64(char *out, int lim, uchar *in, int n)
134 {
135         return enc64x(out, lim, in, n, enc64chr);
136 }
137
138 int
139 dec64(uchar *out, int lim, char *in, int n)
140 {
141         return dec64x(out, lim, in, n, dec64chr);
142 }