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