Make WvStreams compile with gcc 4.4.
[wvstreams.git] / utils / wvbase64.cc
blob7135e2af331fd4393e5a99f133c9c0f4b723a86a
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Functions for encoding and decoding strings in MIME's Base64 notation.
7 * Base 64 is pretty easy. The input is processed in groups of three bytes.
8 * These 24 bits are split into 4 groups of 6 bits. Each group of six bits
9 * is represented by one character in the base64 alphabet, in the encoded
10 * output. The alphabet is as follows:
11 * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
12 * Where 'A' through '/' represent 000000 through 011111, the 64 different
13 * combinations. The '=' (100000) is padding and has no value when decoded.
15 #include "wvbase64.h"
17 // maps codes to the Base64 alphabet
18 static char alphabet[67] =
19 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
21 // finds codes in the Base64 alphabet
22 static int lookup(char ch)
24 if (ch >= 'A' && ch <= 'Z')
25 return ch - 'A';
26 if (ch >= 'a' && ch <= 'z')
27 return ch - 'a' + 26;
28 if (ch >= '0' && ch <= '9')
29 return ch - '0' + 52;
30 if (ch == '+')
31 return 62;
32 if (ch == '/')
33 return 63;
34 if (ch == '=')
35 return 64; // padding
36 if (ch == '\n' || ch == ' ' || ch == '\r' || ch == '\t' ||
37 ch == '\f' || ch == '\v')
38 return 65; // whitespace
39 return -1;
43 /***** WvBase64Encoder *****/
45 WvBase64Encoder::WvBase64Encoder()
47 _reset();
51 bool WvBase64Encoder::_reset()
53 state = ATBIT0;
54 bits = 0;
55 return true;
59 bool WvBase64Encoder::_encode(WvBuf &in, WvBuf &out, bool flush)
61 // base 64 encode the entire buffer
62 while (in.used() != 0)
64 unsigned char next = in.getch();
65 bits = (bits << 8) | next;
66 switch (state)
68 case ATBIT0:
69 out.putch(alphabet[bits >> 2]);
70 bits &= 0x03;
71 state = ATBIT2;
72 break;
73 case ATBIT2:
74 out.putch(alphabet[bits >> 4]);
75 bits &= 0x0f;
76 state = ATBIT4;
77 break;
78 case ATBIT4:
79 out.putch(alphabet[bits >> 6]);
80 out.putch(alphabet[bits & 0x3f]);
81 bits = 0;
82 state = ATBIT0;
83 break;
86 // do not consider the data flushed if we need padding
87 if (flush && state != ATBIT0)
88 return false;
89 return true;
93 bool WvBase64Encoder::_finish(WvBuf &out)
95 // pad text if needed
96 switch (state)
98 case ATBIT2:
99 out.putch(alphabet[bits << 4]);
100 out.putch('=');
101 out.putch('=');
102 break;
103 case ATBIT4:
104 out.putch(alphabet[bits << 2]);
105 out.putch('=');
106 break;
107 case ATBIT0:
108 break;
110 return true;
115 /***** WvBase64Decoder *****/
117 WvBase64Decoder::WvBase64Decoder()
119 _reset();
123 bool WvBase64Decoder::_reset()
125 state = ATBIT0;
126 bits = 0;
127 return true;
131 bool WvBase64Decoder::_encode(WvBuf &in, WvBuf &out, bool flush)
133 // base 64 decode the entire buffer
134 while (in.used() != 0)
136 unsigned char next = in.getch();
137 int symbol = lookup(next);
138 switch (symbol)
140 case -1: // invalid character
141 seterror("invalid character #%s in base64 input", next);
142 return false;
144 case 64: // padding
145 // strip out any remaining padding
146 // we are lenient in that we do not track how much padding we skip
147 setfinished();
148 state = PAD;
149 break;
151 case 65: // whitespace
152 break;
154 default: // other symbol
155 bits = (bits << 6) | symbol;
156 switch (state)
158 case ATBIT0:
159 state = ATBIT2;
160 break;
161 case ATBIT2:
162 out.putch(bits >> 4);
163 bits &= 0x0f;
164 state = ATBIT4;
165 break;
166 case ATBIT4:
167 out.putch(bits >> 2);
168 bits &= 0x03;
169 state = ATBIT6;
170 break;
171 case ATBIT6:
172 out.putch(bits);
173 bits = 0;
174 state = ATBIT0;
175 break;
177 case PAD:
178 seterror("invalid character #%s "
179 "after base64 padding", next);
180 return false;
182 break;
185 // if flushing and we did not get sufficient padding, then fail
186 if (flush && (state == ATBIT2 || state == ATBIT4 || state == ATBIT6))
187 return false; // insufficient padding to flush!
188 return true;