Unicodeドメイン名を ASCIIに変換する「Punycode変換」では、先頭に「xn--
」という特徴的な文字列が付加され、一見して元の文字列との対応がわかりにくいです。
しかし、これは コンピュータが ASCII文字列に Unicode文字を一つずつくっつけて、元の文字列を復元するための「レシピ」になっています。
実は、一文字ずつ変換する「URLエンコード」と比べて、コンパクトに収まっています。
Punycodeは、文字変換だけでなく圧縮も含めた変換です。
1. 文字の素とレシピ
「Punycode」は、一般に「ピュニコード」と発音されます1。
例えば、「ちいLabo」は、
「xn--labo-453crg
」と変換されます2。
Punycodeでは、ASCIIとUnicodeが混在した文字列の場合、
「xn--●●-▲▲▲」の形式になります。
「●●」の部分には 素 となるASCII文字列が入り、
「▲▲▲」の部分はUnicodeを付け加える レシピ になっています。
例えば、「1と2345」のように、2文字目にUnicodeが含まれている場合は、「xn--12345-pc4d」というのが、Punycode変換後の文字列です。
逆にいうと、「pc4d」の部分は「2文字目に『と』を追加する」という意味になっているわけです。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
「pd4d」がどのようにしてできているかは、だいぶややこしいです。
文字変換というよりは、「データ圧縮」のような計算処理だからです。
Bootstringパラメータ
base = 36
tmin = 1
tmax = 26
skew = 38
damp = 700
initial_bias = 72
initial_n = 128 = 0x80
code points digit-values
------------ ----------------------
41..5A (A-Z) = 0 to 25, respectively
61..7A (a-z) = 0 to 25, respectively
30..39 (0-9) = 26 to 35, respectively
バイアス適応関数
function adapt(delta, numpoints, firsttime):
if firsttime then let delta = delta div damp
else let delta = delta div 2
let delta = delta + (delta div numpoints)
let k = 0
while delta > ((base - tmin) * tmax) div 2 do begin
let delta = delta div (base - tmin)
let k = k + base
end
return k + (((base - tmin + 1) * delta) div (delta + skew))
符号化手順
let n = initial_n
let delta = 0
let bias = initial_bias
let h = b = the number of basic code points in the input
copy them to the output in order, followed by a delimiter if b > 0
{if the input contains a non-basic code point < n then fail}
while h < length(input) do begin
let m = the minimum {non-basic} code point >= n in the input
let delta = delta + (m - n) * (h + 1), fail on overflow
let n = m
for each code point c in the input (in order) do begin
if c < n {or c is basic} then increment delta, fail on overflow
if c == n then begin
let q = delta
for k = base to infinity in steps of base do begin
let t = tmin if k <= bias {+ tmin}, or
tmax if k >= bias + tmax, or k - bias otherwise
if q < t then break
output the code point for digit t + ((q - t) mod (base - t))
let q = (q - t) div (base - t)
end
output the code point for digit q
let bias = adapt(delta, h + 1, test h equals b?)
let delta = 0
increment h
end
end
increment delta and n
end
1-1. 一文字を追加する
処理のイメージをつかむために、具体的に少しいじってみます。
例えば、2文字目に追加する文字を「て」や「あ」に変更するコードを見てみます。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-dc4d | 1て2345 |
xn--12345-643d | 1あ2345 |
あるいは、文字を挿入する位置を変えてみます。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-qc4d | 12と345 |
xn--12345-sc4d | 123と45 |
レシピの部分が、ちょっとずつ変わっているのがわかります。
2. 2文字を追加する
2文字目を追加すると、レシピ部分も伸びていきます。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-pc4duf | 1と2ま345 |
xn--12345-pc4d1f | 1と2み345 |
コード末尾に2文字ずつ追加されています。
2-1. 2文字目が同じ文字だと簡略
今度は、同じ文字を追加してみます。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-pc4da | 1とと2345 |
xn--12345-pc4dd | 1と234と5 |
末尾に増えたのは1文字だけです。
同じ文字だと、「そこから何文字目に追加されるのか」だけの情報で済むので、短く指示できるのです。
punycodeは、もともとデータ圧縮を考慮して作られているんだね。
2-2. 文字コード表の前の文字だと
ただし、文字コード表の順番が重要です。
例えば、「あ」を追加した場合、コードの外見が大きく変わります。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-743dvj | 1と2あ345 |
これは「と」よりも「あ」の方がコード表で前にあるので、「あ」を入れるレシピが先になるのです。
先に「あ」を入れたコードと比較するとわかりやすいです。
punycode | 文字列 |
---|---|
xn--12345-743d | 12あ345 |
xn--12345-743dvj | 1と2あ345 |
このように、punycodeでは、使われるUnicodeをコード表の前の文字から順番に、文字列の中に一つ挿入して、文字列を組み立てていきます。
文字が出てきた順でなく、文字コードの順番になっています。
3. レシピの仕組みと圧縮効率
例えば、「12345」というASCIIに「とまと」という文字を挿入した「1と2ま34と5」についてみてみます。
「1と2ま34と5」を作るには、
「まず1つ目の『と』を挿入し、
続けて2つ目の『と』を挿入し、
最後に『ま』を挿入する」
というレシピで文字列が完成しています。
punycode | 文字列 |
---|---|
xn--12345-pc4d | 1と2345 |
xn--12345-pc4dd | 1と234と5 |
xn--12345-pc4dd7o | 1と2ま34と5 |
こんなややこしい仕組みですが、実は単純に一文字ずつ変換するより効率的なんです。
実際に一文字ずつ変換する「URLエンコード」と比較してみます。
文字列 | 1と2ま34と5 | ちいLabo |
---|---|---|
punycode3 | xn–12345-pc4dd7o | xn–labo-453crg |
URLエンコード4 | 1%E3%81%A82%E3%81%BE34%E3%81%A85 | %E3%81%A1%E3%81%84Labo |
確かに、Punycodeの方が短い文字数でコード変換できています。
こちらもどうぞ。
(補足)
- JPRS用語辞典|Punycode(ピュニコード)
- 日本語JPドメイン名のPunycode変換・逆変換 – 日本語.jp
- 日本語JPドメイン名のPunycode変換・逆変換 – 日本語.jp
- URLエンコード・デコード|日本語URLをサクッと変換 | すぐに使える便利なWEBツール | Tech-Unlimited