gauche.unicode
- Unicodeユーティリティ ¶このモジュールは、Unicodeのコードポイントの列に対する様々な操作を提供します。
Gaucheは以前、内部文字エンコーディングとしてUnicode以外も選べるようになっていました。 その場合、文字列に対して完全にUnicode互換の動作を提供できない場合があったため、 そこで、本モジュールの多くの操作は、文字列を対象にするものと、 コードポイントの数値のシーケンスを対象にするものの両方で提供されます。
• Unicode transfer encodings: | ||
• Unicode text segmentation: | ||
• フルセットの大文字小文字変換: | ||
• 東アジア文字幅プロパティ: |
このグループの手続きは、整数で表現されたコードポイントを扱います。 以下の説明で「オクテット」は0から255までの整数です。
これらの手続きは省略可能なstrictness引数を取ります。 この引数は、定義域外の入力が来たときの振る舞いを指定します。 指定できる値は次のいずれかです。
strict
定義域外の入力が来たらエラーを投げます。これがデフォルトの振る舞いです。
permissive
可能な限り、入力を有効な値であるかのように扱います。
例えば#x10ffff
を越えるコードポイント値はUnicode標準では不正な値ですが、
utf-8の規則を拡張することでエンコード可能であり、文字列以外のバイナリデータを単にutf-8風に
エンコードしたいだけの場合などには便利かもしれません。
replace
不正な入力を見たら、それをユニコード置換文字U+FFFD
に置き換え処理を続行します。
ignore
可能であれば、不正な入力は無視します。
strictnessがpermissive
やreplace
やignore
であっても、
入力データの妥当な解釈ができない場合はエラーが投げられる可能性があります。
{gauche.unicode
}
整数のコードポイント値を受け取り、utf-8でエンコードされたオクテットのリストを返します。
(ucs4->utf8 #x3bb) ⇒ (206 187) (ucs4->utf8 #x3042) ⇒ (227 129 130)
strictnessがstrict
の場合(デフォルト)、
入力が#xd800
と#xdfff
の間か、#x110000
以上の場合は
エラーを投げます。
strictnessがreplace
であれば、そのような入力に対しては
utf8シーケンス#xef, #xbf, #xbd
(U+FFFD
) がせ生成されます。
strictnessがpermissive
の場合は、
0
から#x7fffffff
までの入力が許されます。
入力が大きい場合はエンコードされた出力は5〜6オクテットになるでしょう
(初期のutf-8の定義通り)。
strictnessがignore
の場合は、
Unicodeとして不正なコードポイントに対しては空リストが返されます。
{gauche.unicode
}
octetをutf-8シーケンスの最初のオクテットとみなし、
そこからひとつのコードポイントをデコードするのに全部で何オクテット必要かを返します。
octet引数が0から255の間の正確な整数でなければ、 strictness引数の値にかかわらず、エラーが投げられます。
strictnessがstrict
の場合(デフォルト)、
戻り値は1,2,3,4のいずれかです。octetがutf-8でエンコードされた
Unicodeコードポイントの最初のオクテットとしてありえない値であれば
エラーが投げられます。
strictnessがpermissive
かreplace
の場合、
この手続きは0から6までの整数を返します。
入力が#xf8
から#xfd
の間の値(両端含む)の場合は
元々のutf-8仕様に基づいて5か6を返します
(これらのオクテットはコードポイントが#x110000
から
#x7fffffff
になるような値に相当します)。
引数が#x80
から#xbf
までの値、および#xfe
と#xff
の場合は、
utf-8の先頭バイトになり得ませんが、アプリケーションがこの不正なバイトだけを
適切に処理することを前提にして、1が返されます。
strictnessがignore
の場合、この手続きは
strict
でエラーが投げられる入力値について0
を返します。
それ以外はstrict
の動作と同じです。
{gauche.unicode
}
オクテットのリストを取り、それをutf-8のシーケンスとして解釈して、
デコードされたコードポイント及び残りのリストの2つの値を返します。
もし処理中に、0から255の間の正確な整数以外の値が入力に見つかったら、 strictnessの設定に関わらずエラーが投げられます。
それ以外の不正なutf-8シーケンスは、strictnessがstrict
であれば
エラーに、ignore
であればスキップされます。
strictnessがreplace
の場合は、そういったutf8シーケンスは
U+FFFD
を生成します。
strictnessがpermissive
の場合は、
最初のutf-8仕様で許されていた全てのコードポイント、すなわち
サロゲートペア領域(#xd800
から#dfff
まで)及び
#x110000
以上#x7fffffff
以下のコードポイントも認識されます。
それ以外の不正なコードポイントはpermissive
であってもエラーになります。
[R7RS base]
{gauche.unicode
}
u8vectorの、インデックスstart(含む)からend(含まない)までに
格納された値をutf-8オクテット列と見なし、文字列に変換して返します。
start、endが省略された場合はそれぞれベクタの最初と最後が指定されたものと
解釈します。
Gaucheのネイティブエンコーディングがutf8の場合、
この手続きはまずu8vector->string
を試します
(ユニフォームベクタ参照)。
もし入力がutf8シーケンスとして有効であれば、それが最も速いです。
しかし、入力に無効なutf8シーケンスが含まれていた場合、
この手続きは1文字づつ文字列を構築するモードにフォールバックし、
無効なutf8シーケンスの部分はUnicode置換文字U+FFFD
に置き換えられます。
従って戻り値は常に完全な文字列です。
入力に不正なuft8シーケンスが含まれていたかどうかを知りたい場合は
u8vector->string
を直接呼んでください。
Gaucheのネイティブエンコーディングがutf8以外の場合、
U+FFFD
に相当するコードがないので、無効なutf8シーケンスに出会うと
エラーが投げられます。
[R7RS base]
{gauche.unicode
}
文字列をutf8オクテットの並びにエンコードしてu8vectorとして返します。
省略可能なstartとend引数は対象とする文字列の範囲を指定します。
Gaucheのネイティブエンコーディングがutf8であれば、この手続きは
単にstring->u8vector
を呼び出すだけです。
(ユニフォームベクタ参照)。
そうでなければまず入力文字列がutf8に変換されてから
string->u8vector
が呼ばれます。
{gauche.unicode
}
整数で与えられたコードポイントをutf-16にエンコードして整数のリストとして返します。
strictnessがstrict
の場合(デフォルト)、
入力値は0
から#xd7ff
までの間か、
#xe000
から#x10ffff
までの間でなければなりません。
それ以外の場合はエラーが投げられます。
開いている部分はサロゲートに予約されているコードで、
この領域をutf-16にエンコードする方法は定義されていません。
strictnessがreplace
であれば、そのような入力は
#xfffd
(Unicode置換文字)に置き換えられます。
strictnessがpermissive
の場合、サロゲート領域の入力は
エラーにならず、その値を唯一の要素とするリストが返されます。
負の値および#x110000
の値についてはやはりエラーになります。
strictnessがignore
の場合は、不正なコードポイント(サロゲート領域含む)
については空リストが返されます。
註: permissiveモードでは#x10ffff
より大きな値をutf-8にはエンコードできますが、
utf-16にはエンコードできません。
{gauche.unicode
}
codeは0から65535までの正確な整数でなければなりません。
code
がBMPのコードポイントなら1を、utf-16の上位サロゲートであれば2を返します。
strictnessがstrict
の場合(デフォルト)、codeが
下位サロゲートであったり、定義外の値であればエラーが投げられます。
strictnessがpermissive
やreplace
の場合は、
やはり定義外の値であればエラーが投げられますが、
下位サロゲートの場合には1が返されます。
strictnessがignore
の場合、
定義域外および下位サロゲートに対しては0が返されます。
{gauche.unicode
}
正確な整数のリストを取り、それをutf-16の並びとして解釈します。
デコードされたucs4コードポイントおよび、残りのリストの二つの値を返します。
strictnessがstrict
の場合(デフォルト)、不正なutf-16の並びや
定義域外の値に出会ったらエラーが投げられます。
strictnessがpermissive
の場合は、
やはり定義外の値であればエラーが投げられますが、
片方だけのサロゲートの場合にはそれがそのまま(コードポイントとして)返されます。
strictnessがreplace
の場合は、
片方だけのサロゲートはU+FFFD
に置換されます。
strictnessがignore
の場合、
定義域外および片方だけのサロゲートは無視されます。
{guache.unicode
}
[R7RS scheme.bytevector]
u8vectorに格納されたutf16およびutf32シーケンスを文字列に変換します。
utf16->string
は、
もし入力に不正なutf16シーケンス (ペアになっていないサロゲート) があった場合は、
それがUnicode置換文字(U+FFFD
)に置き換えます。
入力のオクテット数がエンコーディング単位(utf16なら2オクテット、utf32なら4オクテット)
の倍数でない場合はエラーが投げられます。
省略可能なendianとignore-bom?引数は入力がUTF16BE/UTF32BEか
UTF16LE/UTF32LEかを
決めます。ignore-bom?が#f
または省略された場合、まず入力の
最初の2オクテットが調べられ、BOMであればendianの値にかかわらず
それがバイトオーダーを決定します。
入力がBOMで始まっていないか、ignore-bom?が真の値であれば、
endian引数がバイトオーダーを決定します。それが
big-endian
かbig
であればUTF16BE/UTF32BE、
little-endian
かlittle
かarm-little-endian
であれば
UTF16LE/UTF32LEとなります (エンディアンについてはエンディアンネス参照)。
ignore-bom?が与えられて真の値であった場合、
入力の先頭のBOMはコードポイントとみなされます。
endianが#f
または省略された場合は、
UTF16BE/UTF32BEとみなされます
(これはR7RS scheme.bytevector
で定義された仕様です)。
なおR7RS scheme.bytevector
ではignore-bom?引数は
endianness-mandatoryと呼ばれています。動作は同じです。
省略可能なstartとend引数は処理に先立って入力のオクテットシーケンスの
範囲を制限します(BOM検出も範囲制限後に行われます)。
この2つの引数はGauche独自拡張で、R7RS scheme.bytevector
では定義されていません。
{gauche.unicode
}
[R7RS scheme.bytevector]
文字列strをutf-16またはutf-32にエンコードしたオクテット列をu8vectorで返します。
省略可能なendian引数は、エンコーディングがUTF16BE/UTF32BEかUTF16LE/UTF32LEかを決めます。
シンボルbig-endian
かbig
が渡されたらUTF16BE/UTF32BE、
シンボルlittle-endian
かlittle
かarm-little-endian
が
渡されたらUTF16LE/UTF32LEになります。省略されるか#f
ならUTF16BE/UTF32BEになります。
バイトオーダーについての詳細はエンディアンネスを参照してください。
二つめの省略可能引数add-bom?にもし真の値が与えられたら、
出力の先頭にBOMが含められます。省略されるか#f
であればBOMは付加されません。
続く省略可能引数startとendは入力文字列strの特定の範囲だけを 対象とするのに使います。
R7RSのscheme.bytevector
ではendian引数だけを認めています。
残りはGaucheの拡張です。
These procedures implements grapheme-cluster and word breaking algorithms defined in UAX #29: Unicode Text Segmentation.
{gauche.unicode
}
与えられた文字列あるいはコードポイントシーケンス(コードポイントを要素とする
<sequence>
オブジェクト)から、単語のリストを返します。
各単語はそれぞれ、文字列あるいはコードポイントシーケンスで表現されます。
(string->words "That's it.") ⇒ ("That's" " " "it" ".") (codepoints->words '(84 104 97 116 39 115 32 105 116 46) ⇒ ((84 104 97 116 39 115) (32) (105 116) (46)) (codepoints->words '#(84 104 97 116 39 115 32 105 116 46) ⇒ (#(84 104 97 116 39 115) #(32) #(105 116) #(46))
二番めと三番目の例の入力は "That’s it." をコードポイント列にしたものです。
{gauche.unicode
}
与えられた文字列あるいはコードポイントシーケンス(コードポイントを要素とする
<sequence>
オブジェクト)から、graphemeクラスタのリストを返します。
各クラスタはそれぞれ、文字列あるいはコードポイントシーケンスで表現されます。
以下の手続きは上記のstring->words
等の高レベル手続きを作る部品となる、
低レベル手続きです。
{gauche.unicode
}
文字かコードポイントを生成するジェネレータgeneratorを取り、
二つの値を返すジェネレータを返します。最初の値は元のジェネレータから受け取った
文字またはコードポイントで、二つめの値は、その文字またはコードポイントの直前に
単語もしくはgraphemeクラスタ境界があった時に#t
、そうでない時に#f
となる
真偽値です。
ジェネレータg
が文字列That's it.
に含まれる文字を順に返す
ジェネレータとすれば、作られるジェネレータの動作は次の通りです。
(define brk (make-word-breaker g)) (brk) ⇒ #\T and #t (brk) ⇒ #\h and #f (brk) ⇒ #\a and #f (brk) ⇒ #\t and #f (brk) ⇒ #\' and #f (brk) ⇒ #\s and #f (brk) ⇒ #\space and #t (brk) ⇒ #\i and #t (brk) ⇒ #\t and #f (brk) ⇒ #\. and #t (brk) ⇒ #<eof> and #t
つまり、下図で^
で示される箇所が単語境界となっています
(空白字を_
で表しています)。
T h a t ' s _ i t . ^ ^ ^ ^ ^
{gauche.unicode
}
generatorは文字またはコードポイントを生成するジェネレータで、
returnは文字またはコードポイントのリストを受け取り、オブジェクトを返す手続きです。
これらの手続きは、オブジェクト (単語またはgraphemeクラスタ) をひとつづつ生成する
ジェネレータを返します。
ジェネレータg
が文字列That's it.
に含まれる文字を順に返す
ジェネレータとすれば、作られるジェネレータの動作は次の通りです。
(define brk (make-word-reader g list->string)) (brk) ⇒ "That's" (brk) ⇒ " " (brk) ⇒ "it" (brk) ⇒ "." (brk) ⇒ #<eof>
[R6RS][R7RS char][SRFI-129]
{gauche.unicode
}
与えられた文字列stringの大文字小文字を、Unicodeで定義された
言語独立のcase folding規則に基づいて変換します。
SRFI-13にも同名の手続きがありますが、そちらは文字ごとに変換する点で
これらの手続きと異なります(文字列のケース(大文字小文字)マッピング参照)。
特に、こちらの手続きは元の文字列と変換後の文字列の長さが異なる場合があり、
また文字が単語境界にあるかどうかで変換が変わることもあります。
単語境界はUAX #29の規則に基づいて判断されます。
(string-upcase "straße") ⇒ "STRASSE" (string-downcase "ΧΑΟΣΧΑΟΣ.ΧΑΟΣ. Σ.") ⇒ "χαοσχαοσ.χαος. σ." (string-titlecase "You're talking about R6RS, right?") ⇒ "You're Talking About R6rs, Right?" (string-foldcase "straße") ⇒ "strasse" (string-foldcase "ΧΑΟΣΣ") ⇒ "χαοσσ"
string-upcase
、string-downcase
、string-foldcase
は
R7RSのscheme.char
モジュールでも提供されます。
string-titlecase
はSRFI-129でも定義されています。
{gauche.unicode
}
string-upcase
などと同じですが、文字列ではなくコードポイント例を対象にします。
戻り値は入力と同じ型になります。
(codepoints-upcase '#(115 116 114 97 223 101)) ⇒ #(83 84 82 65 83 83 69)
[R7RS char]
{gauche.unicode
}
文字列全体の大文字小文字変換を使って、大文字小文字の違いを無視した文字列比較を行います。
Gaucheは組み込みでstring-ci=?
などを持っていますが、そちらは
文字ごとの大文字小文字変換を使います(文字列の色々な比較参照)。
それとは異なる手続きです。
(string-ci=? "\u00df" "SS") ⇒ #t
{gauche.unicode
}
引数は文字か、Unicodeコードポイントを表す非負整数でなければなりません。
次のいずれかのシンボルを返します:
N
(neutral)、
F
(fullwidth)、 H
(halfwidth)、 W
(wide)、
Na
(narrow)、A
(ambiguous)。
各シンボルの意味についてはUnicode standard annex #11を参照してください: http://unicode.org/reports/tr11/。
{gauche.unicode
}
東アジア文字幅プロパティを考慮して、文字列strの「幅」を計算して返します。
この幅は、概ね文字列を等幅フォントでターミナルに表示した場合の近似と考えることが
できます。
もちろん実際に文字列が表示された時にどのくらいの幅を取るかは、実際にグリフを使って レンダリングしてみないとわかりません。が、文字列の構成要素がある程度限られている 場合は、ヒューリスティクスでだいたいうまくいきます。 例えば文字列がASCII文字とCJK漢字からなる場合、’Full-width’と’Wide’ プロパティの文字をASCII文字の2倍幅とみなすことができるでしょう。
この手続きは、各文字の「東アジア文字幅プロパティ」カテゴリに次の幅を割り当てます。
キーワード引数F
, H
, W
, Na
, N
, A
によってそれぞれの幅に違う値を割り当てることも可能です。
2
1
2
1
1
2
文字幅の考慮について詳しくは、UAX #11 (http://unicode.org/reports/tr11/) の5節を見てください。
(string-east-asian-width "abc") ⇒ 3 (string-east-asian-width "いろは") ⇒ 6 (string-east-asian-width "1番目" :W 1.5) ⇒ 4.0
{gauche.unicode
}
string-take
とstring-drop
(srfi.13
- 文字列ライブラリ参照) のように、
文字列strを指定箇所で切った前部分と後部分を返しますが、
文字数で切るかわりに文字の幅で切ります。
string-take-width
は、strのプレフィクスのうち、
そのstring-east-asian-width
がwidthを越えない部分を返します。
一方string-drop-width
はそのプレフィクスを取り除いた部分を返します。
キーワード引数は東アジア文字幅のカテゴリから幅へのマッピングをカスタマイズするものです。
詳しくは上のstring-east-asian-width
の説明を見てください。