1
7
8 package java.util.prefs;
9
10
19 class Base64 {
20
24 static String byteArrayToBase64(byte[] a) {
25 return byteArrayToBase64(a, false);
26 }
27
28
34 static String byteArrayToAltBase64(byte[] a) {
35 return byteArrayToBase64(a, true);
36 }
37
38 private static String byteArrayToBase64(byte[] a, boolean alternate) {
39 int aLen = a.length;
40 int numFullGroups = aLen/3;
41 int numBytesInPartialGroup = aLen - 3*numFullGroups;
42 int resultLen = 4*((aLen + 2)/3);
43 StringBuffer result = new StringBuffer(resultLen);
44 char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
45
46 int inCursor = 0;
48 for (int i=0; i<numFullGroups; i++) {
49 int byte0 = a[inCursor++] & 0xff;
50 int byte1 = a[inCursor++] & 0xff;
51 int byte2 = a[inCursor++] & 0xff;
52 result.append(intToAlpha[byte0 >> 2]);
53 result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
54 result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
55 result.append(intToAlpha[byte2 & 0x3f]);
56 }
57
58 if (numBytesInPartialGroup != 0) {
60 int byte0 = a[inCursor++] & 0xff;
61 result.append(intToAlpha[byte0 >> 2]);
62 if (numBytesInPartialGroup == 1) {
63 result.append(intToAlpha[(byte0 << 4) & 0x3f]);
64 result.append("==");
65 } else {
66 int byte1 = a[inCursor++] & 0xff;
68 result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
69 result.append(intToAlpha[(byte1 << 2)&0x3f]);
70 result.append('=');
71 }
72 }
73 return result.toString();
76 }
77
78
83 private static final char intToBase64[] = {
84 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
85 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
86 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
87 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
88 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
89 };
90
91
98 private static final char intToAltBase64[] = {
99 '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
100 ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
101 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
102 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
103 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?'
104 };
105
106
113 static byte[] base64ToByteArray(String s) {
114 return base64ToByteArray(s, false);
115 }
116
117
125 static byte[] altBase64ToByteArray(String s) {
126 return base64ToByteArray(s, true);
127 }
128
129 private static byte[] base64ToByteArray(String s, boolean alternate) {
130 byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);
131 int sLen = s.length();
132 int numGroups = sLen/4;
133 if (4*numGroups != sLen)
134 throw new IllegalArgumentException(
135 "String length must be a multiple of four.");
136 int missingBytesInLastGroup = 0;
137 int numFullGroups = numGroups;
138 if (sLen != 0) {
139 if (s.charAt(sLen-1) == '=') {
140 missingBytesInLastGroup++;
141 numFullGroups--;
142 }
143 if (s.charAt(sLen-2) == '=')
144 missingBytesInLastGroup++;
145 }
146 byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
147
148 int inCursor = 0, outCursor = 0;
150 for (int i=0; i<numFullGroups; i++) {
151 int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
152 int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
153 int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
154 int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
155 result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
156 result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
157 result[outCursor++] = (byte) ((ch2 << 6) | ch3);
158 }
159
160 if (missingBytesInLastGroup != 0) {
162 int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
163 int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
164 result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
165
166 if (missingBytesInLastGroup == 1) {
167 int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
168 result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
169 }
170 }
171 return result;
174 }
175
176
183 private static int base64toInt(char c, byte[] alphaToInt) {
184 int result = alphaToInt[c];
185 if (result < 0)
186 throw new IllegalArgumentException("Illegal character " + c);
187 return result;
188 }
189
190
197 private static final byte base64ToInt[] = {
198 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
199 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
200 -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
201 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
202 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
203 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
204 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
205 };
206
207
211 private static final byte altBase64ToInt[] = {
212 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
213 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
214 2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
215 58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
216 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
217 -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
218 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
219 51, 22, 23, 24, 25
220 };
221
222 public static void main(String args[]) {
223 int numRuns = Integer.parseInt(args[0]);
224 int numBytes = Integer.parseInt(args[1]);
225 java.util.Random rnd = new java.util.Random();
226 for (int i=0; i<numRuns; i++) {
227 for (int j=0; j<numBytes; j++) {
228 byte[] arr = new byte[j];
229 for (int k=0; k<j; k++)
230 arr[k] = (byte)rnd.nextInt();
231
232 String s = byteArrayToBase64(arr);
233 byte [] b = base64ToByteArray(s);
234 if (!java.util.Arrays.equals(arr, b))
235 System.out.println("Dismal failure!");
236
237 s = byteArrayToAltBase64(arr);
238 b = altBase64ToByteArray(s);
239 if (!java.util.Arrays.equals(arr, b))
240 System.out.println("Alternate dismal failure!");
241 }
242 }
243 }
244 }
245