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 }