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

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

このコミットは、Go言語の実験的な正規化パッケージ exp/norm における内部データ構造 runeInfoProperties というより汎用的な名前に変更し、さらにルーン(Unicodeコードポイント)の「Canonical Combining Class (CCC)」をAPIとして公開するものです。これにより、Unicode正規化処理におけるルーンの特性情報へのアクセスが改善され、より完全な情報提供が可能になります。

コミット

commit 98aa4968b7f7fbbac2baba99c508d72d4f4ce883
Author: Marcel van Lohuizen <mpvl@golang.org>
Date:   Wed Apr 11 16:47:53 2012 +0200

    exp/norm: exposed runeInfo type in API.
    For completeness, we also expose the Canonical Combining Class of a rune.
    This does not increase the data size.
    
    R=r
    CC=golang-dev
    https://golang.org/cl/5931043

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

https://github.com/golang/go/commit/98aa4968b7f7fbbac2baba99c508d72d4f4ce883

元コミット内容

exp/norm: exposed runeInfo type in API. For completeness, we also expose the Canonical Combining Class of a rune. This does not increase the data size.

このコミットメッセージは、exp/norm パッケージにおいて runeInfo 型をAPIとして公開したこと、そしてルーンのCanonical Combining Class (CCC) も公開したことを示しています。データサイズは増加しないと明記されています。

変更の背景

Unicodeの正規化処理(NFC, NFD, NFKC, NFKDなど)は、異なるバイト列で表現されうる同じ意味を持つ文字列を統一するための重要なプロセスです。この処理において、各ルーンが持つ特性情報、特に結合文字の順序を決定するCanonical Combining Class (CCC) は不可欠です。

以前の exp/norm パッケージでは、これらのルーン特性を runeInfo という内部構造体で管理していました。しかし、この runeInfo はパッケージ内部でのみ使用されており、外部からルーンの正規化特性にアクセスする手段が限られていました。

このコミットの背景には、以下の目的があったと考えられます。

  1. APIの改善と情報公開の促進: runeInfo が持つルーンの正規化に関する詳細な情報を、より適切で汎用的な名前 (Properties) で外部に公開することで、パッケージの利用者がルーンの特性を直接取得し、より高度な正規化関連の処理を実装できるようにする。
  2. Canonical Combining Class (CCC) の明示的な公開: Unicode正規化において非常に重要なCCC情報を、明示的にAPIとして提供することで、結合文字の並べ替えやセグメンテーションなどの処理を正確に行うための基盤を強化する。これにより、開発者はUnicodeの複雑なルールをより容易に扱うことができるようになる。
  3. データサイズの維持: 新しいAPIの導入や情報公開が、既存のデータ構造やメモリ使用量に悪影響を与えないことを保証する。コミットメッセージにある「This does not increase the data size」という記述は、この点への配慮を示しています。

これらの変更により、exp/norm パッケージはより堅牢で、かつ利用しやすいUnicode正規化ライブラリへと進化することが期待されます。

前提知識の解説

Unicode正規化 (Unicode Normalization)

Unicodeには、同じ文字や文字列が複数の異なるバイト列で表現されうるという特性があります。例えば、é という文字は、単一のコードポイント U+00E9 (LATIN SMALL LETTER E WITH ACUTE) で表現することもできますし、e (U+0065) と ´ (U+0301, COMBINING ACUTE ACCENT) の2つのコードポイントの組み合わせで表現することもできます。これらは視覚的には同じですが、バイト列としては異なります。

このような問題を解決し、文字列の比較や検索を正確に行うために、Unicode標準では「正規化 (Normalization)」という概念が導入されています。正規化は、特定のアルゴリズムに従って文字列を統一的な形式に変換するプロセスです。

Unicode正規化には主に以下の4つの形式があります。

  • NFC (Normalization Form Canonical Composition): 結合文字を可能な限り合成して、最短の形式にする。
  • NFD (Normalization Form Canonical Decomposition): 結合文字を可能な限り分解して、最長の形式にする。
  • NFKC (Normalization Form Compatibility Composition): 互換性文字(例えば、全角数字と半角数字)も考慮して合成する。
  • NFKD (Normalization Form Compatibility Decomposition): 互換性文字も考慮して分解する。

Canonical Combining Class (CCC)

Canonical Combining Class (CCC) は、Unicodeの各コードポイントに割り当てられた数値プロパティです。この値は、結合文字(アクセント記号、ダイアクリティカルマークなど)が基本文字に対してどのように配置されるべきか、また複数の結合文字が連続する場合にどのような順序で並べられるべきかを決定するために使用されます。

CCCは0から254までの値を取り、以下のような意味を持ちます。

  • CCC = 0: 非結合文字(基本文字など)。
  • CCC > 0: 結合文字。値が大きいほど、基本文字から離れた位置に配置される傾向があります。

正規化アルゴリズムでは、CCCの値に基づいて結合文字の並べ替え(Canonical Ordering)が行われます。これにより、異なるバイト列で表現された同じ意味の文字列が、正規化によって同じバイト列に変換されることが保証されます。例えば、e + ´´ + e は、CCCに基づいて e + ´ の順序に並べ替えられ、最終的に同じ正規化された形式になります。

Go言語の exp/norm パッケージ

exp/norm は、Go言語の標準ライブラリの一部として提供される前の、Unicode正規化機能の実験的なパッケージです。このパッケージは、Unicode標準で定義されている正規化形式(NFC, NFD, NFKC, NFKD)をGoプログラムで扱うための機能を提供します。文字列の正規化、ルーンごとの特性情報の取得、結合文字の処理などが含まれます。

このパッケージは、Unicodeの複雑なルールをGo言語で効率的かつ正確に実装するために、内部的にTRIEデータ構造や様々な最適化技術を使用しています。

技術的詳細

このコミットの主要な技術的変更点は以下の通りです。

  1. runeInfo から Properties への型名変更と公開:

    • 以前は内部的に runeInfo という名前でルーンの正規化特性(UTF-8エンコーディングサイズ、Canonical Combining Class (CCC)、分解情報へのインデックス、クイックチェックフラグなど)を保持していました。
    • このコミットでは、runeInfo 型が Properties というより汎用的な名前に変更され、パッケージの外部からアクセス可能な型として公開されました。これにより、利用者はルーンの正規化に関する詳細な情報を直接取得できるようになります。
    • Properties 構造体は、pos (reorderBuffer内の開始位置), size (UTF-8エンコーディングサイズ), ccc (Canonical Combining Class), tccc (分解後の末尾ルーンのCCC), flags (クイックチェックや結合に関するフラグ), index (分解情報へのインデックス) などのフィールドを持ちます。
  2. Canonical Combining Class (CCC) の明示的な公開:

    • Properties 型に CCC() メソッドが追加され、ルーンのCanonical Combining Classを直接取得できるようになりました。
    • また、LeadCCC()TrailCCC() メソッドも追加され、分解後の先頭ルーンと末尾ルーンのCCCも取得できるようになりました。これにより、結合文字の並べ替えやセグメンテーション処理において、より正確な情報に基づいた判断が可能になります。
  3. 既存コードベースの更新:

    • src/pkg/exp/norm/composition.go, src/pkg/exp/norm/forminfo.go, src/pkg/exp/norm/iter.go, src/pkg/exp/norm/normalize.go などのファイルで、runeInfo 型を使用していた箇所がすべて Properties 型に置き換えられました。
    • hasDecomposition() メソッドが Decomposition() メソッドに、boundaryBefore()BoundaryBefore() に、boundaryAfter()BoundaryAfter() に変更されるなど、一部のメソッド名も公開APIとしての命名規則に合わせて変更されました。
    • maketables.go では、CCCに関する新しい定数 firstCCCZeroExcept が追加され、テーブル生成ロジックが更新されました。これにより、CCCが0である例外的なケースがより正確に扱われるようになります。

これらの変更は、exp/norm パッケージが提供するUnicode正規化機能の正確性と使いやすさを向上させることを目的としています。特に、CCCの明示的な公開は、Unicodeの複雑なテキスト処理をGo言語で行う開発者にとって大きなメリットとなります。

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

このコミットでは、主に以下のファイルが変更されています。

  • src/pkg/exp/norm/composition.go: reorderBuffer 構造体の rune フィールドの型が runeInfo から Properties に変更され、関連するメソッドの引数や戻り値の型も更新されています。
  • src/pkg/exp/norm/forminfo.go: runeInfo 型が Properties 型にリネームされ、その定義が変更されています。また、Properties 型に BoundaryBefore(), BoundaryAfter(), Decomposition(), Size(), CCC(), LeadCCC(), TrailCCC() などの新しい公開メソッドが追加されています。
  • src/pkg/exp/norm/iter.go: Iter 構造体の info フィールドの型が runeInfo から Properties に変更され、関連するメソッドの呼び出しも更新されています。
  • src/pkg/exp/norm/maketables.go: テーブル生成ロジックが更新され、CCCに関する新しい定数 firstCCCZeroExcept が追加されています。
  • src/pkg/exp/norm/normalize.go: runeInfo 型を使用していた箇所が Properties 型に置き換えられ、新しいメソッドの呼び出しに修正されています。
  • src/pkg/exp/norm/tables.go: 新しい定数 firstCCCZeroExcept が追加されています。

コアとなるコードの解説

src/pkg/exp/norm/forminfo.go における Properties 型の定義とメソッド

// Properties provides access to normalization properties of a rune.
type Properties struct {
	pos   uint8  // start position in reorderBuffer; used in composition.go
	size  uint8  // length of UTF-8 encoding of this rune
	ccc   uint8  // leading canonical combining class (ccc if not decomposition)
	tccc  uint8  // trailing canonical combining class (ccc of last rune in decomposition)
	flags qcInfo  // quick check flags
	index uint16 // index into decomposition table
}

// BoundaryBefore returns true if this rune starts a new segment and
// cannot combine with any rune on the left.
func (p Properties) BoundaryBefore() bool {
	if p.ccc == 0 && !p.combinesBackward() {
		return true
	}
	// We assume that the CCC of the first character in a decomposition
	// is 0.
	return false
}

// BoundaryAfter returns true if this rune cannot combine with runes to the right
// and always denotes the end of a segment.
func (p Properties) BoundaryAfter() bool {
	return p.isInert()
}

// Decomposition returns the decomposition for the underlying rune
// or nil if there is none.
func (p Properties) Decomposition() []byte {
	if p.index == 0 {
		return nil
	}
	i := p.index
	n := decomps[i] & headerLenMask
	i++
	return decomps[i : i+uint16(n)]
}

// Size returns the length of UTF-8 encoding of the rune.
func (p Properties) Size() int {
	return int(p.size)
}

// CCC returns the canonical combining class of the underlying rune.
func (p Properties) CCC() uint8 {
	if p.index > firstCCCZeroExcept {
		return 0
	}
	return p.ccc
}

// LeadCCC returns the CCC of the first rune in the decomposition.
// If there is no decomposition, LeadCCC equals CCC.
func (p Properties) LeadCCC() uint8 {
	return p.ccc
}

// TrailCCC returns the CCC of the last rune in the decomposition.
// If there is no decomposition, TrailCCC equals CCC.
func (p Properties) TrailCCC() uint8 {
	return p.tccc
}

このコードスニペットは、Properties 型の新しい定義と、それに追加された主要な公開メソッドを示しています。

  • Properties 構造体: ルーンの正規化に関する様々なプロパティをカプセル化します。ccctccc フィールドは、それぞれルーン自身のCCCと、そのルーンが分解された場合の末尾ルーンのCCCを保持します。
  • BoundaryBefore()BoundaryAfter(): これらのメソッドは、正規化処理におけるセグメント境界の判断に使用されます。CCCの値や結合特性に基づいて、ルーンが新しいセグメントの開始点となるか、またはセグメントの終了点となるかを判定します。
  • Decomposition(): ルーンの分解形(UTF-8バイト列)を返します。これにより、合成されたルーンがどのように分解されるかを知ることができます。
  • Size(): ルーンのUTF-8エンコーディングにおけるバイト長を返します。
  • CCC(): ルーンのCanonical Combining Class (CCC) を返します。これは、結合文字の並べ替え順序を決定する上で非常に重要な情報です。firstCCCZeroExcept という定数を用いて、特定の範囲のルーンに対してCCCが0であるという例外処理を行っています。
  • LeadCCC()TrailCCC(): これらのメソッドは、ルーンが分解される場合の先頭ルーンと末尾ルーンのCCCを返します。これにより、より複雑な正規化シナリオでのCCCの挙動を正確に把握できます。

これらのメソッドは、exp/norm パッケージの利用者がUnicode正規化の内部ロジックをより深く理解し、必要に応じてカスタマイズされた処理を実装するための強力なツールとなります。

関連リンク

参考にした情報源リンク

  • Unicode Standard Annex #15: Unicode Normalization Forms (上記と同じ)
  • Go言語の text/unicode/norm パッケージのドキュメント (上記と同じ)
  • Canonical Combining Class (CCC) に関する一般的な情報源 (例: Wikipedia, Unicode Consortiumのウェブサイトなど)
  • Go言語のソースコード (特に src/pkg/exp/norm ディレクトリ内のファイル)
  • コミットメッセージと差分情報
  • Go言語のコードレビューシステム (Gerrit) の変更リスト (CL) 5931043: https://golang.org/cl/5931043 (コミットメッセージに記載)
  • Go言語の公式ドキュメントやブログ記事 (Unicode正規化に関するもの)I have generated the comprehensive technical explanation in Markdown format, following all your instructions and the specified chapter structure. The output is provided directly to standard output as requested.