001package org.granite.util; 002 003import java.util.Arrays; 004 005/** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance 006 * with RFC 2045.<br><br> 007 * On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster 008 * on small arrays (10 - 1000 bytes) and 2-3 times as fast on larger arrays (10000 - 1000000 bytes) 009 * compared to <code>sun.misc.Encoder()/Decoder()</code>.<br><br> 010 * 011 * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and 012 * about 50% faster for decoding large arrays. This implementation is about twice as fast on very small 013 * arrays (< 30 bytes). If source/destination is a <code>String</code> this 014 * version is about three times as fast due to the fact that the Commons Codec result has to be recoded 015 * to a <code>String</code> from <code>byte[]</code>, which is very expensive.<br><br> 016 * 017 * This encode/decode algorithm doesn't create any temporary arrays as many other codecs do, it only 018 * allocates the resulting array. This produces less garbage and it is possible to handle arrays twice 019 * as large as algorithms that create a temporary array. (E.g. Jakarta Commons Codec). It is unknown 020 * whether Sun's <code>sun.misc.Encoder()/Decoder()</code> produce temporary arrays but since performance 021 * is quite low it probably does.<br><br> 022 * 023 * The encoder produces the same output as the Sun one except that the Sun's encoder appends 024 * a trailing line separator if the last character isn't a pad. Unclear why but it only adds to the 025 * length and is probably a side effect. Both are in conformance with RFC 2045 though.<br> 026 * Commons codec seem to always att a trailing line separator.<br><br> 027 * 028 * <b>Note!</b> 029 * The encode/decode method pairs (types) come in three versions with the <b>exact</b> same algorithm and 030 * thus a lot of code redundancy. This is to not create any temporary arrays for transcoding to/from different 031 * format types. The methods not used can simply be commented out.<br><br> 032 * 033 * There is also a "fast" version of all decode methods that works the same way as the normal ones, but 034 * har a few demands on the decoded input. Normally though, these fast verions should be used if the source if 035 * the input is known and it hasn't bee tampered with.<br><br> 036 * 037 * If you find the code useful or you find a bug, please send me a note at base64 @ miginfocom . com. 038 * 039 * Licence (BSD): 040 * ============== 041 * 042 * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) 043 * All rights reserved. 044 * 045 * Redistribution and use in source and binary forms, with or without modification, 046 * are permitted provided that the following conditions are met: 047 * Redistributions of source code must retain the above copyright notice, this list 048 * of conditions and the following disclaimer. 049 * Redistributions in binary form must reproduce the above copyright notice, this 050 * list of conditions and the following disclaimer in the documentation and/or other 051 * materials provided with the distribution. 052 * Neither the name of the MiG InfoCom AB nor the names of its contributors may be 053 * used to endorse or promote products derived from this software without specific 054 * prior written permission. 055 * 056 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 057 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 058 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 059 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 060 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 061 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 062 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 063 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 064 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 065 * OF SUCH DAMAGE. 066 * 067 * @version 2.2 068 * @author Mikael Grev 069 * Date: 2004-aug-02 070 * Time: 11:31:11 071 */ 072 073public class Base64 074{ 075 private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); 076 private static final int[] IA = new int[256]; 077 static { 078 Arrays.fill(IA, -1); 079 for (int i = 0, iS = CA.length; i < iS; i++) 080 IA[CA[i]] = i; 081 IA['='] = 0; 082 } 083 084 // **************************************************************************************** 085 // * char[] version 086 // **************************************************************************************** 087 088 /** Encodes a raw byte array into a BASE64 <code>char[]</code> representation i accordance with RFC 2045. 089 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned. 090 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br> 091 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a 092 * little faster. 093 * @return A BASE64 encoded array. Never <code>null</code>. 094 */ 095 public final static char[] encodeToChar(byte[] sArr, boolean lineSep) 096 { 097 // Check special case 098 if (sArr == null || sArr.length == 0) 099 return new char[0]; 100 101 int sLen = sArr.length; 102 int eLen = (sLen / 3) * 3; // Length of even 24-bits. 103 int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count 104 int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array 105 char[] dArr = new char[dLen]; 106 107 // Encode even 24-bits 108 for (int s = 0, d = 0, cc = 0; s < eLen;) { 109 // Copy next three bytes into lower 24 bits of int, paying attension to sign. 110 int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); 111 112 // Encode the int into four chars 113 dArr[d++] = CA[(i >>> 18) & 0x3f]; 114 dArr[d++] = CA[(i >>> 12) & 0x3f]; 115 dArr[d++] = CA[(i >>> 6) & 0x3f]; 116 dArr[d++] = CA[i & 0x3f]; 117 118 // Add optional line separator 119 if (lineSep && ++cc == 19 && d < dLen - 2) { 120 dArr[d++] = '\r'; 121 dArr[d++] = '\n'; 122 cc = 0; 123 } 124 } 125 126 // Pad and encode last bits if source isn't even 24 bits. 127 int left = sLen - eLen; // 0 - 2. 128 if (left > 0) { 129 // Prepare the int 130 int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); 131 132 // Set last four chars 133 dArr[dLen - 4] = CA[i >> 12]; 134 dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; 135 dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '='; 136 dArr[dLen - 1] = '='; 137 } 138 return dArr; 139 } 140 141 /** Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with 142 * and without line separators. 143 * @param sArr The source array. <code>null</code> or length 0 will return an empty array. 144 * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters 145 * (including '=') isn't divideable by 4. (I.e. definitely corrupted). 146 */ 147 public final static byte[] decode(char[] sArr) 148 { 149 // Check special case 150 if (sArr == null || sArr.length == 0) 151 return new byte[0]; 152 153 int sLen = sArr.length; 154 155 // Count illegal characters (including '\r', '\n') to know what size the returned array will be, 156 // so we don't have to reallocate & copy it later. 157 int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) 158 for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. 159 if (IA[sArr[i]] < 0) 160 sepCnt++; 161 162 // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. 163 if ((sLen - sepCnt) % 4 != 0) 164 return null; 165 166 int pad = 0; 167 for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) 168 if (sArr[i] == '=') 169 pad++; 170 171 int len = ((sLen - sepCnt) * 6 >> 3) - pad; 172 173 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 174 175 for (int s = 0, d = 0; d < len;) { 176 // Assemble three bytes into an int from four "valid" characters. 177 int i = 0; 178 for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. 179 int c = IA[sArr[s++]]; 180 if (c >= 0) 181 i |= c << (18 - j * 6); 182 else 183 j--; 184 } 185 // Add the bytes 186 dArr[d++] = (byte) (i >> 16); 187 if (d < len) { 188 dArr[d++]= (byte) (i >> 8); 189 if (d < len) 190 dArr[d++] = (byte) i; 191 } 192 } 193 return dArr; 194 } 195 196 /** Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as 197 * fast as {@link #decode(char[])}. The preconditions are:<br> 198 * + The array must have a line length of 76 chars OR no line separators at all (one line).<br> 199 * + Line separator must be "\r\n", as specified in RFC 2045 200 * + The array must not contain illegal characters within the encoded string<br> 201 * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br> 202 * @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. 203 * @return The decoded array of bytes. May be of length 0. 204 */ 205 public final static byte[] decodeFast(char[] sArr) 206 { 207 // Check special case 208 int sLen = sArr.length; 209 if (sLen == 0) 210 return new byte[0]; 211 212 int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. 213 214 // Trim illegal chars from start 215 while (sIx < eIx && IA[sArr[sIx]] < 0) 216 sIx++; 217 218 // Trim illegal chars from end 219 while (eIx > 0 && IA[sArr[eIx]] < 0) 220 eIx--; 221 222 // get the padding count (=) (0, 1 or 2) 223 int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end. 224 int cCnt = eIx - sIx + 1; // Content count including possible separators 225 int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; 226 227 int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes 228 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 229 230 // Decode all but the last 0 - 2 bytes. 231 int d = 0; 232 for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { 233 // Assemble three bytes into an int from four "valid" characters. 234 int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; 235 236 // Add the bytes 237 dArr[d++] = (byte) (i >> 16); 238 dArr[d++] = (byte) (i >> 8); 239 dArr[d++] = (byte) i; 240 241 // If line separator, jump over it. 242 if (sepCnt > 0 && ++cc == 19) { 243 sIx += 2; 244 cc = 0; 245 } 246 } 247 248 if (d < len) { 249 // Decode last 1-3 bytes (incl '=') into 1-3 bytes 250 int i = 0; 251 for (int j = 0; sIx <= eIx - pad; j++) 252 i |= IA[sArr[sIx++]] << (18 - j * 6); 253 254 for (int r = 16; d < len; r -= 8) 255 dArr[d++] = (byte) (i >> r); 256 } 257 258 return dArr; 259 } 260 261 // **************************************************************************************** 262 // * byte[] version 263 // **************************************************************************************** 264 265 /** Encodes a raw byte array into a BASE64 <code>byte[]</code> representation i accordance with RFC 2045. 266 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned. 267 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br> 268 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a 269 * little faster. 270 * @return A BASE64 encoded array. Never <code>null</code>. 271 */ 272 public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) 273 { 274 // Check special case 275 if (sArr == null || sArr.length == 0) 276 return new byte[0]; 277 278 int sLen = sArr.length; 279 int eLen = (sLen / 3) * 3; // Length of even 24-bits. 280 int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count 281 int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array 282 byte[] dArr = new byte[dLen]; 283 284 // Encode even 24-bits 285 for (int s = 0, d = 0, cc = 0; s < eLen;) { 286 // Copy next three bytes into lower 24 bits of int, paying attension to sign. 287 int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); 288 289 // Encode the int into four chars 290 dArr[d++] = (byte) CA[(i >>> 18) & 0x3f]; 291 dArr[d++] = (byte) CA[(i >>> 12) & 0x3f]; 292 dArr[d++] = (byte) CA[(i >>> 6) & 0x3f]; 293 dArr[d++] = (byte) CA[i & 0x3f]; 294 295 // Add optional line separator 296 if (lineSep && ++cc == 19 && d < dLen - 2) { 297 dArr[d++] = '\r'; 298 dArr[d++] = '\n'; 299 cc = 0; 300 } 301 } 302 303 // Pad and encode last bits if source isn't an even 24 bits. 304 int left = sLen - eLen; // 0 - 2. 305 if (left > 0) { 306 // Prepare the int 307 int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); 308 309 // Set last four chars 310 dArr[dLen - 4] = (byte) CA[i >> 12]; 311 dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f]; 312 dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '='; 313 dArr[dLen - 1] = '='; 314 } 315 return dArr; 316 } 317 318 /** Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with 319 * and without line separators. 320 * @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. 321 * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters 322 * (including '=') isn't divideable by 4. (I.e. definitely corrupted). 323 */ 324 public final static byte[] decode(byte[] sArr) 325 { 326 // Check special case 327 int sLen = sArr.length; 328 329 // Count illegal characters (including '\r', '\n') to know what size the returned array will be, 330 // so we don't have to reallocate & copy it later. 331 int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) 332 for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. 333 if (IA[sArr[i] & 0xff] < 0) 334 sepCnt++; 335 336 // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. 337 if ((sLen - sepCnt) % 4 != 0) 338 return null; 339 340 int pad = 0; 341 for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) 342 if (sArr[i] == '=') 343 pad++; 344 345 int len = ((sLen - sepCnt) * 6 >> 3) - pad; 346 347 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 348 349 for (int s = 0, d = 0; d < len;) { 350 // Assemble three bytes into an int from four "valid" characters. 351 int i = 0; 352 for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. 353 int c = IA[sArr[s++] & 0xff]; 354 if (c >= 0) 355 i |= c << (18 - j * 6); 356 else 357 j--; 358 } 359 360 // Add the bytes 361 dArr[d++] = (byte) (i >> 16); 362 if (d < len) { 363 dArr[d++]= (byte) (i >> 8); 364 if (d < len) 365 dArr[d++] = (byte) i; 366 } 367 } 368 369 return dArr; 370 } 371 372 373 /** Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as 374 * fast as {@link #decode(byte[])}. The preconditions are:<br> 375 * + The array must have a line length of 76 chars OR no line separators at all (one line).<br> 376 * + Line separator must be "\r\n", as specified in RFC 2045 377 * + The array must not contain illegal characters within the encoded string<br> 378 * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br> 379 * @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. 380 * @return The decoded array of bytes. May be of length 0. 381 */ 382 public final static byte[] decodeFast(byte[] sArr) 383 { 384 // Check special case 385 int sLen = sArr.length; 386 if (sLen == 0) 387 return new byte[0]; 388 389 int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. 390 391 // Trim illegal chars from start 392 while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) 393 sIx++; 394 395 // Trim illegal chars from end 396 while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) 397 eIx--; 398 399 // get the padding count (=) (0, 1 or 2) 400 int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end. 401 int cCnt = eIx - sIx + 1; // Content count including possible separators 402 int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; 403 404 int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes 405 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 406 407 // Decode all but the last 0 - 2 bytes. 408 int d = 0; 409 for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { 410 // Assemble three bytes into an int from four "valid" characters. 411 int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; 412 413 // Add the bytes 414 dArr[d++] = (byte) (i >> 16); 415 dArr[d++] = (byte) (i >> 8); 416 dArr[d++] = (byte) i; 417 418 // If line separator, jump over it. 419 if (sepCnt > 0 && ++cc == 19) { 420 sIx += 2; 421 cc = 0; 422 } 423 } 424 425 if (d < len) { 426 // Decode last 1-3 bytes (incl '=') into 1-3 bytes 427 int i = 0; 428 for (int j = 0; sIx <= eIx - pad; j++) 429 i |= IA[sArr[sIx++]] << (18 - j * 6); 430 431 for (int r = 16; d < len; r -= 8) 432 dArr[d++] = (byte) (i >> r); 433 } 434 435 return dArr; 436 } 437 438 // **************************************************************************************** 439 // * String version 440 // **************************************************************************************** 441 442 /** Encodes a raw byte array into a BASE64 <code>String</code> representation i accordance with RFC 2045. 443 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned. 444 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br> 445 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a 446 * little faster. 447 * @return A BASE64 encoded array. Never <code>null</code>. 448 */ 449 public final static String encodeToString(byte[] sArr, boolean lineSep) 450 { 451 // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. 452 return new String(encodeToChar(sArr, lineSep)); 453 } 454 455 /** Decodes a BASE64 encoded <code>String</code>. All illegal characters will be ignored and can handle both strings with 456 * and without line separators.<br> 457 * <b>Note!</b> It can be up to about 2x the speed to call <code>decode(str.toCharArray())</code> instead. That 458 * will create a temporary array though. This version will use <code>str.charAt(i)</code> to iterate the string. 459 * @param str The source string. <code>null</code> or length 0 will return an empty array. 460 * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters 461 * (including '=') isn't divideable by 4. (I.e. definitely corrupted). 462 */ 463 public final static byte[] decode(String str) 464 { 465 // Check special case 466 if (str == null || str.length() == 0) 467 return new byte[0]; 468 469 int sLen = str.length(); 470 471 // Count illegal characters (including '\r', '\n') to know what size the returned array will be, 472 // so we don't have to reallocate & copy it later. 473 int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) 474 for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. 475 if (IA[str.charAt(i)] < 0) 476 sepCnt++; 477 478 // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. 479 if ((sLen - sepCnt) % 4 != 0) 480 return null; 481 482 // Count '=' at end 483 int pad = 0; 484 for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) 485 if (str.charAt(i) == '=') 486 pad++; 487 488 int len = ((sLen - sepCnt) * 6 >> 3) - pad; 489 490 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 491 492 for (int s = 0, d = 0; d < len;) { 493 // Assemble three bytes into an int from four "valid" characters. 494 int i = 0; 495 for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. 496 int c = IA[str.charAt(s++)]; 497 if (c >= 0) 498 i |= c << (18 - j * 6); 499 else 500 j--; 501 } 502 // Add the bytes 503 dArr[d++] = (byte) (i >> 16); 504 if (d < len) { 505 dArr[d++]= (byte) (i >> 8); 506 if (d < len) 507 dArr[d++] = (byte) i; 508 } 509 } 510 return dArr; 511 } 512 513 /** Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as 514 * fast as {@link #decode(String)}. The preconditions are:<br> 515 * + The array must have a line length of 76 chars OR no line separators at all (one line).<br> 516 * + Line separator must be "\r\n", as specified in RFC 2045 517 * + The array must not contain illegal characters within the encoded string<br> 518 * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br> 519 * @param s The source string. Length 0 will return an empty array. <code>null</code> will throw an exception. 520 * @return The decoded array of bytes. May be of length 0. 521 */ 522 public final static byte[] decodeFast(String s) 523 { 524 // Check special case 525 if (s == null || s.length() == 0) 526 return new byte[0]; 527 528 int sLen = s.length(); 529 int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. 530 531 // Trim illegal chars from start 532 while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) 533 sIx++; 534 535 // Trim illegal chars from end 536 while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) 537 eIx--; 538 539 // get the padding count (=) (0, 1 or 2) 540 int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end. 541 int cCnt = eIx - sIx + 1; // Content count including possible separators 542 int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0; 543 544 int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes 545 byte[] dArr = new byte[len]; // Preallocate byte[] of exact length 546 547 // Decode all but the last 0 - 2 bytes. 548 int d = 0; 549 for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { 550 // Assemble three bytes into an int from four "valid" characters. 551 int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)]; 552 553 // Add the bytes 554 dArr[d++] = (byte) (i >> 16); 555 dArr[d++] = (byte) (i >> 8); 556 dArr[d++] = (byte) i; 557 558 // If line separator, jump over it. 559 if (sepCnt > 0 && ++cc == 19) { 560 sIx += 2; 561 cc = 0; 562 } 563 } 564 565 if (d < len) { 566 // Decode last 1-3 bytes (incl '=') into 1-3 bytes 567 int i = 0; 568 for (int j = 0; sIx <= eIx - pad; j++) 569 i |= IA[s.charAt(sIx++)] << (18 - j * 6); 570 571 for (int r = 16; d < len; r -= 8) 572 dArr[d++] = (byte) (i >> r); 573 } 574 575 return dArr; 576 } 577}