Import ezmlm-idx 0.40
[ezmlm] / encodeB.c
1 /* $Id: encodeB.c,v 1.3 1998/03/21 18:30:27 lindberg Exp $*/
2 /* $Name: ezmlm-idx-040 $*/
3
4 #include "stralloc.h"
5 #include "uint32.h"
6 #include "mime.h"
7 #include "strerr.h"
8 #include "errtxt.h"
9
10 static void die_nomem(fatal)
11 char *fatal;
12 {
13 strerr_die2x(111,fatal,ERR_NOMEM);
14 }
15
16 static unsigned char base64char[] =
17 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18
19 static unsigned int pos = 0;
20 static unsigned int i = 0;
21 static uint32 hold32;
22 static unsigned char *cpout;
23
24 static void addone(ch)
25 unsigned char ch;
26 {
27 if (!(pos++))
28 hold32 = (uint32) ch;
29 else
30 hold32 = (hold32 << 8) | ch;
31 if (pos == 3) {
32 *cpout++ = base64char[(hold32 >> 18) & 0x3f];
33 *cpout++ = base64char[(hold32 >> 12) & 0x3f];
34 *cpout++ = base64char[(hold32 >> 6) & 0x3f];
35 *cpout++ = base64char[hold32 & 0x3f];
36 if (++i == 18) {
37 *cpout++ = '\n';
38 i = 0;
39 }
40 pos = 0;
41 }
42 }
43
44 static void dorest()
45 {
46 switch (pos) {
47 case 2:
48 hold32 = hold32 << 2;
49 *cpout++ = base64char[(hold32 >> 12) & 0x3f];
50 *cpout++ = base64char[(hold32 >> 06) & 0x3f];
51 *cpout++ = base64char[hold32 & 0x3f];
52 *cpout++ = '=';
53 break;
54 case 1:
55 hold32 = hold32 << 4;
56 *cpout++ = base64char[(hold32 >> 06) & 0x3f];
57 *cpout++ = base64char[hold32 & 0x3f];
58 *cpout++ = '=';
59 *cpout++ = '=';
60 break;
61 default:
62 break;
63 }
64 *cpout++ = '\n';
65 }
66
67 void encodeB(indata,n,outdata,control,fatal)
68 unsigned char *indata;
69 unsigned int n;
70 stralloc *outdata;
71 int control; /* 1 = init, 2 = flush */
72 char *fatal;
73 /* converts any character with the high order bit set to */
74 /* base64. In: n chars of indata, out: stralloc outdata */
75 /* as '=' is not allowed within the block, we cannot flush after */
76 /* each line, so we carry over data from call to call. The last */
77 /* call to encodeB should have control = 2 to do the flushing. */
78 /* control = 0 resets, and the routine starts out reset. */
79 {
80 register unsigned char ch;
81
82 if (control == 1) {
83 pos = 0;
84 i = 0;
85 }
86 if (!stralloc_copys(outdata,"")) die_nomem(fatal);
87 if (!stralloc_ready(outdata,n*8/3 + n/72 + 5)) die_nomem(fatal);
88 cpout = (unsigned char *) outdata->s;
89 while (n--) {
90 ch = *indata++;
91 if (ch == '\n')
92 addone('\r');
93 addone(ch);
94 }
95 if (control == 2)
96 dorest();
97 outdata->len = (unsigned int) (cpout - (unsigned char *) outdata->s);
98 }
99