2 /// Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4 /// Author: Alexander Gnauck AG-Software
6 /// This file is part of GNU Libidn.
8 /// This program is free software; you can redistribute it and/or
9 /// modify it under the terms of the GNU General Public License as
10 /// published by the Free Software Foundation; either version 2 of the
11 /// License, or (at your option) any later version.
13 /// This program is distributed in the hope that it will be useful,
14 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 /// General Public License for more details.
18 /// You should have received a copy of the GNU General Public License
19 /// along with this program; if not, write to the Free Software
20 /// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 namespace gnu
.inet
.encoding
31 /* Punycode parameters */
32 internal const int TMIN
= 1;
33 internal const int TMAX
= 26;
34 internal const int BASE
= 36;
35 internal const int INITIAL_N
= 128;
36 internal const int INITIAL_BIAS
= 72;
37 internal const int DAMP
= 700;
38 internal const int SKEW
= 38;
39 internal const char DELIMITER
= '-';
41 /// <summary> Punycodes a unicode string.
44 /// <param name="input">Unicode string.
46 /// <returns> Punycoded string.
49 public static System
.String
encode(System
.String input
)
53 int bias
= INITIAL_BIAS
;
54 System
.Text
.StringBuilder output
= new System
.Text
.StringBuilder();
56 // Copy all basic code points to the output
58 for (int i
= 0; i
< input
.Length
; i
++)
71 output
.Append(DELIMITER
);
75 while (h
< input
.Length
)
77 int m
= System
.Int32
.MaxValue
;
79 // Find the minimum code point >= n
80 for (int i
= 0; i
< input
.Length
; i
++)
89 if (m
- n
> (System
.Int32
.MaxValue
- delta
) / (h
+ 1))
91 throw new PunycodeException(PunycodeException
.OVERFLOW
);
93 delta
= delta
+ (m
- n
) * (h
+ 1);
96 for (int j
= 0; j
< input
.Length
; j
++)
104 throw new PunycodeException(PunycodeException
.OVERFLOW
);
111 for (int k
= BASE
; ; k
+= BASE
)
118 else if (k
>= bias
+ TMAX
)
130 output
.Append((char) digit2codepoint(t
+ (q
- t
) % (BASE
- t
)));
131 q
= (q
- t
) / (BASE
- t
);
134 output
.Append((char) digit2codepoint(q
));
135 bias
= adapt(delta
, h
+ 1, h
== b
);
145 return output
.ToString();
148 /// <summary> Decode a punycoded string.
151 /// <param name="input">Punycode string
153 /// <returns> Unicode string.
156 public static System
.String
decode(System
.String input
)
160 int bias
= INITIAL_BIAS
;
161 System
.Text
.StringBuilder output
= new System
.Text
.StringBuilder();
163 int d
= input
.LastIndexOf((System
.Char
) DELIMITER
);
166 for (int j
= 0; j
< d
; j
++)
171 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
182 while (d
< input
.Length
)
187 for (int k
= BASE
; ; k
+= BASE
)
189 if (d
== input
.Length
)
191 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
194 int digit
= codepoint2digit(c
);
195 if (digit
> (System
.Int32
.MaxValue
- i
) / w
)
197 throw new PunycodeException(PunycodeException
.OVERFLOW
);
207 else if (k
>= bias
+ TMAX
)
222 bias
= adapt(i
- oldi
, output
.Length
+ 1, oldi
== 0);
224 if (i
/ (output
.Length
+ 1) > System
.Int32
.MaxValue
- n
)
226 throw new PunycodeException(PunycodeException
.OVERFLOW
);
229 n
= n
+ i
/ (output
.Length
+ 1);
230 i
= i
% (output
.Length
+ 1);
231 // following overload is not supported on CF
232 //output.Insert(i,(char) n);
233 output
.Insert(i
, new char[1] { (char) n }
);
237 return output
.ToString();
240 public static int adapt(int delta
, int numpoints
, bool first
)
244 delta
= delta
/ DAMP
;
251 delta
= delta
+ (delta
/ numpoints
);
254 while (delta
> ((BASE
- TMIN
) * TMAX
) / 2)
256 delta
= delta
/ (BASE
- TMIN
);
260 return k
+ ((BASE
- TMIN
+ 1) * delta
) / (delta
+ SKEW
);
263 public static bool isBasic(char c
)
268 public static int digit2codepoint(int d
)
277 // 26..35 : '0'..'9';
282 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
286 public static int codepoint2digit(int c
)
293 else if (c
- 'a' < 26)
300 throw new PunycodeException(PunycodeException
.BAD_INPUT
);