| | |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | public class Base64 |
| | | { |
| | | public class Base64 { |
| | | private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); |
| | | private static final int[] IA = new int[256]; |
| | | |
| | | static |
| | | { |
| | | static { |
| | | Arrays.fill(IA, -1); |
| | | for (int i = 0, iS = CA.length; i < iS; i++) |
| | | IA[CA[i]] = i; |
| | |
| | | * little faster. |
| | | * @return A BASE64 encoded array. Never <code>null</code>. |
| | | */ |
| | | public static char[] encodeToChar(byte[] sArr, boolean lineSep) |
| | | { |
| | | public static char[] encodeToChar(byte[] sArr, boolean lineSep) { |
| | | // Check special case |
| | | int sLen = sArr != null ? sArr.length : 0; |
| | | if (sLen == 0) |
| | |
| | | char[] dArr = new char[dLen]; |
| | | |
| | | // Encode even 24-bits |
| | | for (int s = 0, d = 0, cc = 0; s < eLen;) |
| | | { |
| | | for (int s = 0, d = 0, cc = 0; s < eLen;) { |
| | | // Copy next three bytes into lower 24 bits of int, paying attension to sign. |
| | | int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); |
| | | |
| | |
| | | dArr[d++] = CA[i & 0x3f]; |
| | | |
| | | // Add optional line separator |
| | | if (lineSep && ++cc == 19 && d < dLen - 2) |
| | | { |
| | | if (lineSep && ++cc == 19 && d < dLen - 2) { |
| | | dArr[d++] = '\r'; |
| | | dArr[d++] = '\n'; |
| | | cc = 0; |
| | |
| | | |
| | | // Pad and encode last bits if source isn't even 24 bits. |
| | | int left = sLen - eLen; // 0 - 2. |
| | | if (left > 0) |
| | | { |
| | | if (left > 0) { |
| | | // Prepare the int |
| | | int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); |
| | | |
| | |
| | | * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters |
| | | * (including '=') isn't divideable by 4. (I.e. definitely corrupted). |
| | | */ |
| | | public static byte[] decode(char[] sArr) |
| | | { |
| | | public static byte[] decode(char[] sArr) { |
| | | // Check special case |
| | | int sLen = sArr != null ? sArr.length : 0; |
| | | if (sLen == 0) |
| | |
| | | |
| | | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | for (int s = 0, d = 0; d < len;) |
| | | { |
| | | for (int s = 0, d = 0; d < len;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = 0; |
| | | for (int j = 0; j < 4; j++) |
| | | { // j only increased if a valid char was found. |
| | | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. |
| | | int c = IA[sArr[s++]]; |
| | | if (c >= 0) |
| | | i |= c << (18 - j * 6); |
| | |
| | | } |
| | | // Add the bytes |
| | | dArr[d++] = (byte) (i >> 16); |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | dArr[d++] = (byte) (i >> 8); |
| | | if (d < len) |
| | | dArr[d++] = (byte) i; |
| | |
| | | * @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. |
| | | * @return The decoded array of bytes. May be of length 0. |
| | | */ |
| | | public byte[] decodeFast(char[] sArr) |
| | | { |
| | | public byte[] decodeFast(char[] sArr) { |
| | | // Check special case |
| | | int sLen = sArr.length; |
| | | if (sLen == 0) |
| | |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) |
| | | { |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; |
| | | |
| | |
| | | dArr[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) |
| | | { |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |
| | |
| | | * little faster. |
| | | * @return A BASE64 encoded array. Never <code>null</code>. |
| | | */ |
| | | public static byte[] encodeToByte(byte[] sArr, boolean lineSep) |
| | | { |
| | | public static byte[] encodeToByte(byte[] sArr, boolean lineSep) { |
| | | // Check special case |
| | | int sLen = sArr != null ? sArr.length : 0; |
| | | if (sLen == 0) |
| | |
| | | byte[] dArr = new byte[dLen]; |
| | | |
| | | // Encode even 24-bits |
| | | for (int s = 0, d = 0, cc = 0; s < eLen;) |
| | | { |
| | | for (int s = 0, d = 0, cc = 0; s < eLen;) { |
| | | // Copy next three bytes into lower 24 bits of int, paying attension to sign. |
| | | int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); |
| | | |
| | |
| | | dArr[d++] = (byte) CA[i & 0x3f]; |
| | | |
| | | // Add optional line separator |
| | | if (lineSep && ++cc == 19 && d < dLen - 2) |
| | | { |
| | | if (lineSep && ++cc == 19 && d < dLen - 2) { |
| | | dArr[d++] = '\r'; |
| | | dArr[d++] = '\n'; |
| | | cc = 0; |
| | |
| | | |
| | | // Pad and encode last bits if source isn't an even 24 bits. |
| | | int left = sLen - eLen; // 0 - 2. |
| | | if (left > 0) |
| | | { |
| | | if (left > 0) { |
| | | // Prepare the int |
| | | int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); |
| | | |
| | |
| | | * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters |
| | | * (including '=') isn't divideable by 4. (I.e. definitely corrupted). |
| | | */ |
| | | public static byte[] decode(byte[] sArr) |
| | | { |
| | | public static byte[] decode(byte[] sArr) { |
| | | // Check special case |
| | | int sLen = sArr.length; |
| | | |
| | |
| | | |
| | | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | for (int s = 0, d = 0; d < len;) |
| | | { |
| | | for (int s = 0, d = 0; d < len;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = 0; |
| | | for (int j = 0; j < 4; j++) |
| | | { // j only increased if a valid char was found. |
| | | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. |
| | | int c = IA[sArr[s++] & 0xff]; |
| | | if (c >= 0) |
| | | i |= c << (18 - j * 6); |
| | |
| | | |
| | | // Add the bytes |
| | | dArr[d++] = (byte) (i >> 16); |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | dArr[d++] = (byte) (i >> 8); |
| | | if (d < len) |
| | | dArr[d++] = (byte) i; |
| | |
| | | * @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. |
| | | * @return The decoded array of bytes. May be of length 0. |
| | | */ |
| | | public static byte[] decodeFast(byte[] sArr) |
| | | { |
| | | public static byte[] decodeFast(byte[] sArr) { |
| | | // Check special case |
| | | int sLen = sArr.length; |
| | | if (sLen == 0) |
| | |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) |
| | | { |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; |
| | | |
| | |
| | | dArr[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) |
| | | { |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |
| | |
| | | * little faster. |
| | | * @return A BASE64 encoded array. Never <code>null</code>. |
| | | */ |
| | | public static String encodeToString(byte[] sArr, boolean lineSep) |
| | | { |
| | | public static String encodeToString(byte[] sArr, boolean lineSep) { |
| | | // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. |
| | | return new String(encodeToChar(sArr, lineSep)); |
| | | } |
| | |
| | | * @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters |
| | | * (including '=') isn't divideable by 4. (I.e. definitely corrupted). |
| | | */ |
| | | public static byte[] decode(String str) |
| | | { |
| | | public static byte[] decode(String str) { |
| | | // Check special case |
| | | int sLen = str != null ? str.length() : 0; |
| | | if (sLen == 0) |
| | |
| | | |
| | | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | for (int s = 0, d = 0; d < len;) |
| | | { |
| | | for (int s = 0, d = 0; d < len;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = 0; |
| | | for (int j = 0; j < 4; j++) |
| | | { // j only increased if a valid char was found. |
| | | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. |
| | | int c = IA[str.charAt(s++)]; |
| | | if (c >= 0) |
| | | i |= c << (18 - j * 6); |
| | |
| | | } |
| | | // Add the bytes |
| | | dArr[d++] = (byte) (i >> 16); |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | dArr[d++] = (byte) (i >> 8); |
| | | if (d < len) |
| | | dArr[d++] = (byte) i; |
| | |
| | | * @param s The source string. Length 0 will return an empty array. <code>null</code> will throw an exception. |
| | | * @return The decoded array of bytes. May be of length 0. |
| | | */ |
| | | public static byte[] decodeFast(String s) |
| | | { |
| | | public static byte[] decodeFast(String s) { |
| | | // Check special case |
| | | int sLen = s.length(); |
| | | if (sLen == 0) |
| | |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) |
| | | { |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)]; |
| | | |
| | |
| | | dArr[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) |
| | | { |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) |
| | | { |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |