001package biweekly.util;
002
003/**
004 * Encodes and decodes data into base64.
005 * @author <a href="http://stackoverflow.com/users/518568/georgek">GeorgeK</a>
006 * @see <a
007 * href="http://stackoverflow.com/a/4265472/13379">http://stackoverflow.com/a/4265472/13379</a>
008 */
009public class Base64 {
010        private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
011        private static final int[] toInt = new int[128];
012        static {
013                for (int i = 0; i < ALPHABET.length; i++) {
014                        toInt[ALPHABET[i]] = i;
015                }
016        }
017
018        /**
019         * Translates the specified byte array into Base64 string.
020         * @param buf the byte array
021         * @return the translated Base64 string
022         */
023        public static String encode(byte[] buf) {
024                int size = buf.length;
025                char[] ar = new char[((size + 2) / 3) * 4];
026                int a = 0;
027                int i = 0;
028                while (i < size) {
029                        byte b0 = buf[i++];
030                        byte b1 = (i < size) ? buf[i++] : 0;
031                        byte b2 = (i < size) ? buf[i++] : 0;
032
033                        int mask = 0x3F;
034                        ar[a++] = ALPHABET[(b0 >> 2) & mask];
035                        ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
036                        ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
037                        ar[a++] = ALPHABET[b2 & mask];
038                }
039                switch (size % 3) {
040                case 1:
041                        ar[--a] = '=';
042                case 2:
043                        ar[--a] = '=';
044                }
045                return new String(ar);
046        }
047
048        /**
049         * Translates the specified Base64 string into a byte array.
050         * @param s the Base64 string
051         * @return the byte array
052         */
053        public static byte[] decode(String s) {
054                int delta = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0;
055                byte[] buffer = new byte[s.length() * 3 / 4 - delta];
056                int mask = 0xFF;
057                int index = 0;
058                for (int i = 0; i < s.length(); i += 4) {
059                        int c0 = toInt[s.charAt(i)];
060                        int c1 = toInt[s.charAt(i + 1)];
061                        buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
062                        if (index >= buffer.length) {
063                                return buffer;
064                        }
065                        int c2 = toInt[s.charAt(i + 2)];
066                        buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
067                        if (index >= buffer.length) {
068                                return buffer;
069                        }
070                        int c3 = toInt[s.charAt(i + 3)];
071                        buffer[index++] = (byte) (((c2 << 6) | c3) & mask);
072                }
073                return buffer;
074        }
075
076        private Base64() {
077                //hide
078        }
079}