Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14260] ファイルの概要

このコミットは、Go言語の標準ライブラリであるstrconvパッケージ内のisprint.goファイルを更新し、Unicodeのバージョンを6.2.0に準拠させるものです。これにより、文字の「表示可能 (printable)」判定ロジックが最新のUnicode標準に合わせられ、ビルドの問題も修正されています。

コミット

commit a90b3a5528bd366995eb76acc8811a7a3caf45aa
Author: Rob Pike <r@golang.org>
Date:   Wed Oct 31 10:11:04 2012 -0700

    strconv: update to unicode 6.2.0
    Fixes build, too.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/6775088

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/a90b3a5528bd366995eb76acc8811a7a3caf45aa

元コミット内容

strconv: update to unicode 6.2.0 Fixes build, too.

変更の背景

このコミットの主な背景は、Go言語のstrconvパッケージが使用するUnicodeの文字プロパティデータが古くなっていたことです。strconvパッケージは文字列と数値の変換を行うための機能を提供しますが、その中には文字が「表示可能 (printable)」であるかどうかの判定を行う関数(例: IsPrint)が含まれています。この判定は、ターミナル出力やログ出力などにおいて、非表示文字や制御文字が意図せず表示されることを防ぐために重要です。

Unicodeは継続的に新しい文字やプロパティを追加・修正しており、Go言語が最新の文字セットを正しく扱えるようにするためには、定期的にUnicodeデータベースを更新する必要があります。Unicode 6.2.0は、2012年9月26日にリリースされたバージョンであり、このコミットはその変更をGoのstrconvパッケージに反映させるものです。

また、コミットメッセージには「Fixes build, too.」とあり、Unicodeデータの不整合が何らかのビルドエラーを引き起こしていた可能性も示唆されています。これは、古いUnicodeデータが新しいコンパイラや環境と互換性がなかったり、特定の文字処理ロジックに影響を与えたりした結果かもしれません。

前提知識の解説

Unicodeとは

Unicodeは、世界中のあらゆる文字をコンピュータで扱うための文字コードの国際標準です。各文字には一意の「コードポイント」が割り当てられており、これにより異なる言語やシステム間での文字の互換性が保証されます。Unicodeはバージョンアップを重ねており、新しい文字の追加や既存の文字プロパティの変更が行われます。

strconvパッケージとは

Go言語の標準ライブラリであるstrconvパッケージは、「string conversion」の略で、文字列と基本的なデータ型(整数、浮動小数点数、真偽値など)との間で相互変換を行うための機能を提供します。例えば、Atoi(文字列を整数に変換)、Itoa(整数を文字列に変換)、ParseBoolFormatFloatなどの関数があります。

このパッケージには、文字が「表示可能 (printable)」であるかを判定するIsPrint関数も含まれています。この関数は、主にデバッグ出力やユーザーインターフェースにおいて、制御文字や非表示文字が誤って表示されることを防ぐために利用されます。

表示可能文字 (Printable Characters)

「表示可能文字」とは、通常、画面やプリンターに出力された際に視覚的に表現される文字のことを指します。これには、アルファベット、数字、記号、句読点などが含まれます。一方、改行、タブ、NULL文字などの制御文字や、特定の書式設定を行うための非表示文字は、通常「表示可能」とは見なされません。

strconvパッケージのIsPrint関数は、内部的にUnicodeの文字プロパティデータベースを参照し、与えられたルーン(GoにおけるUnicodeコードポイント)が表示可能であるかを判定します。このデータベースは、isprint.goファイル内のisPrint16, isNotPrint16, isPrint32, isNotPrint32といった配列で表現されています。これらの配列は、特定のコードポイント範囲が表示可能であるか、または表示可能ではないかを示しています。

Go言語における文字と文字列

Go言語では、文字列はUTF-8エンコードされたバイトのシーケンスとして扱われます。個々の文字は「ルーン (rune)」と呼ばれ、これはUnicodeのコードポイントに対応するint32型のエイリアスです。Goの文字列処理は、UTF-8の特性を考慮して設計されており、多言語対応が容易になっています。

技術的詳細

このコミットの技術的な核心は、src/pkg/strconv/isprint.goファイル内のUnicode文字範囲定義の更新です。このファイルは、strconv.IsPrint関数が文字が表示可能かどうかを判断するために使用する静的なデータテーブルを含んでいます。

具体的には、以下の配列が更新されています。

  • isPrint16: 16ビット(U+0000からU+FFFF)の範囲で表示可能なUnicodeコードポイントの範囲を定義するuint16のペアの配列。
  • isNotPrint16: 16ビットの範囲で表示可能ではない(しかし、isPrint16の範囲に含まれる可能性がある)特定のUnicodeコードポイントを定義するuint16の配列。これは、例外的な非表示文字をマークするために使用されます。
  • isPrint32: 32ビット(U+10000以上)の範囲で表示可能なUnicodeコードポイントの範囲を定義するuint32のペアの配列。
  • isNotPrint32: 32ビットの範囲で表示可能ではない特定のUnicodeコードポイントを定義するuint16の配列(ただし、実際にはuint32のコードポイントを表すために0x10000が加算される)。

Unicode 6.2.0への更新に伴い、これらの配列内のコードポイントの範囲が修正されています。これは、Unicode標準で新しく定義された文字、既存の文字のプロパティ変更、または以前のバージョンで誤って分類されていた文字の修正などによるものです。

例えば、差分を見ると、isPrint16配列では0x0591, 0x05c70x058f, 0x05c7に変更されたり、0x1780, 0x17b30x17b6, 0x17dd0x1780, 0x17ddに統合されたりしています。これは、特定のスクリプト(例: ヘブライ語、クメール語)における文字の表示可能性の定義が変更されたことを示唆しています。

また、isPrint32配列では、より高位のコードポイント(サロゲートペアや追加多言語面など)に関する変更が見られます。例えば、0x010980から始まる新しい範囲が追加されています。

これらの変更は、strconv.IsPrint関数が、最新のUnicode標準に準拠した正確な表示可能文字の判定を行えるようにするために不可欠です。これにより、Goアプリケーションが様々な言語や記号を含むテキストを扱う際に、より堅牢で期待通りの動作をするようになります。

ファイル冒頭のコメント// (474+134+42)*2 + (180)*4 = 2020 bytes// (470+136+60)*2 + (218)*4 = 2204 bytesに変わっているのは、これらの配列の要素数が増減した結果、データ構造全体のサイズが変化したことを示しています。これは、Unicode 6.2.0で追加された文字や変更されたプロパティによって、表示可能/非表示可能の範囲定義が増えたことを反映しています。

コアとなるコードの変更箇所

変更はすべて src/pkg/strconv/isprint.go ファイル内で行われています。

--- a/src/pkg/strconv/isprint.go
+++ b/src/pkg/strconv/isprint.go
@@ -3,7 +3,7 @@
 
  package strconv
  
-// (474+134+42)*2 + (180)*4 = 2020 bytes
+// (470+136+60)*2 + (218)*4 = 2204 bytes
 
  var isPrint16 = []uint16{
  	0x0020, 0x007e,
@@ -12,7 +12,7 @@ var isPrint16 = []uint16{
  	0x0384, 0x0527,
  	0x0531, 0x0556,
  	0x0559, 0x058a,
-\t0x0591, 0x05c7,
+\t0x058f, 0x05c7,
  	0x05d0, 0x05ea,
  	0x05f0, 0x05f4,
  	0x0606, 0x061b,
@@ -23,7 +23,8 @@ var isPrint16 = []uint16{
  	0x0800, 0x082d,
  	0x0830, 0x085b,
  	0x085e, 0x085e,
-\t0x0900, 0x098c,
+\t0x08a0, 0x08ac,
+\t0x08e4, 0x098c,
  	0x098f, 0x0990,
  	0x0993, 0x09b2,
  	0x09b6, 0x09b9,
@@ -99,12 +100,12 @@ var isPrint16 = []uint16{
  	0x0eaa, 0x0ebd,
  	0x0ec0, 0x0ecd,
  	0x0ed0, 0x0ed9,
-\t0x0edc, 0x0edd,
+\t0x0edc, 0x0edf,
  	0x0f00, 0x0f6c,
  	0x0f71, 0x0fda,
-\t0x1000, 0x10c5,
-\t0x10d0, 0x10fc,
-\t0x1100, 0x124d,
+\t0x1000, 0x10c7,
+\t0x10cd, 0x10cd,
+\t0x10d0, 0x124d,
  	0x1250, 0x125d,
  	0x1260, 0x128d,
  	0x1290, 0x12b5,
@@ -120,8 +121,7 @@ var isPrint16 = []uint16{
  	0x1720, 0x1736,
  	0x1740, 0x1753,
  	0x1760, 0x1773,
-\t0x1780, 0x17b3,
-\t0x17b6, 0x17dd,
+\t0x1780, 0x17dd,
  	0x17e0, 0x17e9,
  	0x17f0, 0x17f9,
  	0x1800, 0x180d,
@@ -145,13 +145,12 @@ var isPrint16 = []uint16{
  	0x1aa0, 0x1aad,
  	0x1b00, 0x1b4b,
  	0x1b50, 0x1b7c,
-\t0x1b80, 0x1baa,
-\t0x1bae, 0x1bb9,
-\t0x1bc0, 0x1bf3,
+\t0x1b80, 0x1bf3,
  	0x1bfc, 0x1c37,
  	0x1c3b, 0x1c49,
  	0x1c4d, 0x1c7f,
-\t0x1cd0, 0x1cf2,
+\t0x1cc0, 0x1cc7,
+\t0x1cd0, 0x1cf6,
  	0x1d00, 0x1de6,
  	0x1dfc, 0x1f15,
  	0x1f18, 0x1f1d,
@@ -165,7 +164,7 @@ var isPrint16 = []uint16{
  	0x2030, 0x205e,
  	0x2070, 0x2071,
  	0x2074, 0x209c,
-\t0x20a0, 0x20b9,
+\t0x20a0, 0x20ba,
  	0x20d0, 0x20f0,
  	0x2100, 0x2189,
  	0x2190, 0x23f3,
@@ -173,12 +172,13 @@ var isPrint16 = []uint16{
  	0x2440, 0x244a,
  	0x2460, 0x2b4c,
  	0x2b50, 0x2b59,
-\t0x2c00, 0x2cf1,
-\t0x2cf9, 0x2d25,
-\t0x2d30, 0x2d65,
+\t0x2c00, 0x2cf3,
+\t0x2cf9, 0x2d27,
+\t0x2d2d, 0x2d2d,
+\t0x2d30, 0x2d67,
  	0x2d6f, 0x2d70,
  	0x2d7f, 0x2d96,
-\t0x2da0, 0x2e31,
+\t0x2da0, 0x2e3b,
  	0x2e80, 0x2ef3,
  	0x2f00, 0x2fd5,
  	0x2ff0, 0x2ffb,
@@ -188,16 +188,15 @@ var isPrint16 = []uint16{
  	0x3131, 0x31ba,
  	0x31c0, 0x31e3,
  	0x31f0, 0x4db5,
-\t0x4dc0, 0x9fcb,
+\t0x4dc0, 0x9fcc,
  	0xa000, 0xa48c,
  	0xa490, 0xa4c6,
  	0xa4d0, 0xa62b,
-\t0xa640, 0xa673,
-\t0xa67c, 0xa697,
-\t0xa6a0, 0xa6f7,
-\t0xa700, 0xa791,
-\t0xa7a0, 0xa7a9,
-\t0xa7fa, 0xa82b,
+\t0xa640, 0xa697,
+\t0xa69f, 0xa6f7,
+\t0xa700, 0xa793,
+\t0xa7a0, 0xa7aa,
+\t0xa7f8, 0xa82b,
  	0xa830, 0xa839,
  	0xa840, 0xa877,
  	0xa880, 0xa8c4,
@@ -212,7 +211,7 @@ var isPrint16 = []uint16{
  	0xaa50, 0xaa59,
  	0xaa5c, 0xaa7b,
  	0xaa80, 0xaac2,
-\t0xaadb, 0xaadf,
+\t0xaadb, 0xaaf6,
  	0xab01, 0xab06,
  	0xab09, 0xab0e,
  	0xab11, 0xab16,
@@ -222,8 +221,7 @@ var isPrint16 = []uint16{
  	0xac00, 0xd7a3,
  	0xd7b0, 0xd7c6,
  	0xd7cb, 0xd7fb,
-\t0xf900, 0xfa2d,
-\t0xfa30, 0xfa6d,
+\t0xf900, 0xfa6d,
  	0xfa70, 0xfad9,
  	0xfb00, 0xfb06,
  	0xfb13, 0xfb17,
@@ -252,8 +250,11 @@ var isNotPrint16 = []uint16{\n  	0x03a2,\n  	0x0560,\n  	0x0588,\n+\t0x0590,\n  	0x06dd,\n  	0x083f,\n+\t0x08a1,\n+\t0x08ff,\
  	0x0978,\n  	0x0980,\n  	0x0984,\
@@ -275,7 +276,6 @@ var isNotPrint16 = []uint16{\n  	0x0ab4,\n  	0x0ac6,\n  	0x0aca,\n-\t0x0af0,\
  	0x0b04,\n  	0x0b29,\n  	0x0b31,\
@@ -327,6 +327,7 @@ var isNotPrint16 = []uint16{\n  	0x0f98,\n  	0x0fbd,\n  	0x0fcd,\n+\t0x10c6,\
  	0x1249,\n  	0x1257,\n  	0x1259,\
@@ -351,10 +352,9 @@ var isNotPrint16 = []uint16{\n  	0x1ff5,\n  	0x208f,\n  	0x2700,\n-\t0x27cb,\
-\t0x27cd,\
  	0x2c2f,\n  	0x2c5f,\
+\t0x2d26,\
  	0x2da7,\n  	0x2daf,\n  	0x2db7,\
@@ -406,6 +406,8 @@ var isPrint32 = []uint32{\n  	0x010900, 0x01091b,\n  	0x01091f, 0x010939,\n  	0x01093f, 0x01093f,\n+\t0x010980, 0x0109b7,\n+\t0x0109be, 0x0109bf,\
  	0x010a00, 0x010a06,\n  	0x010a0c, 0x010a33,\n  	0x010a38, 0x010a3a,\
@@ -421,11 +423,21 @@ var isPrint32 = []uint32{\n  	0x011000, 0x01104d,\n  	0x011052, 0x01106f,\n  	0x011080, 0x0110c1,\n+\t0x0110d0, 0x0110e8,\
+\t0x0110f0, 0x0110f9,\
+\t0x011100, 0x011143,\
+\t0x011180, 0x0111c8,\
+\t0x0111d0, 0x0111d9,\
+\t0x011680, 0x0116b7,\
+\t0x0116c0, 0x0116c9,\
  	0x012000, 0x01236e,\n  	0x012400, 0x012462,\n  	0x012470, 0x012473,\
  	0x013000, 0x01342e,\n  	0x016800, 0x016a38,\
+\t0x016f00, 0x016f44,\
+\t0x016f50, 0x016f7e,\
+\t0x016f8f, 0x016f9f,\
  	0x01b000, 0x01b001,\n  	0x01d000, 0x01d0f5,\n  	0x01d100, 0x01d126,\
@@ -442,13 +454,21 @@ var isPrint32 = []uint32{\n  	0x01d54a, 0x01d6a5,\n  	0x01d6a8, 0x01d7cb,\n  	0x01d7ce, 0x01d7ff,\n+\t0x01ee00, 0x01ee24,\
+\t0x01ee27, 0x01ee3b,\
+\t0x01ee42, 0x01ee42,\
+\t0x01ee47, 0x01ee54,\
+\t0x01ee57, 0x01ee64,\
+\t0x01ee67, 0x01ee9b,\
+\t0x01eea1, 0x01eebb,\
+\t0x01eef0, 0x01eef1,\
  	0x01f000, 0x01f02b,\n  	0x01f030, 0x01f093,\n  	0x01f0a0, 0x01f0ae,\n  	0x01f0b1, 0x01f0be,\n  	0x01f0c1, 0x01f0df,\n  	0x01f100, 0x01f10a,\n-\t0x01f110, 0x01f169,\
+\t0x01f110, 0x01f16b,\
  	0x01f170, 0x01f19a,\n  	0x01f1e6, 0x01f202,\n  	0x01f210, 0x01f23a,\
@@ -461,10 +481,9 @@ var isPrint32 = []uint32{\n  	0x01f3e0, 0x01f3f0,\n  	0x01f400, 0x01f4fc,\n  	0x01f500, 0x01f53d,\n+\t0x01f540, 0x01f543,\
  	0x01f550, 0x01f567,\n-\t0x01f5fb, 0x01f625,\n-\t0x01f628, 0x01f62d,\
-\t0x01f630, 0x01f640,\
+\t0x01f5fb, 0x01f640,\
  	0x01f645, 0x01f64f,\n  	0x01f680, 0x01f6c5,\n  	0x01f700, 0x01f773,\
@@ -489,6 +508,7 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n  	0x0a14,\n  	0x0a18,\n  	0x10bd,\n+\t0x1135,\
  	0xd455,\n  	0xd49d,\n  	0xd4ad,\
@@ -502,6 +522,32 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n  	0xd53f,\n  	0xd545,\n  	0xd551,\n+\t0xee04,\
+\t0xee20,\
+\t0xee23,\
+\t0xee28,\
+\t0xee33,\
+\t0xee38,\
+\t0xee3a,\
+\t0xee48,\
+\t0xee4a,\
+\t0xee4c,\
+\t0xee50,\
+\t0xee53,\
+\t0xee58,\
+\t0xee5a,\
+\t0xee5c,\
+\t0xee5e,\
+\t0xee60,\
+\t0xee63,\
+\t0xee6b,\
+\t0xee73,\
+\t0xee78,\
+\t0xee7d,\
+\t0xee7f,\
+\t0xee8a,\
+\t0xeea4,\
+\t0xeeaa,\
  	0xf0d0,\n  	0xf12f,\n  	0xf336,\
@@ -509,13 +555,4 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n  	0xf43f,\n  	0xf441,\n  	0xf4f8,\n-\t0xf600,\
-\t0xf611,\
-\t0xf615,\
-\t0xf617,\
-\t0xf619,\
-\t0xf61b,\
-\t0xf61f,\
-\t0xf62c,\
-\t0xf634,\
  }\

コアとなるコードの解説

このコミットのコアとなる変更は、isprint.goファイル内のisPrint16, isNotPrint16, isPrint32, isNotPrint32という4つの配列のデータ更新です。これらの配列は、Goのstrconvパッケージが文字の表示可能性を判定するために使用する、Unicodeコードポイントの範囲または個別のコードポイントのリストを保持しています。

  • isPrint16: この配列は、U+0000からU+FFFFまでの範囲で「表示可能」と見なされるUnicodeコードポイントの連続した範囲を[開始コードポイント, 終了コードポイント]のペアで定義しています。例えば、0x0020, 0x007eは、スペース(U+0020)からチルダ(U+007E)までのASCII文字が表示可能であることを示します。このコミットでは、既存の範囲が拡張されたり、新しい範囲が追加されたり、あるいは隣接する範囲が統合されたりしています。これにより、Unicode 6.2.0で新しく表示可能とされた文字や、以前のバージョンで誤って分類されていた文字が正しく扱われるようになります。

  • isNotPrint16: この配列は、isPrint16で定義された広範な表示可能範囲の中に含まれるものの、実際には「表示可能ではない」と見なされる特定の16ビットコードポイントを列挙しています。これは、一般的な範囲定義では捉えきれない、例外的な非表示文字(例えば、特定の制御文字や書式設定文字)を明示的に除外するために使用されます。このコミットでは、Unicode 6.2.0の定義に基づいて、いくつかのコードポイントが追加または削除されています。

  • isPrint32: この配列は、U+10000以上の高位のUnicodeコードポイント(サロゲートペアや追加多言語面など)で「表示可能」と見なされる範囲を[開始コードポイント, 終了コードポイント]のペアで定義しています。基本的な多言語面(BMP)以外の文字セット、例えば絵文字や歴史的なスクリプトなどがこの範囲に含まれます。Unicode 6.2.0では、これらの高位コードポイントにも多くの変更があったため、この配列も大幅に更新されています。

  • isNotPrint32: isNotPrint16と同様に、isPrint32で定義された広範な表示可能範囲の中に含まれるものの、実際には「表示可能ではない」と見なされる特定の32ビットコードポイントを列挙しています。この配列の要素はuint16型ですが、実際のコードポイントは0x10000が加算されて32ビットのコードポイントとして扱われます。このコミットでは、高位コードポイントにおける例外的な非表示文字の定義が更新されています。

これらの配列の更新は、strconv.IsPrint関数が内部的にこれらのデータテーブルを検索し、与えられたルーンが表示可能であるかを効率的に判断するために行われます。Unicode標準の更新は、文字のプロパティ(表示可能性を含む)に影響を与えるため、Go言語が最新の国際的な文字セットを正確に処理するためには、このようなデータ更新が不可欠です。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード(GitHub): https://github.com/golang/go
  • Unicode Consortiumのウェブサイト: https://home.unicode.org/
  • Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/6775088 (コミットメッセージに記載されているChange-Idのリンク)
  • (Web検索結果に基づく)Unicode 6.2.0に関する情報源(例: Wikipedia, Unicodeの公式ドキュメントなど)