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    }