Code

Extensions. Add option to choose dxf output units
[inkscape.git] / src / io / base64stream.cpp
1 /**
2  * Base64-enabled input and output streams
3  *
4  * This class allows easy encoding and decoding
5  * of Base64 data with a stream interface, hiding
6  * the implementation from the user.
7  *
8  * Authors:
9  *   Bob Jamison <rjamison@titan.com>
10  *
11  * Copyright (C) 2004 Inkscape.org
12  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #include "base64stream.h"
20 namespace Inkscape
21 {
22 namespace IO
23 {
25 //#########################################################################
26 //# B A S E 6 4    I N P U T    S T R E A M
27 //#########################################################################
29 static int base64decode[] =
30 {
31 /*00*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
32 /*08*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
33 /*10*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
34 /*18*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
35 /*20*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
36 /*28*/    -1,   -1,   -1,   62,   -1,   -1,   -1,   63,
37 /*30*/    52,   53,   54,   55,   56,   57,   58,   59,
38 /*38*/    60,   61,   -1,   -1,   -1,   -1,   -1,   -1,
39 /*40*/    -1,    0,    1,    2,    3,    4,    5,    6,
40 /*48*/     7,    8,    9,   10,   11,   12,   13,   14,
41 /*50*/    15,   16,   17,   18,   19,   20,   21,   22,
42 /*58*/    23,   24,   25,   -1,   -1,   -1,   -1,   -1,
43 /*60*/    -1,   26,   27,   28,   29,   30,   31,   32,
44 /*68*/    33,   34,   35,   36,   37,   38,   39,   40,
45 /*70*/    41,   42,   43,   44,   45,   46,   47,   48,
46 /*78*/    49,   50,   51,   -1,   -1,   -1,   -1,   -1
47 };
50 /**
51  *
52  */ 
53 Base64InputStream::Base64InputStream(InputStream &sourceStream)
54                     : BasicInputStream(sourceStream)
55 {
56     outCount = 0;
57     padCount = 0;
58     closed   = false;
59     done     = false;
60 }
62 /**
63  *
64  */ 
65 Base64InputStream::~Base64InputStream()
66 {
67     close();
68 }
70 /**
71  * Returns the number of bytes that can be read (or skipped over) from
72  * this input stream without blocking by the next caller of a method for
73  * this input stream.
74  */ 
75 int Base64InputStream::available()
76 {
77     if (closed )
78         return 0;
79     int len = source.available() * 2 / 3;
80     return len;
81 }
83     
84 /**
85  *  Closes this input stream and releases any system resources
86  *  associated with the stream.
87  */ 
88 void Base64InputStream::close()
89 {
90     if (closed)
91         return;
92     source.close();
93     closed = true;
94 }
95     
96 /**
97  * Reads the next byte of data from the input stream.  -1 if EOF
98  */ 
99 int Base64InputStream::get()
101     if (closed)
102         return -1;
104     if (outCount - padCount > 0)
105         {
106         return outBytes[3-(outCount--)];
107         }
109     if (done)
110         return -1;
112     int inBytes[4];
113     int inCount = 0;
114     while (inCount < 4)
115         {
116         int ch = source.get();
117         if (ch < 0)
118             {
119             while (inCount < 4)  //pad if needed
120                 {
121                 inBytes[inCount++] = 0;
122                 padCount++;
123                 }
124             done = true;
125             break;
126             }
127         if (isspace(ch)) //ascii whitespace
128             {
129             //nothing
130             }
131         else if (ch == '=') //padding
132             {
133             inBytes[inCount++] = 0;
134             padCount++;
135             }
136         else
137             {
138             int byteVal = base64decode[ch & 0x7f];
139             //printf("char:%c %d\n", ch, byteVal);
140             if (byteVal < 0)
141                 {
142                 //Bad lookup value
143                 }
144             inBytes[inCount++] = byteVal;
145             }
146         }
148     outBytes[0] = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
149     outBytes[1] = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
150     outBytes[2] = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3]   ) & 0x3f);
151     
152     outCount = 3;
154     //try again
155     if (outCount - padCount > 0)
156         {
157         return outBytes[3-(outCount--)];
158         }
159     
160     return -1;
165 //#########################################################################
166 //# B A S E 6 4    O U T P U T    S T R E A M
167 //#########################################################################
169 static char const *base64encode =
170     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
172 /**
173  *
174  */ 
175 Base64OutputStream::Base64OutputStream(OutputStream &destinationStream)
176                      : BasicOutputStream(destinationStream)
178     column      = 0;
179     columnWidth = 72;
180     outBuf      = 0L;
181     bitCount    = 0;
184 /**
185  *
186  */ 
187 Base64OutputStream::~Base64OutputStream()
189     close();
192 /**
193  * Closes this output stream and releases any system resources
194  * associated with this stream.
195  */ 
196 void Base64OutputStream::close()
198     if (closed)
199         return;
201     //get any last bytes (1 or 2) out of the buffer
202     if (bitCount == 16)
203         {
204         outBuf <<= 2;  //pad to make 18 bits
206         int indx  = (int)((outBuf & 0x0003f000L) >> 12);
207         int obyte = (int)base64encode[indx & 63];
208         putCh(obyte);
210         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
211         obyte     = (int)base64encode[indx & 63];
212         putCh(obyte);
214         indx      = (int)((outBuf & 0x0000003fL)      );
215         obyte     = (int)base64encode[indx & 63];
216         putCh(obyte);
218         putCh('=');
219         }
220     else if (bitCount == 8)
221         {
222         outBuf <<= 4; //pad to make 12 bits
224         int indx  = (int)((outBuf & 0x00000fc0L) >>  6);
225         int obyte = (int)base64encode[indx & 63];
226         putCh(obyte);
228         indx      = (int)((outBuf & 0x0000003fL)      );
229         obyte     = (int)base64encode[indx & 63];
230         putCh(obyte);
232         putCh('=');
233         putCh('=');
234         }
236     if (columnWidth > 0) //if <=0, no newlines
237         destination.put('\n');
239     destination.close();
240     closed = true;
242     
243 /**
244  *  Flushes this output stream and forces any buffered output
245  *  bytes to be written out.
246  */ 
247 void Base64OutputStream::flush()
249     if (closed)
250         return;
251     //dont flush here.  do it on close()    
252     destination.flush();
255 /**
256  * Private. Put a char to the output stream, checking for line length
257  */ 
258 void Base64OutputStream::putCh(int ch)
260     destination.put(ch);
261     column++;
262     if (columnWidth > 0 && column >= columnWidth)
263         {
264         destination.put('\n');
265         column = 0;
266         }
270 /**
271  * Writes the specified byte to this output stream.
272  */ 
273 void Base64OutputStream::put(int ch)
275     if (closed)
276         {
277         //probably throw an exception here
278         return;
279         }
281     outBuf   <<=  8;
282     outBuf   |=  (ch & 0xff);
283     bitCount +=  8;
284     if (bitCount >= 24)
285         {
286         int indx  = (int)((outBuf & 0x00fc0000L) >> 18);
287         int obyte = (int)base64encode[indx & 63];
288         putCh(obyte);
290         indx      = (int)((outBuf & 0x0003f000L) >> 12);
291         obyte     = (int)base64encode[indx & 63];
292         putCh(obyte);
294         indx      = (int)((outBuf & 0x00000fc0L) >>  6);
295         obyte     = (int)base64encode[indx & 63];
296         putCh(obyte);
298         indx      = (int)((outBuf & 0x0000003fL)      );
299         obyte     = (int)base64encode[indx & 63];
300         putCh(obyte);
302         bitCount = 0;
303         outBuf   = 0L;
304         }
309 } // namespace IO
310 } // namespace Inkscape
313 //#########################################################################
314 //# E N D    O F    F I L E
315 //#########################################################################