Code

fix some includes
[inkscape.git] / src / dom / io / base64stream.cpp
1 /**\r
2  * Phoebe DOM Implementation.\r
3  *\r
4  * Base64-enabled input and output streams\r
5  *\r
6  * This class allows easy encoding and decoding\r
7  * of Base64 data with a stream interface, hiding\r
8  * the implementation from the user.\r
9  *\r
10  * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html\r
11  *\r
12  * Authors:\r
13  *   Bob Jamison\r
14  *\r
15  * Copyright (C) 2006 Bob Jamison\r
16  *\r
17  *  This library is free software; you can redistribute it and/or\r
18  *  modify it under the terms of the GNU Lesser General Public\r
19  *  License as published by the Free Software Foundation; either\r
20  *  version 2.1 of the License, or (at your option) any later version.\r
21  *\r
22  *  This library is distributed in the hope that it will be useful,\r
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
25  *  Lesser General Public License for more details.\r
26  *\r
27  *  You should have received a copy of the GNU Lesser General Public\r
28  *  License along with this library; if not, write to the Free Software\r
29  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
30  */\r
31 \r
32 \r
33 \r
34 #include "base64stream.h"\r
35 \r
36 \r
37 namespace org\r
38 {\r
39 namespace w3c\r
40 {\r
41 namespace dom\r
42 {\r
43 namespace io\r
44 {\r
45 \r
46 \r
47 //#########################################################################\r
48 //# B A S E 6 4    I N P U T    S T R E A M\r
49 //#########################################################################\r
50 \r
51 static int base64decode[] =\r
52 {\r
53 /*00*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,\r
54 /*08*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,\r
55 /*10*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,\r
56 /*18*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,\r
57 /*20*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,\r
58 /*28*/    -1,   -1,   -1,   62,   -1,   -1,   -1,   63,\r
59 /*30*/    52,   53,   54,   55,   56,   57,   58,   59,\r
60 /*38*/    60,   61,   -1,   -1,   -1,   -1,   -1,   -1,\r
61 /*40*/    -1,    0,    1,    2,    3,    4,    5,    6,\r
62 /*48*/     7,    8,    9,   10,   11,   12,   13,   14,\r
63 /*50*/    15,   16,   17,   18,   19,   20,   21,   22,\r
64 /*58*/    23,   24,   25,   -1,   -1,   -1,   -1,   -1,\r
65 /*60*/    -1,   26,   27,   28,   29,   30,   31,   32,\r
66 /*68*/    33,   34,   35,   36,   37,   38,   39,   40,\r
67 /*70*/    41,   42,   43,   44,   45,   46,   47,   48,\r
68 /*78*/    49,   50,   51,   -1,   -1,   -1,   -1,   -1\r
69 };\r
70 \r
71 \r
72 /**\r
73  *\r
74  */\r
75 Base64InputStream::Base64InputStream(InputStream &sourceStream)\r
76                     : BasicInputStream(sourceStream)\r
77 {\r
78     outCount = 0;\r
79     padCount = 0;\r
80     closed   = false;\r
81     done     = false;\r
82 }\r
83 \r
84 /**\r
85  *\r
86  */\r
87 Base64InputStream::~Base64InputStream()\r
88 {\r
89     close();\r
90 }\r
91 \r
92 /**\r
93  * Returns the number of bytes that can be read (or skipped over) from\r
94  * this input stream without blocking by the next caller of a method for\r
95  * this input stream.\r
96  */\r
97 int Base64InputStream::available()\r
98 {\r
99     if (closed )\r
100         return 0;\r
101     int len = source.available() * 2 / 3;\r
102     return len;\r
103 }\r
104 \r
105 \r
106 /**\r
107  *  Closes this input stream and releases any system resources\r
108  *  associated with the stream.\r
109  */\r
110 void Base64InputStream::close()\r
111 {\r
112     if (closed)\r
113         return;\r
114     source.close();\r
115     closed = true;\r
116 }\r
117 \r
118 /**\r
119  * Reads the next byte of data from the input stream.  -1 if EOF\r
120  */\r
121 int Base64InputStream::get()\r
122 {\r
123     if (closed)\r
124         return -1;\r
125 \r
126     if (outCount - padCount > 0)\r
127         {\r
128         return outBytes[3-(outCount--)];\r
129         }\r
130 \r
131     if (done)\r
132         return -1;\r
133 \r
134     int inBytes[4];\r
135     int inCount = 0;\r
136     while (inCount < 4)\r
137         {\r
138         int ch = source.get();\r
139         if (ch < 0)\r
140             {\r
141             while (inCount < 4)  //pad if needed\r
142                 {\r
143                 inBytes[inCount++] = 0;\r
144                 padCount++;\r
145                 }\r
146             done = true;\r
147             break;\r
148             }\r
149         if (isspace(ch)) //ascii whitespace\r
150             {\r
151             //nothing\r
152             }\r
153         else if (ch == '=') //padding\r
154             {\r
155             inBytes[inCount++] = 0;\r
156             padCount++;\r
157             }\r
158         else\r
159             {\r
160             int byteVal = base64decode[ch & 0x7f];\r
161             //printf("char:%c %d\n", ch, byteVal);\r
162             if (byteVal < 0)\r
163                 {\r
164                 //Bad lookup value\r
165                 }\r
166             inBytes[inCount++] = byteVal;\r
167             }\r
168         }\r
169 \r
170     outBytes[0] = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);\r
171     outBytes[1] = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);\r
172     outBytes[2] = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3]   ) & 0x3f);\r
173 \r
174     outCount = 3;\r
175 \r
176     //try again\r
177     if (outCount - padCount > 0)\r
178         {\r
179         return outBytes[3-(outCount--)];\r
180         }\r
181 \r
182     return -1;\r
183 \r
184 }\r
185 \r
186 \r
187 //#########################################################################\r
188 //# B A S E 6 4    O U T P U T    S T R E A M\r
189 //#########################################################################\r
190 \r
191 static char *base64encode =\r
192     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
193 \r
194 /**\r
195  *\r
196  */\r
197 Base64OutputStream::Base64OutputStream(OutputStream &destinationStream)\r
198                      : BasicOutputStream(destinationStream)\r
199 {\r
200     column      = 0;\r
201     columnWidth = 72;\r
202     outBuf      = 0L;\r
203     bitCount    = 0;\r
204 }\r
205 \r
206 /**\r
207  *\r
208  */\r
209 Base64OutputStream::~Base64OutputStream()\r
210 {\r
211     close();\r
212 }\r
213 \r
214 /**\r
215  * Closes this output stream and releases any system resources\r
216  * associated with this stream.\r
217  */\r
218 void Base64OutputStream::close()\r
219 {\r
220     if (closed)\r
221         return;\r
222 \r
223     //get any last bytes (1 or 2) out of the buffer\r
224     if (bitCount == 16)\r
225         {\r
226         outBuf <<= 2;  //pad to make 18 bits\r
227 \r
228         int indx  = (int)((outBuf & 0x0003f000L) >> 12);\r
229         int obyte = (int)base64encode[indx & 63];\r
230         putCh(obyte);\r
231 \r
232         indx      = (int)((outBuf & 0x00000fc0L) >>  6);\r
233         obyte     = (int)base64encode[indx & 63];\r
234         putCh(obyte);\r
235 \r
236         indx      = (int)((outBuf & 0x0000003fL)      );\r
237         obyte     = (int)base64encode[indx & 63];\r
238         putCh(obyte);\r
239 \r
240         putCh('=');\r
241         }\r
242     else if (bitCount == 8)\r
243         {\r
244         outBuf <<= 4; //pad to make 12 bits\r
245 \r
246         int indx  = (int)((outBuf & 0x00000fc0L) >>  6);\r
247         int obyte = (int)base64encode[indx & 63];\r
248         putCh(obyte);\r
249 \r
250         indx      = (int)((outBuf & 0x0000003fL)      );\r
251         obyte     = (int)base64encode[indx & 63];\r
252         putCh(obyte);\r
253 \r
254         putCh('=');\r
255         putCh('=');\r
256         }\r
257 \r
258     if (columnWidth > 0) //if <=0, no newlines\r
259         destination.put('\n');\r
260 \r
261     destination.close();\r
262     closed = true;\r
263 }\r
264 \r
265 /**\r
266  *  Flushes this output stream and forces any buffered output\r
267  *  bytes to be written out.\r
268  */\r
269 void Base64OutputStream::flush()\r
270 {\r
271     if (closed)\r
272         return;\r
273     //dont flush here.  do it on close()\r
274     destination.flush();\r
275 }\r
276 \r
277 /**\r
278  * Private. Put a char to the output stream, checking for line length\r
279  */\r
280 void Base64OutputStream::putCh(int ch)\r
281 {\r
282     destination.put(ch);\r
283     column++;\r
284     if (columnWidth > 0 && column >= columnWidth)\r
285         {\r
286         destination.put('\n');\r
287         column = 0;\r
288         }\r
289 }\r
290 \r
291 \r
292 /**\r
293  * Writes the specified byte to this output stream.\r
294  */\r
295 void Base64OutputStream::put(int ch)\r
296 {\r
297     if (closed)\r
298         {\r
299         //probably throw an exception here\r
300         return;\r
301         }\r
302 \r
303     outBuf   <<=  8;\r
304     outBuf   |=  (ch & 0xff);\r
305     bitCount +=  8;\r
306     if (bitCount >= 24)\r
307         {\r
308         int indx  = (int)((outBuf & 0x00fc0000L) >> 18);\r
309         int obyte = (int)base64encode[indx & 63];\r
310         putCh(obyte);\r
311 \r
312         indx      = (int)((outBuf & 0x0003f000L) >> 12);\r
313         obyte     = (int)base64encode[indx & 63];\r
314         putCh(obyte);\r
315 \r
316         indx      = (int)((outBuf & 0x00000fc0L) >>  6);\r
317         obyte     = (int)base64encode[indx & 63];\r
318         putCh(obyte);\r
319 \r
320         indx      = (int)((outBuf & 0x0000003fL)      );\r
321         obyte     = (int)base64encode[indx & 63];\r
322         putCh(obyte);\r
323 \r
324         bitCount = 0;\r
325         outBuf   = 0L;\r
326         }\r
327 }\r
328 \r
329 \r
330 \r
331 }  //namespace io\r
332 }  //namespace dom\r
333 }  //namespace w3c\r
334 }  //namespace org\r
335 \r
336 \r
337 //#########################################################################\r
338 //# E N D    O F    F I L E\r
339 //#########################################################################\r