3 /// Author: Alexander Gnauck AG-Software, mailto:gnauck@ag-software.de
5 /// This file is part of GNU Libidn.
7 /// This library is free software; you can redistribute it and/or
8 /// modify it under the terms of the GNU Lesser General Public License
9 /// as published by the Free Software Foundation; either version 2.1 of
10 /// the License, or (at your option) any later version.
12 /// This library is distributed in the hope that it will be useful, but
13 /// WITHOUT ANY WARRANTY; without even the implied warranty of
14 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 /// Lesser General Public License for more details.
17 /// You should have received a copy of the GNU Lesser General Public
18 /// License along with this library; if not, write to the Free Software
19 /// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
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
= '-';
42 /// Punycodes a unicode string.
44 /// <param name="input">Unicode string.</param>
45 /// <returns> Punycoded string.</returns>
46 public static string Encode(string input
)
50 int bias
= INITIAL_BIAS
;
51 StringBuilder output
= new StringBuilder();
53 // Copy all basic code points to the output
55 for (int i
= 0; i
< input
.Length
; i
++)
68 output
.Append(DELIMITER
);
72 while (h
< input
.Length
)
74 int m
= System
.Int32
.MaxValue
;
76 // Find the minimum code point >= n
77 for (int i
= 0; i
< input
.Length
; i
++)
86 if (m
- n
> (System
.Int32
.MaxValue
- delta
) / (h
+ 1))
88 throw new PunycodeException(PunycodeException
.OVERFLOW
);
90 delta
= delta
+ (m
- n
) * (h
+ 1);
93 for (int j
= 0; j
< input
.Length
; j
++)
101 throw new PunycodeException(PunycodeException
.OVERFLOW
);
108 for (int k
= BASE
; ; k
+= BASE
)
115 else if (k
>= bias
+ TMAX
)
127 output
.Append((char) Digit2Codepoint(t
+ (q
- t
) % (BASE
- t
)));
128 q
= (q
- t
) / (BASE
- t
);
131 output
.Append((char) Digit2Codepoint(q
));
132 bias
= Adapt(delta
, h
+ 1, h
== b
);
142 return output
.ToString();
146 /// Decode a punycoded string.
148 /// <param name="input">Punycode string</param>
149 /// <returns> Unicode string.</returns>
150 public static string Decode(string input
)
154 int bias
= INITIAL_BIAS
;
155 StringBuilder output
= new StringBuilder();
157 int d
= input
.LastIndexOf((System
.Char
) DELIMITER
);
160 for (int j
= 0; j
< d
; j
++)
165 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
176 while (d
< input
.Length
)
181 for (int k
= BASE
; ; k
+= BASE
)
183 if (d
== input
.Length
)
185 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
188 int digit
= Codepoint2Digit(c
);
189 if (digit
> (System
.Int32
.MaxValue
- i
) / w
)
191 throw new PunycodeException(PunycodeException
.OVERFLOW
);
201 else if (k
>= bias
+ TMAX
)
216 bias
= Adapt(i
- oldi
, output
.Length
+ 1, oldi
== 0);
218 if (i
/ (output
.Length
+ 1) > Int32
.MaxValue
- n
)
220 throw new PunycodeException(PunycodeException
.OVERFLOW
);
223 n
= n
+ i
/ (output
.Length
+ 1);
224 i
= i
% (output
.Length
+ 1);
225 // following overload is not supported on CF
226 //output.Insert(i,(char) n);
227 output
.Insert(i
, new char[1] { (char) n }
);
231 return output
.ToString();
234 public static int Adapt(int delta
, int numpoints
, bool first
)
238 delta
= delta
/ DAMP
;
245 delta
= delta
+ (delta
/ numpoints
);
248 while (delta
> ((BASE
- TMIN
) * TMAX
) / 2)
250 delta
= delta
/ (BASE
- TMIN
);
254 return k
+ ((BASE
- TMIN
+ 1) * delta
) / (delta
+ SKEW
);
257 public static bool IsBasic(char c
)
262 public static int Digit2Codepoint(int d
)
271 // 26..35 : '0'..'9';
276 throw new PunycodeException(PunycodeException
.BAD_INPUT
);
280 public static int Codepoint2Digit(int c
)
287 else if (c
- 'a' < 26)
294 throw new PunycodeException(PunycodeException
.BAD_INPUT
);