-
Notifications
You must be signed in to change notification settings - Fork 4
/
15.txt
247 lines (182 loc) · 14.3 KB
/
15.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
[3] [[Unicode]] では、実際には同じ意味を表す列を複数の[[文字]]の列で表せることがあります。
この時、そのうちの一つの表現を代表として定めた上で、それへの変換方法を規定することができ、
その表現、あるいは変換方法を[DFN[[RUBYB[正規化形]@en[normalization form]]]]といいます。
[[正規化形]]に変換することを[DFN[[RUBYB[正規化]@en[normalization]]]]といいます。
* 仕様書
[REFS[
- [6] [CITE@en-us[UAX #15: Unicode Normalization Forms]] ([TIME[2010-09-18 09:52:06 +09:00]] 版) <http://www.unicode.org/reports/tr15/>
- [53] <http://www.unicode.org/versions/latest/ch02.pdf#page=41>
- [54] [[Unicode Standard]] ([TIME[2016-07-19 02:38:02 +09:00]]) <http://www.unicode.org/versions/Unicode9.0.0/ch03.pdf#page=69>
- [9] [CITE@en-us[Unicode Character Encoding Stability Policy]] ([TIME[2010-12-28 03:43:17 +09:00]] 版) <http://www.unicode.org/policies/stability_policy.html#Normalization>
]REFS]
* 正規化形
[4] [[正規化形]]にはいくつかのバリエーションがあります。
[FIG(short list)[
- [[NFC]]
- [[NFKC]]
- [[NFD]]
- [[NFKD]]
- [[HFS+のNFD]]
- [[FCC]]
- [[FCD]]
]FIG]
[5] [[正規化形]]と[[応用]]レベルの[[文脈]]上の制約を組み合わせた概念もあります。
[FIG(short list)[
- [[完全正規化]]
]FIG]
[50] [[Stringprep]] や[[Unicode IDNA互換性処理]]や [[PRECIS]]
も広義の[[正規化]]と言えますが、 [[Unicode]]
の[[正規化]]に加えて[[大文字]]と[[小文字]]の変換や禁止文字などその他の処理も組み合わさっています。
[[IDNA2008]] による制約を満たす文字列も広義の[[正規化形]]と言えますが、やはり他の制約が組み合わさっています。
* 正規化形の性質
** 固有性
[24] [RUBYB[固有性]@en[uniqueness]]は [[Unicode]] [[正規化形]]の最も重要な[[設計目標]]とされています。
2つの等価な[[文字列]]の[[正規化形]]は完全に一致します [SRC[>>6 7]]。すなわち、
- [25] 2つの[[文字列]]が[RUBYB[[[正準等価]]]@en[canonical equivalent]]なら、
両者に [[NFC]] を適用した結果は[[一致]]します。また、両者に [[NFD]]
を適用した結果は[[一致]]します。 [SRC[>>6 7]]
- [26] 2つの[[文字列]]が[RUBYB[[[互換性等価]]]@en[compatibility equivalent]]なら、
両者に [[NFKC]] を適用した結果は[[一致]]します。また、両者に [[NFKD]]
を適用した結果は[[一致]]します。 [SRC[>>6 7]]
- [27] [[NFC]], [[NFD]], [[NFKC]], [[NFKD]] はいずれも[[冪等]]です。 [SRC[>>6 7]]
-- [28] これは >>25、>>26 から導かれます。 [SRC[>>6 7]]
-- [46] [[訂正 #5]] による変更以前は実は[[冪等]]でないケースが存在しました。
** 安定性
[29] ここでいう[RUBYB[安定性]@en[stability]]は[[正規化]]に直接関係しない[[文字]]がそのまま無変更で残ることをいいます。具体的には、
- [30] [[互換性分解]]を持った[[文字]]は、 [[NFC]] や [[NFD]] を適用しても元の[[文字]]のまま結果に含まれます。 [SRC[>>6 7]]
- [31] [[結合文字]]が含まれていなければ、 [[NFC]] によって[[文字列]]は変化しないことを原則とします。 [SRC[>>6 7]]
-- [32] [[合成除外表]]に含まれるものは例外です。 [SRC[>>6 7]]
- [33] [[合成]]に無関係な[[結合文字]]が含まれていても、[[合成]]の結果には影響しません。 [SRC[>>6 7]]
-- [34] [[合成済文字]]に対応する[[基底文字]]と[[結合文字]]に加え、更に別の[[結合文字]]があったとしても、
[[結合文字]]同士の順序の如何を問わず、結局[[合成]]は行われ、それに加えてその別の[[結合文字]]が残ります。
** 効率性
[35] [[正規化]]は[RUBYB[効率的]@en[efficiency]]に実装可能であるとされています [SRC[>>6 7]]。
具体的には、
- [36] [[正規化形]]が効率良く実装可能であって、とりわけ既に [[NFC]] または [[NFD]]
である[[文字列]]に対して [[NFC]] を高速に得ることが可能です。 [SRC[>>6 7]]
- [37] [[合成]]を行う[[正規化形]]は、必ずしも最初の形を生成するものではありません。
最小形の計算は高価である可能性があるためです。 [SRC[>>6 7]]
* 安定性
[7] [[Unicode Consortium]] の規定する [[Unicode]] の[[正規化形]]、[[NFC]]、[[NFD]]、
[[NFKC]]、[[NFKD]] については、'''[[安定性]]'''、つまり [[Unicode]]
の改訂を通じて[[正規化]]に非互換な変更が加わらないことがある程度保証されています。
[58] 基本的には、[[安定性]]は[[文字]]が定義されている[[符号位置]]に関するものです。
新たな [[Unicodeの版]]で新しい[[文字]]が追加されると、その[[符号位置]]の[[正規化]]の結果は変化するかもしれません。
** 強い正規化安定性
[10] [DFN[[RUBYB[[[強い正規化安定性]]]@en[strong normalization stability]]]]: [[Unicode]] 4.1 とそれ以降において、
ある版で割り当て済みの[[文字]]のみから構成される[[文字列]]を[[正規化]]した結果は、
その[[文字列]]を以降の任意の版で[[正規化]]した結果と一致します。
[SRC[>>9]]
[11] そのために、一旦割り当てられた[[文字]]の[[分解写像]]と[[正準結合クラス]]が改訂によって変化しないことが保証されています。
[SRC[>>9]]
[12] この安定性は割り当て済みの[[文字]]のみで構成される場合についてのものであり、
[[未割当]]の[[符号位置]]が含まれているときには必ずしも保証されません。
[38] この安定性が保証されるのは [[Unicode]] 4.1 以降ですが、実際には [[Unicode]] 3 以降においても
[[Corrigendum #2]], [[Corrigendum #3]], [[Corrigendum #4]], [[Corrigendum #5]]
の影響を受けない範囲では成立します。 [SRC[>>6 11.2]]
** 弱い正規化安定性
[13] [DFN[[RUBYB[[[弱い正規化安定性]]]@en[weak normalization stability]]]]:
[[Unicode]] 3.1 とそれ以降において、ある版で割り当て済みの[[文字]]のみから構成される[[文字列]]を[[正規化]]した結果得られる[[文字列]]は、
以降の任意の版においても[[正規化]]済みです。また、それ以前で [[Unicode]] 3.1 までの版であって、
その[[文字列]]に含まれる[[文字]]すべてが含まれる版においてもまた、[[正規化]]済みです。
[SRC[>>9、>>6 11.1]]
[14] そのために、一旦割り当てられた[[文字]]の[[分解写像]]がいくつかの例外ケースを除き改訂によって変化しないこと、
[[正準結合クラス]]が改訂によって変化しないことが保証されています。 [SRC[>>9]]
;; [8] [[Unicode]] [[正規化形]]の[DFN[[RUBYB[[[合成版]]]@en[composition version]]]]は「[[UCD]]
3.1.0」であると規定されています [SRC[>>6 3]]。これは[[弱い正規化安定性]]が 3.1.0
以降について成立するということです。
[15] [[強い正規化安定性]]が保証されれていれば、[[弱い正規化安定性]]もまた保証されます。
[18] 「XY」の2文字から「Z」の1文字への[[合成]]を追加する場合、
[[弱い正規化安定性]]が満たされるためには、
3文字すべてが新しい[[文字]]であるか、または [VAR[X]] と [VAR[Y]]
のどちらかだけが古い[[文字]]であるかでなければなりません。 [SRC[>>6 3]]
[20] また、[[正規化]]に影響するような既存の[[文字]]の[[特性]]の変更も認められないことになります。
[SRC[>>6 3]]
*** 例
[16] 「Q + caron」という[[文字]] (の列) を考えます。[[合成版]]である 3.1.0
にはこれを1[[符号位置]]で表す[[合成済文字]]は含まれていません。
[[基底文字]]と[[結合文字]]の2文字で表すしかなく、これが[[正規形]]です。
[17] その後の版で、「Q + caron」を1文字で表す[[合成済文字]]が追加されたとしましょう。
自然に考えれば「Q-caron」 → 「Q」 + 「caron」という[[合成]] ([[正準分解]]) を追加したいところですが、
そうすると以前の版で [[NFC]] だった「Q」 + 「caron」の2文字の表現が [[NFC]]
ではなくなり、新しい「Q-caron」に[[正規化]]しなければならなくなってしまいます。
これは[[弱い正規化安定性]]の定義に反します。
;; [19] [[Unicode Consortium]] は新しい[[合成]]を追加することを[[非推奨]]としており、
従って「Q-caron」のような[[文字]]が後から追加されることは原則として無いようです。 [SRC[>>6 3]]
** Unicode 3.1 以前の非互換性
[22] [[Unicode]] 3.1.0 が「[[合成版]]」ということは、逆にそれまでの版と現在とでは互換性がない変更が行われていることを意味します。
[23] たとえば [[Unicode]] 2.1.9 において[[ハングル音節]]に関する[[互換性写像]]が削除され、
[[正規化]]の結果が変化しています。 [SRC[>>6 6]]
[43] [[Unicode]] 3.0.1 と 3.1 の間に発行された[[訂正 #2]] では、
誤って[[合成除外表]]から欠落していた1[[文字]]について、
[[合成除外表]]に追加され、非互換性が生じています。
** Unicode 3.1 から Unicode 4.1 までの非互換性
[39] [[UAX #15]] では、[[強い正規化安定性]]が保証されていない [[Unicode]] 4.1
よりも前の版との互換性が必要な時の対処方法として、
- [40] [[Unicode]] 4.1 以前の動作に近づける [SRC[>>6 11.3]]
- [41] 動作が変わってしまった[[文字]]の利用を禁止する [SRC[>>6 11.4]]
... の2通りを挙げて説明しています。
;; [42] >>41 は利用頻度が少ない[[文字]]だから問題ないことが多かろうなどと説明されていますが、
ひどいもんですなw
[44] [[Unicode]] 3.1 と 4.1 の間には[[訂正 #3]]と[[訂正 #4]]が発行され、
6文字について[[正準分解]]が修正されています。
[45] [[Unicode]] 4.0.1 と 4.1 の間には[[訂正 #5]] が発行され、「[[妨害]]」
の定義が修正されて[[正規化]]の[[冪等性]] (>>27) が保たれるようになっています。
それ以前も[[冪等性]]は設計目標に入っていましたが、定義の誤りにより厳密には成立していませんでした。
* 分解と合成
[55] [[Unicode]] では、[[符号化文字列]][VAR[文字列]]に対して[[正準分解]]、[[正準合成]]、[[互換分解]]といった[[演算]]が定義されています。
4つの[[正規化形]]は、その組み合わせとして次のように定義されています [SRC[>>54]]。
[FIG(list)[
- [[NFC]]: [VAR[文字列]]の[[正準分解]]の[[正準合成]]
- [[NFKC]]: [VAR[文字列]]の[[互換分解]]の[[正準合成]]
- [[NFD]]: [VAR[文字列]]の[[正準分解]]
- [[NFKD]]: [VAR[文字列]]の[[互換分解]]
]FIG]
[67] 次のような[[手順群]]に整理できます [SRC[>>54]]。
[FIG(steps)[
= [64] [VAR[文字列]]に[[完全分解]]を適用します。
[[NFC]]/[[NFD]] なら[[正準等価性]]を、[[NFKC]]/[[NFKD]] なら[[互換等価性]]を用います。
= [65] [[NFC]]/[[NFKC]] なら、
== [66] [VAR[文字列]]に[[正準合成アルゴリズム]]を適用します。
= [68] それ以外なら、
== [63] [VAR[文字列]]に[[正準再順序付けアルゴリズム]]を適用します。
]FIG]
* 大文字・小文字との関係
[52] >>51 は[[プログラミング言語]]の[[識別子]]について[[大文字・小文字不区別]]と[[正規化]]を両方採用する場合について考察しています。
[REFS[
- [51] [CITE@en-us[UAX #31: Unicode Identifier and Pattern Syntax]] ([TIME[2013-09-30 19:53:19 +09:00]] 版) <http://www.unicode.org/reports/tr31/#normalization_and_case>
]REFS]
* 応用
[61] [[Web]] では、一部で [[NFC]] が使われます。 [[XML]] で[[完全正規化]]も使われます。
[[JavaScript]] の [CODE(DOMm)@en[normalize]] [[メソッド]]は、 [[NFC]]、[[NFD]]、
[[NFKC]]、[[NFKD]] に対応しています。
[62] それ以外の用法については、各[[正規化形]]の項を参照。
* 実装
[REFS[
- [48] [CITE[SADAHIRO Tomoyuki / Unicode-Normalize - search.cpan.org]] ([TIME[2011-04-10 18:07:12 +09:00]] 版) <http://search.cpan.org/dist/Unicode-Normalize/>
]REFS]
[57] [[NFC]]、[[NFD]]、[[NFKC]]、[[NFKD]]、[[FCC]]、[[FCD]] を実装しています。
対応する [[Unicodeの版]]は、[[Perl]] の版に依存します。
[60] [[XS]] 版と [[PP]] 版があります。
[REFS[
- [59] [CITE[Charlint - A Character Normalization Tool]] ([TIME[2009-12-03 17:38:05 +09:00]]) <https://www.w3.org/International/charlint/>
]REFS]
* 関連
[21] >>12 や >>18 のようにありますが、[[合成除外表]]の規定によれば新たな[[正準分解]]が追加されるとすると、
その展開先の[[文字]]に既存の[[文字]]が含まれているなら[[合成除外表]]に追加しなければならないこととなっており、
場合によっては未定義の[[符号位置]]が含まれていても新しい版で結果が変わらないことが保証される場合もあるようです。
* メモ
[1] [CITE[XProc: An XML Pipeline Language]]
([TIME[2010-05-11 22:38:07 +09:00]] 版)
<http://www.w3.org/TR/2010/REC-xproc-20100511/#p.serialization>
[2] [CITE@EN[XQuery 1.0 and XPath 2.0 Functions and Operators (Second Edition)]]
( ([TIME[2010-12-17 00:06:54 +09:00]] 版))
<http://www.w3.org/TR/2010/REC-xpath-functions-20101214/#func-normalize-unicode>
[47] [CITE@en[draft-duerst-i18n-norm - Character Normalization in IETF Protocols]]
<http://tools.ietf.org/html/draft-duerst-i18n-norm>
[49] [CITE@en[Character Model for the World Wide Web 1.0: Normalization]]
( ([TIME[2012-04-27 20:15:23 +09:00]] 版))
<http://www.w3.org/TR/2012/WD-charmod-norm-20120501/>
[56] [CITE@EN[XPath and XQuery Functions and Operators 3.0]]
( ([TIME[2014-04-08 07:02:07 +09:00]] 版))
<http://www.w3.org/TR/xpath-functions-3/#func-normalize-unicode>