【Unicode】UTF-16 サロゲートぺア と コードポイント の変換

UTF-16 は、Unicode の文字をコードポイントと呼ばれる整数値で表現するエンコーディング方式です。UTF-16 では、一部のUnicode 文字は16ビットでは表現できないため、サロゲートペアと呼ばれる特殊な方法で符号化されます。

サロゲートペアは、2つの16ビットの値(上位サロゲートと下位サロゲート)を組み合わせて1つの Unicode 文字を表現します。上位サロゲートは 0xD800-0xDBFF の範囲にあり、下位サロゲートは 0xDC00-0xDFFF の範囲にあります。

Wikipedia で調べると数式があります。

【Unicode】UTF-16 サロゲートぺア と コードポイント の変換
👉 Unicode - Wikipedia hatena-bookmark


code-point <-> surrogate-pair

これに合わせて Python コードにしてみました。


def cp_to_sp(cp):
    cp -= 0x10000
    hsg = cp // 0x400 + 0xD800
    lsg = cp % 0x400 + 0xDC00
    return hsg, lsg


def sp_to_cp(hsg, lsg):
    cp = 0x10000 + (hsg - 0xD800) * 0x400 + (lsg - 0xDC00)
    return cp

この関数を、みんな大好き絵文字「👍」で試してみます。


👉 GitHub Emoji Unicode Full Emoji List - shortcode | code point | escape-sequence hatena-bookmark

表にあるデータから、コードポイントとサロゲートペアのそれぞれの値を使います。


cp = 0x1f44d
hsg, lsg = cp_to_sp(cp)
print(hex(hsg), hex(lsg))
# 0xd83d 0xdc4d

hsg = 0xd83d
lsg = 0xdc4d
cp = sp_to_cp(hsg, lsg)
print(hex(cp))
# 0x1f44d

うまくいってます。

 

👍 まとめ

Unicode まわりは CJK のおかげでか、ややこしいことになってます。

UTF-16などのエンコード処理を扱う場合、コード内では「コードポイント」を中心にを進めると幸せになることがよくあります。


👉 Python vs Kotlin Unicode Escape Sequence (エスケープシーケンス) の記述 hatena-bookmark


GitHub Emoji Unicode Full Emoji List - shortcode | code point | escape-sequence

絵文字の「ショートコード」は各プラットフォームごとに異なるので困ったものです。

GitHub でショートコードが用意されている絵文字は、最新の Unicode 絵文字バージョンではないようですが、Facebook、Twitter など大手プラットフォームで直接を生貼りでも問題なく使えるような雰囲気です。

👉 Emojis - GitHub Docs




「GitHub ショートコード」と「Unicode コードポイント」、「Unicode エスケープシーケンス」をスクリプトで一覧にして書き出しておきます。

一番左の「emoji」カラムは絵文字クリックから Emojipedia に飛べます。




👉 Python vs Kotlin Unicode Escape Sequence (エスケープシーケンス) の記述 hatena-bookmark


テキストアニメーションで Progress Indicator

久しぶりに使ってみたら進化していました。

👉 【KMM】KDoctor って生きてるの? hatena-bookmark

こんな経過表示。

progressSymbols

おされなのでコードを見てみます。


private val progressSymbols = listOf("⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾")
private fun ProducerScope<String>.showDiagnosticProgress(title: String) = launch {
    var progressIndex = 0
    while (isActive) {
        progressIndex = (progressIndex + 1) % progressSymbols.size
        val symbol = progressSymbols[progressIndex]
        send("\r[$symbol] $title")
        delay(60)
    }
}

👉 kdoctor/Doctor.kt at master · Kotlin/kdoctor · GitHub hatena-bookmark


"⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾"

点字用の文字を使ってアニメーションにしているようです。

👉 Braille pattern dots-12456 - Wikipedia hatena-bookmark

bash にしてみます。


Text Animation using Braille pattern dots

かわいいです!

\r (キャリッジリターン) ってこんな使い方があるんですね!

👉 キャリッジ・リターン - Wikipedia hatena-bookmark