-
Notifications
You must be signed in to change notification settings - Fork 0
/
punycoder.jl
112 lines (106 loc) · 2.53 KB
/
punycoder.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module Punycoder
base = 36
tmin = 1
tmax = 26
skew = 38
damp = 700
initial_bias = 72
initial_n = 128
code_points = ['a':'z';'0':'9']
function getbasicstring(str)
return join([isascii(c) ? c : "" for c in str])
end
function adapt(delta, numpoints, firsttime)
delta = if firsttime
div(delta, damp)
else
div(delta, 2)
end
delta += div(delta, numpoints)
k = 0
while delta > div((base - tmin) * tmax, 2)
delta = div(delta, base - tmin)
k += base
end # while
return k + div((base - tmin + 1) * delta, delta + skew)
end
function encode(input)
n, delta, bias = initial_n, 0, initial_bias
encoded_string = getbasicstring(input)
inputLength = length(input)
h = b = length(encoded_string)
if h > 0
encoded_string *= "-"
end # if
input = collect(input)
while h < inputLength
m = minimum(filter(x->!isascii(x) && x >= n, input))
delta += Int(m - n) * (h + 1)
n = m
for c in input
if c < n
delta += 1
elseif c == n
q = delta
for k in base:base:10000000
t = if k <= bias
tmin
elseif k >= bias + tmax
tmax
else
k - bias
end # if
if q < t
break
end
encoded_string = string(encoded_string, code_points[t + 1 + ((q - t) % (base - t))])
q = div((q - t), (base - t))
end # for
encoded_string = string(encoded_string, code_points[q + 1])
bias = adapt(delta, h + 1, h == b)
delta = 0
h += 1
end # if
end # for
delta += 1
n += 1
end # while
return encoded_string
end # function
function decode(input)
n, i, bias = initial_n, 0, initial_bias
input_parts = split(input, '-')
output = collect(input_parts[1])
input = collect(input_parts[end])
while length(input) > 0
oldi, w = i, 1
for k in base:base:10000000
digit = findfirst(code_points, input[1]) - 1
i += digit * w
t = if k <= bias
tmin
elseif k >= bias + tmax
tmax
else
k - bias
end # if
if digit < t
break
end # if
w *= base - t
input = input[2:end]
end # for
bias = adapt(i - oldi, length(output) + 1, oldi == 0)
n += div(i, length(output) + 1)
i = i % (length(output) + 1)
if i == 0
splice!(output, 1, [n, output[1]])
else
splice!(output, i, [output[i], n])
end
i += 1
input = input[2:end]
end # while
return join(output)
end # function
end # module