Package: Base64

Base64

nameinstructionbranchcomplexitylinemethod
Base64()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
decode(byte[])
M: 189 C: 0
0%
M: 19 C: 0
0%
M: 11 C: 0
0%
M: 39 C: 0
0%
M: 1 C: 0
0%
decodeDigit(byte)
M: 54 C: 0
0%
M: 15 C: 0
0%
M: 9 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
decodeInlplace(byte[], int)
M: 182 C: 0
0%
M: 19 C: 0
0%
M: 11 C: 0
0%
M: 38 C: 0
0%
M: 1 C: 0
0%
encode(byte[])
M: 183 C: 0
0%
M: 13 C: 0
0%
M: 8 C: 0
0%
M: 33 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 260 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * #%~
3: * org.overture.ide.debug
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.ide.debug.core.dbgp.internal.utils;
23:
24: /**
25: * Base64 is a helper class for converting byte arrays to and from base 64 encoded Strings.
26: */
27: class Base64
28: {
29:
30:         private static final byte equalSign = (byte) '=';
31:
32:         static char digits[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
33:                         'K', 'L', 'M',
34:                         'N',
35:                         'O',
36:                         'P', //
37:                         'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
38:                         'd',
39:                         'e',
40:                         'f', //
41:                         'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
42:                         't', 'u',
43:                         'v', //
44:                         'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
45:                         '9', '+', '/' };
46:
47:         /**
48:          * This method decodes the byte array in base 64 encoding into a char array Base 64 encoding has to be according to
49:          * the specification given by the RFC 1521 (5.2).
50:          *
51:          * @param data
52:          * the encoded byte array
53:          * @return the decoded byte array
54:          */
55:         public static byte[] decode(byte[] data)
56:         {
57:•                if (data.length == 0)
58:                 {
59:                         return data;
60:                 }
61:                 int lastRealDataIndex = data.length - 1;
62:•                while (data[lastRealDataIndex] == equalSign)
63:                 {
64:                         lastRealDataIndex--;
65:                 }
66:                 // original data digit is 8 bits long, but base64 digit is 6 bits long
67:                 int padBytes = data.length - 1 - lastRealDataIndex;
68:                 int byteLength = data.length * 6 / 8 - padBytes;
69:                 byte[] result = new byte[byteLength];
70:                 // Each 4 bytes of input (encoded) we end up with 3 bytes of output
71:                 int dataIndex = 0;
72:                 int resultIndex = 0;
73:                 int allBits = 0;
74:                 // how many result chunks we can process before getting to pad bytes
75:                 int resultChunks = (lastRealDataIndex + 1) / 4;
76:•                for (int i = 0; i < resultChunks; i++)
77:                 {
78:                         allBits = 0;
79:                         // Loop 4 times gathering input bits (4 * 6 = 24)
80:•                        for (int j = 0; j < 4; j++)
81:                         {
82:                                 allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
83:                         }
84:                         // Loop 3 times generating output bits (3 * 8 = 24)
85:•                        for (int j = resultIndex + 2; j >= resultIndex; j--)
86:                         {
87:                                 result[j] = (byte) (allBits & 0xff); // Bottom 8 bits
88:                                 allBits = allBits >>> 8;
89:                         }
90:                         resultIndex += 3; // processed 3 result bytes
91:                 }
92:                 // Now we do the extra bytes in case the original (non-encoded) data
93:                 // was not multiple of 3 bytes
94:•                switch (padBytes)
95:                 {
96:                         case 1:
97:                                 // 1 pad byte means 3 (4-1) extra Base64 bytes of input, 18
98:                                 // bits, of which only 16 are meaningful
99:                                 // Or: 2 bytes of result data
100:                                 allBits = 0;
101:                                 // Loop 3 times gathering input bits
102:•                                for (int j = 0; j < 3; j++)
103:                                 {
104:                                         allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
105:                                 }
106:                                 // NOTE - The code below ends up being equivalent to allBits =
107:                                 // allBits>>>2
108:                                 // But we code it in a non-optimized way for clarity
109:                                 // The 4th, missing 6 bits are all 0
110:                                 allBits = allBits << 6;
111:                                 // The 3rd, missing 8 bits are all 0
112:                                 allBits = allBits >>> 8;
113:                                 // Loop 2 times generating output bits
114:•                                for (int j = resultIndex + 1; j >= resultIndex; j--)
115:                                 {
116:                                         result[j] = (byte) (allBits & 0xff); // Bottom 8
117:                                         // bits
118:                                         allBits = allBits >>> 8;
119:                                 }
120:                                 break;
121:                         case 2:
122:                                 // 2 pad bytes mean 2 (4-2) extra Base64 bytes of input, 12 bits
123:                                 // of data, of which only 8 are meaningful
124:                                 // Or: 1 byte of result data
125:                                 allBits = 0;
126:                                 // Loop 2 times gathering input bits
127:•                                for (int j = 0; j < 2; j++)
128:                                 {
129:                                         allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
130:                                 }
131:                                 // NOTE - The code below ends up being equivalent to allBits =
132:                                 // allBits>>>4
133:                                 // But we code it in a non-optimized way for clarity
134:                                 // The 3rd and 4th, missing 6 bits are all 0
135:                                 allBits = allBits << 6;
136:                                 allBits = allBits << 6;
137:                                 // The 3rd and 4th, missing 8 bits are all 0
138:                                 allBits = allBits >>> 8;
139:                                 allBits = allBits >>> 8;
140:                                 result[resultIndex] = (byte) (allBits & 0xff); // Bottom
141:                                 // 8
142:                                 // bits
143:                                 break;
144:                 }
145:                 return result;
146:         }
147:
148:         /**
149:          * This method decodes the byte array in base 64 encoding into a char array Base 64 encoding has to be according to
150:          * the specification given by the RFC 1521 (5.2).
151:          *
152:          * @param data
153:          * the encoded byte array
154:          * @param length
155:          * the length of the data
156:          * @return the number of the result bytes
157:          */
158:         public static int decodeInlplace(byte[] data, final int length)
159:         {
160:•                if (length == 0)
161:                 {
162:                         return 0;
163:                 }
164:                 int lastRealDataIndex = length - 1;
165:•                while (data[lastRealDataIndex] == equalSign)
166:                 {
167:                         lastRealDataIndex--;
168:                 }
169:                 // original data digit is 8 bits long, but base64 digit is 6 bits long
170:                 final int padBytes = length - 1 - lastRealDataIndex;
171:                 final int byteLength = length * 6 / 8 - padBytes;
172:                 // Each 4 bytes of input (encoded) we end up with 3 bytes of output
173:                 int dataIndex = 0;
174:                 int resultIndex = 0;
175:                 int allBits = 0;
176:                 // how many result chunks we can process before getting to pad bytes
177:                 int resultChunks = (lastRealDataIndex + 1) / 4;
178:•                for (int i = 0; i < resultChunks; i++)
179:                 {
180:                         allBits = 0;
181:                         // Loop 4 times gathering input bits (4 * 6 = 24)
182:•                        for (int j = 0; j < 4; j++)
183:                         {
184:                                 allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
185:                         }
186:                         // Loop 3 times generating output bits (3 * 8 = 24)
187:•                        for (int j = resultIndex + 2; j >= resultIndex; j--)
188:                         {
189:                                 data[j] = (byte) (allBits & 0xff); // Bottom 8 bits
190:                                 allBits = allBits >>> 8;
191:                         }
192:                         resultIndex += 3; // processed 3 result bytes
193:                 }
194:                 // Now we do the extra bytes in case the original (non-encoded) data
195:                 // was not multiple of 3 bytes
196:•                switch (padBytes)
197:                 {
198:                         case 1:
199:                                 // 1 pad byte means 3 (4-1) extra Base64 bytes of input, 18
200:                                 // bits, of which only 16 are meaningful
201:                                 // Or: 2 bytes of result data
202:                                 allBits = 0;
203:                                 // Loop 3 times gathering input bits
204:•                                for (int j = 0; j < 3; j++)
205:                                 {
206:                                         allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
207:                                 }
208:                                 // NOTE - The code below ends up being equivalent to allBits =
209:                                 // allBits>>>2
210:                                 // But we code it in a non-optimized way for clarity
211:                                 // The 4th, missing 6 bits are all 0
212:                                 allBits = allBits << 6;
213:                                 // The 3rd, missing 8 bits are all 0
214:                                 allBits = allBits >>> 8;
215:                                 // Loop 2 times generating output bits
216:•                                for (int j = resultIndex + 1; j >= resultIndex; j--)
217:                                 {
218:                                         data[j] = (byte) (allBits & 0xff); // Bottom 8
219:                                         // bits
220:                                         allBits = allBits >>> 8;
221:                                 }
222:                                 break;
223:                         case 2:
224:                                 // 2 pad bytes mean 2 (4-2) extra Base64 bytes of input, 12 bits
225:                                 // of data, of which only 8 are meaningful
226:                                 // Or: 1 byte of result data
227:                                 allBits = 0;
228:                                 // Loop 2 times gathering input bits
229:•                                for (int j = 0; j < 2; j++)
230:                                 {
231:                                         allBits = allBits << 6 | decodeDigit(data[dataIndex++]);
232:                                 }
233:                                 // NOTE - The code below ends up being equivalent to allBits =
234:                                 // allBits>>>4
235:                                 // But we code it in a non-optimized way for clarity
236:                                 // The 3rd and 4th, missing 6 bits are all 0
237:                                 allBits = allBits << 6;
238:                                 allBits = allBits << 6;
239:                                 // The 3rd and 4th, missing 8 bits are all 0
240:                                 allBits = allBits >>> 8;
241:                                 allBits = allBits >>> 8;
242:                                 data[resultIndex] = (byte) (allBits & 0xff); // Bottom
243:                                 // 8
244:                                 // bits
245:                                 break;
246:                 }
247:                 return byteLength;
248:         }
249:
250:         /**
251:          * This method converts a Base 64 digit to its numeric value.
252:          *
253:          * @param data
254:          * digit (character) to convert
255:          * @return value for the digit
256:          */
257:         static int decodeDigit(byte data)
258:         {
259:                 char charData = (char) data;
260:•                if (charData <= 'Z' && charData >= 'A')
261:                 {
262:                         return charData - 'A';
263:                 }
264:•                if (charData <= 'z' && charData >= 'a')
265:                 {
266:                         return charData - 'a' + 26;
267:                 }
268:•                if (charData <= '9' && charData >= '0')
269:                 {
270:                         return charData - '0' + 52;
271:                 }
272:•                switch (charData)
273:                 {
274:                         case '+':
275:                                 return 62;
276:                         case '/':
277:                                 return 63;
278:                         default:
279:                                 throw new IllegalArgumentException("Invalid char to decode: " + data); //$NON-NLS-1$
280:                 }
281:         }
282:
283:         /**
284:          * This method encodes the byte array into a char array in base 64 according to the specification given by the RFC
285:          * 1521 (5.2).
286:          *
287:          * @param data
288:          * the encoded char array
289:          * @return the byte array that needs to be encoded
290:          */
291:         public static byte[] encode(byte[] data)
292:         {
293:                 int sourceChunks = data.length / 3;
294:                 int len = (data.length + 2) / 3 * 4;
295:                 byte[] result = new byte[len];
296:                 int extraBytes = data.length - sourceChunks * 3;
297:                 // Each 4 bytes of input (encoded) we end up with 3 bytes of output
298:                 int dataIndex = 0;
299:                 int resultIndex = 0;
300:                 int allBits = 0;
301:•                for (int i = 0; i < sourceChunks; i++)
302:                 {
303:                         allBits = 0;
304:                         // Loop 3 times gathering input bits (3 * 8 = 24)
305:•                        for (int j = 0; j < 3; j++)
306:                         {
307:                                 allBits = allBits << 8 | data[dataIndex++] & 0xff;
308:                         }
309:                         // Loop 4 times generating output bits (4 * 6 = 24)
310:•                        for (int j = resultIndex + 3; j >= resultIndex; j--)
311:                         {
312:                                 result[j] = (byte) digits[allBits & 0x3f]; // Bottom
313:                                 // 6
314:                                 // bits
315:                                 allBits = allBits >>> 6;
316:                         }
317:                         resultIndex += 4; // processed 4 result bytes
318:                 }
319:                 // Now we do the extra bytes in case the original (non-encoded) data
320:                 // is not multiple of 4 bytes
321:•                switch (extraBytes)
322:                 {
323:                         case 1:
324:                                 allBits = data[dataIndex++]; // actual byte
325:                                 allBits = allBits << 8; // 8 bits of zeroes
326:                                 allBits = allBits << 8; // 8 bits of zeroes
327:                                 // Loop 4 times generating output bits (4 * 6 = 24)
328:•                                for (int j = resultIndex + 3; j >= resultIndex; j--)
329:                                 {
330:                                         result[j] = (byte) digits[allBits & 0x3f]; // Bottom
331:                                         // 6
332:                                         // bits
333:                                         allBits = allBits >>> 6;
334:                                 }
335:                                 // 2 pad tags
336:                                 result[result.length - 1] = equalSign;
337:                                 result[result.length - 2] = equalSign;
338:                                 break;
339:                         case 2:
340:                                 allBits = data[dataIndex++]; // actual byte
341:                                 allBits = allBits << 8 | data[dataIndex++] & 0xff; // actual
342:                                 // byte
343:                                 allBits = allBits << 8; // 8 bits of zeroes
344:                                 // Loop 4 times generating output bits (4 * 6 = 24)
345:•                                for (int j = resultIndex + 3; j >= resultIndex; j--)
346:                                 {
347:                                         result[j] = (byte) digits[allBits & 0x3f]; // Bottom
348:                                         // 6
349:                                         // bits
350:                                         allBits = allBits >>> 6;
351:                                 }
352:                                 // 1 pad tag
353:                                 result[result.length - 1] = equalSign;
354:                                 break;
355:                 }
356:                 return result;
357:         }
358: }