16 static uint maxint = ~0;
22 return cp - ('0' - 26);
31 encode_digit(uint d, int flag)
34 return d + (flag ? 'A' : 'a');
35 return d + ('0' - 26);
39 adapt(uint delta, uint numpoints, int firsttime)
43 delta = firsttime ? delta / damp : delta >> 1;
44 delta += delta / numpoints;
45 for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base)
47 return k + (base - tmin + 1) * delta / (delta + skew);
51 punyencode(uint input_length, Rune input[], uint max_out, char output[])
53 uint n, delta, h, b, out, bias, j, m, q, k, t;
59 for (j = 0; j < input_length; ++j) {
60 if ((uint)input[j] < 0x80) {
61 if (max_out - out < 2)
63 output[out++] = input[j];
72 while (h < input_length) {
73 for (m = maxint, j = 0; j < input_length; ++j) {
74 if (input[j] >= n && input[j] < m)
78 if (m - n > (maxint - delta) / (h + 1))
81 delta += (m - n) * (h + 1);
84 for (j = 0; j < input_length; ++j) {
91 for (q = delta, k = base;; k += base) {
96 else if (k >= bias + tmax)
102 output[out++] = encode_digit(t + (q - t) % (base - t), 0);
103 q = (q - t) / (base - t);
105 output[out++] = encode_digit(q, isupperrune(input[j]));
106 bias = adapt(delta, h + 1, h == b);
119 punydecode(uint input_length, char input[], uint max_out, Rune output[])
121 uint n, out, i, bias, b, j, in, oldi, w, k, digit, t;
127 for (b = j = 0; j < input_length; ++j)
134 for (j = 0; j < b; ++j) {
137 output[out++] = input[j];
140 for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) {
141 for (oldi = i, w = 1, k = base;; k += base) {
142 if (in >= input_length)
144 digit = decode_digit(input[in++]);
147 if (digit > (maxint - i) / w)
152 else if (k >= bias + tmax)
158 if (w > maxint / (base - t))
163 bias = adapt(i - oldi, out + 1, oldi == 0);
165 if (i / (out + 1) > maxint - n)
173 memmove(output + i + 1, output + i, (out - i) * sizeof *output);
174 if(((uint)input[in-1] - 'A') < 26)
175 output[i++] = toupperrune(n);
177 output[i++] = tolowerrune(n);
184 * convert punycode encoded internationalized
185 * domain name to unicode string
188 idn2utf(char *name, char *buf, int nbuf)
200 n = chartorune(&r, cp+nc);
206 if(cistrncmp(cp, "xn--", 4) == 0)
207 if((nr = punydecode(nc-4, cp+4, nelem(rb), rb)) < 0)
209 dp = seprint(dp, de, "%.*S", nr, rb);
222 * convert unicode string to punycode
223 * encoded internationalized domain name
226 utf2idn(char *name, char *buf, int nbuf)
237 while(cp[nc] != 0 && nr < nelem(rb)){
238 n = chartorune(&r, cp+nc);
245 dp = seprint(dp, de, "%.*s", nc, cp);
247 dp = seprint(dp, de, "xn--");
248 if((n = punyencode(nr, rb, de - dp, dp)) < 0)