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 }