licensing update to APSL 2.0
[org.ibex.util.git] / src / org / ibex / util / Base64.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.util;
6
7 public class Base64 {
8
9     private static final byte[] encodingTable = {
10         (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
11         (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
12         (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
13         (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
14         (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
15         (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
16         (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
17         (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1',
18         (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8',
19         (byte)'9', (byte)'+', (byte)'/'
20     };
21
22     // FIXME could be far more efficient
23     public static class InputStream extends java.io.ByteArrayInputStream {
24         public InputStream(String s) { super(decode(s.getBytes())); }
25     }
26
27     /**
28      * encode the input data producong a base 64 encoded byte array.
29      *
30      * @return a byte array containing the base 64 encoded data.
31      */
32     public static byte[] encode(byte[]  data) {
33         byte[]  bytes;
34                 
35         int modulus = data.length % 3;
36         if (modulus == 0) {
37             bytes = new byte[4 * data.length / 3];
38         } else {
39             bytes = new byte[4 * ((data.length / 3) + 1)];
40         }
41
42         int dataLength = (data.length - modulus);
43         int a1, a2, a3;
44         for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {
45             a1 = data[i] & 0xff;
46             a2 = data[i + 1] & 0xff;
47             a3 = data[i + 2] & 0xff;
48             
49             bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
50             bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
51             bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
52             bytes[j + 3] = encodingTable[a3 & 0x3f];
53         }
54
55         int     b1, b2, b3;
56         int     d1, d2;
57
58         switch (modulus) {
59                 case 0:         /* nothing left to do */
60                     break;
61                 case 1:
62                     d1 = data[data.length - 1] & 0xff;
63                     b1 = (d1 >>> 2) & 0x3f;
64                     b2 = (d1 << 4) & 0x3f;
65
66                     bytes[bytes.length - 4] = encodingTable[b1];
67                     bytes[bytes.length - 3] = encodingTable[b2];
68                     bytes[bytes.length - 2] = (byte)'=';
69                     bytes[bytes.length - 1] = (byte)'=';
70                     break;
71                 case 2:
72                     d1 = data[data.length - 2] & 0xff;
73                     d2 = data[data.length - 1] & 0xff;
74
75                     b1 = (d1 >>> 2) & 0x3f;
76                     b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
77                     b3 = (d2 << 2) & 0x3f;
78
79                     bytes[bytes.length - 4] = encodingTable[b1];
80                     bytes[bytes.length - 3] = encodingTable[b2];
81                     bytes[bytes.length - 2] = encodingTable[b3];
82                     bytes[bytes.length - 1] = (byte)'=';
83                     break;
84             }
85
86         return bytes;
87     }
88
89     private static final byte[] decodingTable;
90
91     static {
92         decodingTable = new byte[128];
93         for (int i = 'A'; i <= 'Z'; i++) decodingTable[i] = (byte)(i - 'A');
94         for (int i = 'a'; i <= 'z'; i++) decodingTable[i] = (byte)(i - 'a' + 26);
95         for (int i = '0'; i <= '9'; i++) decodingTable[i] = (byte)(i - '0' + 52);
96         decodingTable['+'] = 62;
97         decodingTable['/'] = 63;
98     }
99
100     /**
101      * decode the base 64 encoded input data.
102      *
103      * @return a byte array representing the decoded data.
104      */
105     public static byte[] decode(byte[]  data) {
106         byte[]  bytes;
107         byte    b1, b2, b3, b4;
108
109         if (data[data.length - 2] == '=') bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
110         else if (data[data.length - 1] == '=') bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
111         else bytes = new byte[((data.length / 4) * 3)];
112
113         for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) {
114             b1 = decodingTable[data[i]];
115             b2 = decodingTable[data[i + 1]];
116             b3 = decodingTable[data[i + 2]];
117             b4 = decodingTable[data[i + 3]];
118             
119             bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
120             bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
121             bytes[j + 2] = (byte)((b3 << 6) | b4);
122         }
123
124         if (data[data.length - 2] == '=') {
125             b1 = decodingTable[data[data.length - 4]];
126             b2 = decodingTable[data[data.length - 3]];
127             bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
128         } else if (data[data.length - 1] == '=') {
129             b1 = decodingTable[data[data.length - 4]];
130             b2 = decodingTable[data[data.length - 3]];
131             b3 = decodingTable[data[data.length - 2]];
132             bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
133             bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
134         } else {
135             b1 = decodingTable[data[data.length - 4]];
136             b2 = decodingTable[data[data.length - 3]];
137             b3 = decodingTable[data[data.length - 2]];
138             b4 = decodingTable[data[data.length - 1]];
139             bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
140             bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
141             bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
142         }
143         return bytes;
144     }
145
146     /**
147      * decode the base 64 encoded String data.
148      *
149      * @return a byte array representing the decoded data.
150      */
151     public static byte[] decode(String  data) {
152         byte[]  bytes;
153         byte    b1, b2, b3, b4;
154
155         if (data.charAt(data.length() - 2) == '=')
156             bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
157         else if (data.charAt(data.length() - 1) == '=')
158             bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
159         else
160             bytes = new byte[((data.length() / 4) * 3)];
161
162         for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) {
163             b1 = decodingTable[data.charAt(i)];
164             b2 = decodingTable[data.charAt(i + 1)];
165             b3 = decodingTable[data.charAt(i + 2)];
166             b4 = decodingTable[data.charAt(i + 3)];
167             
168             bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
169             bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
170             bytes[j + 2] = (byte)((b3 << 6) | b4);
171         }
172
173         if (data.charAt(data.length() - 2) == '=') {
174             b1 = decodingTable[data.charAt(data.length() - 4)];
175             b2 = decodingTable[data.charAt(data.length() - 3)];
176             bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
177         } else if (data.charAt(data.length() - 1) == '=') {
178             b1 = decodingTable[data.charAt(data.length() - 4)];
179             b2 = decodingTable[data.charAt(data.length() - 3)];
180             b3 = decodingTable[data.charAt(data.length() - 2)];
181             bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
182             bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
183         } else {
184             b1 = decodingTable[data.charAt(data.length() - 4)];
185             b2 = decodingTable[data.charAt(data.length() - 3)];
186             b3 = decodingTable[data.charAt(data.length() - 2)];
187             b4 = decodingTable[data.charAt(data.length() - 1)];
188             bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
189             bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
190             bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
191         }
192         return bytes;
193     }
194 }