    001    package com.skype.util;
    002
    003    import java.util.Arrays;
    004
    005
    006    public class BaseX
    007    {
    008
    009        public BaseX(String s, boolean flag, char c) {
    010            for (bits = 1; 1 << bits < s.length(); bits++)
    011                ;
    012            if (1 << bits != s.length())
    013                throw new IllegalArgumentException("The size of the encoding alphabet is not a power of 2");
    014            block = 8 / gcd(8, bits);
    015            chars = s.toCharArray();
    016            min = max = - 1;
    017            if (flag) {
    018                addMinMax(s);
    019                values = new int[(max - min) + 1];
    020                Arrays.fill(values, - 1);
    021                addChars(s);
    022            }
    023            else {
    024                addMinMax(s.toUpperCase());
    025                addMinMax(s.toLowerCase());
    026                values = new int[(max - min) + 1];
    027                Arrays.fill(values, - 1);
    028                addChars(s.toUpperCase());
    029                addChars(s.toLowerCase());
    030            }
    031            if (c >= min && c <= max && values[c - min] != - 1) {
    032                throw new IllegalArgumentException("The padding character appears in the encoding alphabet");
    033            }
    034            else {
    035                pad = c;
    036                return;
    037            }
    038        }
    039
    040        private void addMinMax(String s)
    041        {
    042            for (int i = 0; i < s.length(); i++) {
    043                int j = s.codePointAt(i);
    044                if (min == - 1 || min > j)
    045                    min = j;
    046                if (max == - 1 || max < j)
    047                    max = j;
    048            }
    049
    050        }
    051
    052        private void addChars(String s)
    053        {
    054            for (int i = 0; i < s.length(); i++) {
    055                int j = s.codePointAt(i) - min;
    056                if (values[j] != - 1 && values[j] != i)
    057                    throw new IllegalArgumentException("Duplicate characters in the encoding alphapbet");
    058                values[j] = i;
    059            }
    060
    061        }
    062
    063        public StringBuffer encode(byte abyte0[], String s, int i)
    064        {
    065            if (s == null) {
    066                i = 0;
    067            }
    068            else {
    069                for (int j = 0; j < s.length(); j++) {
    070                    int l = s.codePointAt(j);
    071                    if (l >= min && l <= max && values[l - min] != - 1)
    072                        throw new IllegalArgumentException("The separator contains characters from the encoding alphabet");
    073                }
    074
    075            }
    076            int k = ((8 * abyte0.length + bits) - 1) / bits;
    077            k = (((k + block) - 1) / block) * block;
    078            if (i > 0)
    079                k += ((k - 1) / i) * s.length();
    080            StringBuffer stringbuffer = new StringBuffer(k);
    081            int i1 = 0;
    082            int j1 = 0;
    083            int k1 = 0;
    084            int l1 = 0;
    085            int i2 = (1 << bits) - 1;
    086            for (; bits * i1 < 8 * abyte0.length; i1++) {
    087                if (i > 0 && i1 > 0 && i1 % i == 0)
    088                    stringbuffer.append(s);
    089                for (; l1 < bits; l1 += 8) {
    090                    byte byte0 = j1 >= abyte0.length ? 0 : abyte0[j1];
    091                    j1++;
    092                    k1 = k1 << 8 | byte0 & 0xff;
    093                }
    094
    095                stringbuffer.append(chars[k1 >>> l1 - bits & i2]);
    096                l1 -= bits;
    097            }
    098
    099            for (; i1 % block != 0; i1++) {
    100                if (i > 0 && i1 > 0 && i1 % i == 0)
    101                    stringbuffer.append(s);
    102                stringbuffer.append(pad);
    103            }
    104
    105            return stringbuffer;
    106        }
    107
    108        public byte[] decode(String s)
    109        {
    110            byte abyte0[] = new byte[(s.length() * bits) / 8];
    111            int i = 0;
    112            int j = 0;
    113            int k = 0;
    114            int l = 0;
    115            do {
    116                if (j >= s.length())
    117                    break;
    118                int i1 = s.codePointAt(j);
    119                j++;
    120                if (i1 >= min && i1 <= max) {
    121                    i1 = values[i1 - min];
    122                    if (i1 != - 1) {
    123                        k = k << bits | i1;
    124                        l += bits;
    125                        while (l >= 8) {
    126                            abyte0[i] = (byte)(k >>> l - 8 & 0xff);
    127                            l -= 8;
    128                            i++;
    129                        }
    130                    }
    131                }
    132            }
    133            while (true);
    134            if (i < abyte0.length) {
    135                byte abyte1[] = abyte0;
    136                abyte0 = new byte[i];
    137                System.arraycopy(abyte1, 0, abyte0, 0, i);
    138            }
    139            return abyte0;
    140        }
    141
    142        private static int gcd(int i, int j)
    143        {
    144            i = Math.abs(i);
    145            j = Math.abs(j);
    146            int k;
    147            for (; i > 0; i = k) {
    148                k = j % i;
    149                j = i;
    150            }
    151
    152            return j;
    153        }
    154
    155        private char    chars[];
    156        private int  values[];
    157        private int  min;
    158        private int  max;
    159        private int  bits;
    160        private int  block;
    161        private char    pad;
    162    }