...
Source file src/net/http/cookiejar/punycode.go
1
2
3
4
5 package cookiejar
6
7
8
9 import (
10 "fmt"
11 "strings"
12 "unicode/utf8"
13 )
14
15
16
17
18
19 const (
20 base int32 = 36
21 damp int32 = 700
22 initialBias int32 = 72
23 initialN int32 = 128
24 skew int32 = 38
25 tmax int32 = 26
26 tmin int32 = 1
27 )
28
29
30
31
32
33
34 func encode(prefix, s string) (string, error) {
35 output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
36 copy(output, prefix)
37 delta, n, bias := int32(0), initialN, initialBias
38 b, remaining := int32(0), int32(0)
39 for _, r := range s {
40 if r < utf8.RuneSelf {
41 b++
42 output = append(output, byte(r))
43 } else {
44 remaining++
45 }
46 }
47 h := b
48 if b > 0 {
49 output = append(output, '-')
50 }
51 for remaining != 0 {
52 m := int32(0x7fffffff)
53 for _, r := range s {
54 if m > r && r >= n {
55 m = r
56 }
57 }
58 delta += (m - n) * (h + 1)
59 if delta < 0 {
60 return "", fmt.Errorf("cookiejar: invalid label %q", s)
61 }
62 n = m
63 for _, r := range s {
64 if r < n {
65 delta++
66 if delta < 0 {
67 return "", fmt.Errorf("cookiejar: invalid label %q", s)
68 }
69 continue
70 }
71 if r > n {
72 continue
73 }
74 q := delta
75 for k := base; ; k += base {
76 t := k - bias
77 if t < tmin {
78 t = tmin
79 } else if t > tmax {
80 t = tmax
81 }
82 if q < t {
83 break
84 }
85 output = append(output, encodeDigit(t+(q-t)%(base-t)))
86 q = (q - t) / (base - t)
87 }
88 output = append(output, encodeDigit(q))
89 bias = adapt(delta, h+1, h == b)
90 delta = 0
91 h++
92 remaining--
93 }
94 delta++
95 n++
96 }
97 return string(output), nil
98 }
99
100 func encodeDigit(digit int32) byte {
101 switch {
102 case 0 <= digit && digit < 26:
103 return byte(digit + 'a')
104 case 26 <= digit && digit < 36:
105 return byte(digit + ('0' - 26))
106 }
107 panic("cookiejar: internal error in punycode encoding")
108 }
109
110
111 func adapt(delta, numPoints int32, firstTime bool) int32 {
112 if firstTime {
113 delta /= damp
114 } else {
115 delta /= 2
116 }
117 delta += delta / numPoints
118 k := int32(0)
119 for delta > ((base-tmin)*tmax)/2 {
120 delta /= base - tmin
121 k += base
122 }
123 return k + (base-tmin+1)*delta/(delta+skew)
124 }
125
126
127
128
129
130 const acePrefix = "xn--"
131
132
133
134
135 func toASCII(s string) (string, error) {
136 if ascii(s) {
137 return s, nil
138 }
139 labels := strings.Split(s, ".")
140 for i, label := range labels {
141 if !ascii(label) {
142 a, err := encode(acePrefix, label)
143 if err != nil {
144 return "", err
145 }
146 labels[i] = a
147 }
148 }
149 return strings.Join(labels, "."), nil
150 }
151
152 func ascii(s string) bool {
153 for i := 0; i < len(s); i++ {
154 if s[i] >= utf8.RuneSelf {
155 return false
156 }
157 }
158 return true
159 }
160
View as plain text