home *** CD-ROM | disk | FTP | other *** search
- package gnu.inet;
-
- public class Punycode {
- static final int TMIN = 1;
- static final int TMAX = 26;
- static final int BASE = 36;
- static final int INITIAL_N = 128;
- static final int INITIAL_BIAS = 72;
- static final int DAMP = 700;
- static final int SKEW = 38;
- static final char DELIMITER = '-';
-
- public static String encode(String input) throws PunycodeException {
- int n = 128;
- int delta = 0;
- int bias = 72;
- StringBuffer output = new StringBuffer();
- int b = 0;
-
- for(int i = 0; i < input.length(); ++i) {
- char c = input.charAt(i);
- if (isBasic(c)) {
- output.append(c);
- ++b;
- }
- }
-
- if (b > 0) {
- output.append('-');
- }
-
- for(int h = b; h < input.length(); ++n) {
- int m = Integer.MAX_VALUE;
-
- for(int i = 0; i < input.length(); ++i) {
- int c = input.charAt(i);
- if (c >= n && c < m) {
- m = c;
- }
- }
-
- if (m - n > (Integer.MAX_VALUE - delta) / (h + 1)) {
- throw new PunycodeException(PunycodeException.OVERFLOW);
- }
-
- delta += (m - n) * (h + 1);
- n = m;
-
- for(int j = 0; j < input.length(); ++j) {
- int c = input.charAt(j);
- if (c < n) {
- ++delta;
- if (delta == 0) {
- throw new PunycodeException(PunycodeException.OVERFLOW);
- }
- }
-
- if (c == n) {
- int q = delta;
- int k = 36;
-
- while(true) {
- int t;
- if (k <= bias) {
- t = 1;
- } else if (k >= bias + 26) {
- t = 26;
- } else {
- t = k - bias;
- }
-
- if (q < t) {
- output.append((char)digit2codepoint(q));
- bias = adapt(delta, h + 1, h == b);
- delta = 0;
- ++h;
- break;
- }
-
- output.append((char)digit2codepoint(t + (q - t) % (36 - t)));
- q = (q - t) / (36 - t);
- k += 36;
- }
- }
- }
-
- ++delta;
- }
-
- return output.toString();
- }
-
- public static String decode(String input) throws PunycodeException {
- int n = 128;
- int i = 0;
- int bias = 72;
- StringBuffer output = new StringBuffer();
- int d = input.lastIndexOf(45);
- if (d > 0) {
- for(int j = 0; j < d; ++j) {
- char c = input.charAt(j);
- if (!isBasic(c)) {
- throw new PunycodeException(PunycodeException.BAD_INPUT);
- }
-
- output.append(c);
- }
-
- ++d;
- } else {
- d = 0;
- }
-
- label53:
- while(d < input.length()) {
- int oldi = i;
- int w = 1;
-
- for(int k = 36; d != input.length(); k += 36) {
- int c = input.charAt(d++);
- int digit = codepoint2digit(c);
- if (digit > (Integer.MAX_VALUE - i) / w) {
- throw new PunycodeException(PunycodeException.OVERFLOW);
- }
-
- i += digit * w;
- int t;
- if (k <= bias) {
- t = 1;
- } else if (k >= bias + 26) {
- t = 26;
- } else {
- t = k - bias;
- }
-
- if (digit < t) {
- bias = adapt(i - oldi, output.length() + 1, oldi == 0);
- if (i / (output.length() + 1) > Integer.MAX_VALUE - n) {
- throw new PunycodeException(PunycodeException.OVERFLOW);
- }
-
- n += i / (output.length() + 1);
- i %= output.length() + 1;
- output.insert(i, (char)n);
- ++i;
- continue label53;
- }
-
- w *= 36 - t;
- }
-
- throw new PunycodeException(PunycodeException.BAD_INPUT);
- }
-
- return output.toString();
- }
-
- public static final int adapt(int delta, int numpoints, boolean first) {
- if (first) {
- delta /= 700;
- } else {
- delta /= 2;
- }
-
- delta += delta / numpoints;
-
- int k;
- for(k = 0; delta > 455; k += 36) {
- delta /= 35;
- }
-
- return k + 36 * delta / (delta + 38);
- }
-
- public static final boolean isBasic(char c) {
- return c < 128;
- }
-
- public static final int digit2codepoint(int d) throws PunycodeException {
- if (d < 26) {
- return d + 97;
- } else if (d < 36) {
- return d - 26 + 48;
- } else {
- throw new PunycodeException(PunycodeException.BAD_INPUT);
- }
- }
-
- public static final int codepoint2digit(int c) throws PunycodeException {
- if (c - 48 < 10) {
- return c - 48 + 26;
- } else if (c - 97 < 26) {
- return c - 97;
- } else {
- throw new PunycodeException(PunycodeException.BAD_INPUT);
- }
- }
- }
-