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