21 static uint maxint = ~0;
27 return cp - ('0' - 26);
36 encode_digit(uint d, int flag)
39 return d + (flag ? 'A' : 'a');
40 return d + ('0' - 26);
44 adapt(uint delta, uint numpoints, int firsttime)
48 delta = firsttime ? delta / damp : delta >> 1;
49 delta += delta / numpoints;
50 for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base)
52 return k + (base - tmin + 1) * delta / (delta + skew);
56 punyencode(uint input_length, Rune input[], uint max_out, char output[])
58 uint n, delta, h, b, out, bias, j, m, q, k, t;
64 for (j = 0; j < input_length; ++j) {
65 if ((uint)input[j] < 0x80) {
66 if (max_out - out < 2)
68 output[out++] = input[j];
77 while (h < input_length) {
78 for (m = maxint, j = 0; j < input_length; ++j) {
79 if (input[j] >= n && input[j] < m)
83 if (m - n > (maxint - delta) / (h + 1))
86 delta += (m - n) * (h + 1);
89 for (j = 0; j < input_length; ++j) {
96 for (q = delta, k = base;; k += base) {
101 else if (k >= bias + tmax)
107 output[out++] = encode_digit(t + (q - t) % (base - t), 0);
108 q = (q - t) / (base - t);
110 output[out++] = encode_digit(q, isupperrune(input[j]));
111 bias = adapt(delta, h + 1, h == b);
124 punydecode(uint input_length, char input[], uint max_out, Rune output[])
126 uint n, out, i, bias, b, j, in, oldi, w, k, digit, t;
132 for (b = j = 0; j < input_length; ++j)
139 for (j = 0; j < b; ++j) {
142 output[out++] = input[j];
145 for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) {
146 for (oldi = i, w = 1, k = base;; k += base) {
147 if (in >= input_length)
149 digit = decode_digit(input[in++]);
152 if (digit > (maxint - i) / w)
157 else if (k >= bias + tmax)
163 if (w > maxint / (base - t))
168 bias = adapt(i - oldi, out + 1, oldi == 0);
170 if (i / (out + 1) > maxint - n)
178 memmove(output + i + 1, output + i, (out - i) * sizeof *output);
179 if(((uint)input[in-1] - 'A') < 26)
180 output[i++] = toupperrune(n);
182 output[i++] = tolowerrune(n);
189 * convert punycode encoded internationalized
190 * domain name to unicode string
193 idn2utf(char *name, char *buf, int nbuf)
205 n = chartorune(&r, cp+nc);
211 if(cistrncmp(cp, "xn--", 4) == 0)
212 if((nr = punydecode(nc-4, cp+4, nelem(rb), rb)) < 0)
214 dp = seprint(dp, de, "%.*S", nr, rb);
227 * convert unicode string to punycode
228 * encoded internationalized domain name
231 utf2idn(char *name, char *buf, int nbuf)
242 while(cp[nc] != 0 && nr < nelem(rb)){
243 n = chartorune(&r, cp+nc);
250 dp = seprint(dp, de, "%.*s", nc, cp);
252 dp = seprint(dp, de, "xn--");
253 if((n = punyencode(nr, rb, de - dp, dp)) < 0)