読者です 読者をやめる 読者になる 読者になる

Pythonでもオレオレ文字コードを実装したい (2)

符号化文字集合文字符号化方式

符号化文字集合を定義する前に符号化文字集合文字符号化方式について簡単に触れます。

符号化文字集合

コンピュータで扱う文字を取りまとめ、各文字に一意な符号を割り当てたものです。 ここで注意すべき点は、文字とは特定の字の形(グリフ)の事ではなく概念的な物であるということです。 手書きの字ですと書き手よってさまざまな形がありますしコンピュータや印刷物ではさまざまな色やデザインがありますが、そのような見た目によって区別されるものではない意味や骨格としての区別される物を文字と呼んでいます。*1*2

符号化文字集合を定義した時点では各文字に一意な符号を割り当てただけで具体的にどのようなバイト列として表現されるかはまだ定義されていません。それを定義するのが文字符号化方式です。

規格としての符号化文字集合には

  • ISO/IEC 646 Information technology - ISO 7-bit coded character set for information interchange *3
  • ISO/IEC 10646 Information technology - Universal Coded Character Set *4
  • JIS X 0201 7ビット及び8ビットの情報交換用符号化文字集合
  • JIS X 0208 7ビット及び8ビットの2バイト情報交換用符号化漢字集合

などがあります。

(追記)JIS X 0201とX 0208では用語の定義として『文字の集合を定め、文字とビット組み合わせとを一意に対応付けるもの』を符号化文字集合として定義していました。その定義ですとここでの文字符号化方式も符号化文字集合に含まれることになります。

文字符号化方式

符号化文字集合で文字に割り当てられた符号を具体的なバイト列に変換したり、逆にバイト列を符号に変換する方法を文字符号化方式で定義します。

符号化文字集合の符号をそのまま16進数に変換するだけの単純なものや、符号の位置によって当該符号の変換されるバイト数が変わる物など様々なものがあります。

余談ですが、「全角の日本語は2バイトである」という言葉を耳にしたことがあるかもしれません。 これはShift_JISで符号化した場合はその通りなのですが、他の符号化方式では事情が変わります。 UFT-8では漢字だろうが半角カタカナだろうが3バイトで表現されますし*5、UFT-16ではアルファベットだろうが漢字だろうが2バイトで表現されます*6

符号化文字集合の定義

ロードマップに従って、まずは符号化文字集合を定義しましょう。

(某3分間で完成させる料理番組のように)こちらに定義済みの符号化文字集合を用意しました。

意味 対応するUnicodeスカラ値 備考
0 0 NUL U+0000 ヌル文字
0 1 LF U+000A ラインフォワード
0 2 CR U+000D キャレッジリターン
1 0 SP U+0020 いわゆる半角スペース
1 1 A U+0041
1 2 B U+0042
1 3 C U+0043
1 4 D U+0044
1 5 E U+0045
1 6 F U+0046
1 7 G U+0047
1 8 H U+0048
1 9 I U+0049
1 10 J U+004A
1 11 K U+004B
1 12 L U+004C
1 13 M U+004D
1 14 N U+004E
1 15 O U+004F
2 0 P U+0050
2 1 Q U+0051
2 2 R U+0052
2 3 S U+0053
2 4 T U+0054
2 5 U U+0055
2 6 V U+0056
2 7 W U+0057
2 8 X U+0058
2 9 Y U+0059
2 10 Z U+005A
2 11 a U+0061
2 12 b U+0062
2 13 c U+0063
2 14 d U+0064
2 15 e U+0065
3 0 f U+0066
3 1 g U+0067
3 2 h U+0068
3 3 i U+0069
3 4 j U+006A
3 5 k U+006B
3 6 l U+006C
3 7 m U+006D
3 8 n U+006E
3 9 o U+006F
3 10 p U+0070
3 11 q U+0071
3 12 r U+0072
3 13 s U+0073
3 14 t U+0074
3 15 u U+0075
4 0 v U+0076
4 1 w U+0077
4 2 x U+0078
4 3 y U+0079
4 4 z U+007A
5 0 IDSP U+3000 いわゆる全角スペース
5 1 U+3041
5 2 U+3042
5 3 U+3043
5 4 U+3044
5 5 U+3045
5 6 U+3046
5 7 U+3047
5 8 U+3048
5 9 U+3049
5 10 U+304A
5 11 U+304B
5 12 U+304C
5 13 U+304D
5 14 U+304E
5 15 U+304F
6 0 U+3050
6 1 U+3051
6 2 U+3052
6 3 U+3053
6 4 U+3054
6 5 U+3055
6 6 U+3056
6 7 U+3057
6 8 U+3058
6 9 U+3059
6 10 U+305A
6 11 U+305B
6 12 U+305C
6 13 U+305D
6 14 U+305E
6 15 U+305F
7 0 U+3060
7 1 U+3061
7 2 U+3062
7 3 U+3063
7 4 U+3064
7 5 U+3065
7 6 U+3066
7 7 U+3067
7 8 U+3068
7 9 U+3069
7 10 U+306A
7 11 U+306B
7 12 U+306C
7 13 U+306D
7 14 U+306E
7 15 U+306F
8 0 U+3070
8 1 U+3071
8 2 U+3072
8 3 U+3073
8 4 U+3074
8 5 U+3075
8 6 U+3076
8 7 U+3077
8 8 U+3078
8 9 U+3079
8 10 U+307A
8 11 U+307B
8 12 U+307C
8 13 U+307D
8 14 U+307E
8 15 U+307F
9 0 U+3080
9 1 U+3081
9 2 U+3082
9 3 U+3083
9 4 U+3084
9 5 U+3085
9 6 U+3086
9 7 U+3087
9 8 U+3088
9 9 U+3089
9 10 U+308A
9 11 U+308B
9 12 U+308C
9 13 U+308D
9 14 U+308E
9 15 U+308F
10 0 U+3090
10 1 U+3091
10 2 U+3092
10 3 U+3093

今回は「区」及び「点」の二次元で表現する符号化文字集合を考えます。 1つの区に16の点が含まれ、その区が16個集まり集合全体を表します。 集合全体では16×16の256の区点位置が存在します。

0区には申し訳程度の制御文字が位置しており、1区0点にはいわゆる半角スペース、1区1点からアルファベットが並んでいます。 同様の形で5区0点にいわゆる全角スペース、5区1点からひらがなが並んでいます。

表では文字のとなりにU+で始まる符号が記述されてますが、これは当該文字に対応しているUnicodeの文字の符号(Unicodeスカラ値)を表しています。 このオレオレ文字コードUnicode間の変換にはこの対応表を用います。 アルファベットやひらがなの対応しているUnicodeスカラ値がきれいに並んでいる所に確信犯的な何かを感じますが、気のせいだという事でなんとか。

ちなみに割り当てられていない区点位置が100以上ありますので、よかったら各自好きな文字を入れてみてください。*7 世間で流通する符号化文字集合の空いてる符号位置に勝手に文字を当てはめたら顰蹙を買いますが、自分だけで使うオレオレ文字コードなのでここでは気にしなくても大丈夫です。*8

文字符号化方式

次に文字符号化方式を定義して符号化文字集合で文字に割り当てた符号を実際のバイト列に変換する方法を考えます。

(とても白々しく)あれ、そういえば区の数は16個でそれぞれの区に含まれる点の数も16個ですね。 ということは区と点を組み合わせたものはきれいに1バイトにおさまりますね。

ということで今回は区を上位4ビットに、点を下位4ビットとして実際のバイト列に変換します。 たとえば「あ」でしたら0x51、「わ」でしたら0x9Fといった具合です。 8ビットの文字符号化方式です。

すごいあっさりしていますが、これで文字符号化方式も決まりましたので次回からプログラムを書いていきます。

おまけ

ひらがなだけとはいえ、日本語が1バイトで表現可能な文字コードが爆誕しました。 え? JIS X 0201? まぁ、濁点が合成済みのひらがなが扱えるってことで許してヒヤシンス。

最初はASCII文字集合の部分は互換性を持たせようとか、意味なくマルチバイト文字符号化方式にしようかとか考えていましたが先に軽くPythonのコードを眺めたところマルチバイト文字符号化方式ですとプログラムがヤバいことになりそうなのと、ほとんど使われない制御文字に符号位置を割り振るのもあまり気のりしなかったのと、あとは妥協でこのような形になりました。

ASCIIで制御文字にあたる場所にアルファベットが配置されているので誤ってコンソールに出力しようものなら素敵なことになるのは目に見えていますがテキストファイエンコードスキームってことでよろしくお願いいたします。

*1:逆に形や色などの具体的なデザインとして表現されるものをグリフと呼びます。

*2:異体字とか包摂とかの絡みもありますが、今回定義する符号化文字集合には漢字は含まれていないのでスルーします。

*3:ISO/IEC 646では符号化文字集合文字符号化方式の明確に区別していない。

*4:ISO/IEC 10646は符号化文字集合文字符号化方式の両方を含んだ規格となっている。

*5:文字によっては4バイトになる場合もあります。

*6:文字によっては4バイトになる場合もあります。

*7:君だけの文字を集めて最強の符号化文字集合を作ろう!!

*8:もしもあなたが今回作成した符号化文字集合を標準化しようとするなら話は別ですが。