Joh*_*ger 3 unicode normalization icu unicode-normalization
我正在开发一个C项目,需要生成"不区分大小写"的规范化形式的Unicode文本.我选择将规范化形式定义为首先转换为NFD规范化,然后应用Unicode案例折叠算法,最后将结果转换为NFC规范化形式NFC.
我依靠ICU的C API来实现其Unicode表示和实用功能,使用ICU unorm_normalize()和u_strFoldCase()函数实现我的方案相当简单.但是我的一个测试失败了,我不明白为什么.ICU似乎正在产生一种与我预期不同的NFC形式.
输入序列由以下BMP代码点组成:
U+0020, U+1EA5, U+0328, U+1EC4, U+031C
Run Code Online (Sandbox Code Playgroud)
通过调试器,我确定ICU和我同意案例折叠后的中间结果:
U+0020 U+0061 U+0328 U+0302 U+0301 U+0065 U+031C U+0302 U+0303
Run Code Online (Sandbox Code Playgroud)
特别要注意的是,早期转换为形成NFD将字符U + 031C移动到U + 1EC4分解的中间,根据所涉及字符的相对CCC编号.这是我试图测试的一部分.
现在好的部分:根据ICU,折叠字符序列的NFC标准化是
U+0020 U+0105 U+0302 U+0301 U+1ec5 U+031C
Run Code Online (Sandbox Code Playgroud)
而我认为它应该是
U+0020 U+0105 U+0302 U+0301 U+0065 U+031C U+0302 U+0303
Run Code Online (Sandbox Code Playgroud)
因为三个尾随组合字符已经按规范顺序排列,并且没有U + 0065和U + 031C的规范组合.
那么,有两个问题:
ICU是对的.要了解原因,请查看Unicode标准第3章中定义的规范组合算法:
D117 规范组合算法:从编码字符序列(规范分解或兼容性分解)中的第二个字符开始,然后按顺序进行到最终字符,执行以下步骤:
R1在字符C的编码字符序列中向后(左)查找字符序列中C之前的最后一个Starter L.
R2如果存在这样的L,并且C没有被L阻挡,并且存在规范等效于序列<L,C>的初级复合P,则在序列中将L替换为P并从序列中删除C .
您还必须了解前面的定义,尤其是:
D115被阻止:令A和C为编码字符序列<A,... C>中的两个字符.当且仅当ccc(A)= 0并且在编码字符序列中A和C之间存在一些字符B,即<A,... B,... C>和ccc时,C被阻止. (B)= 0或ccc(B)> = ccc(C).
现在考虑输入序列的以下子字符串:
U+0065 U+031C U+0302 U+0303
Run Code Online (Sandbox Code Playgroud)
我们从角色开始,U+031C然后回到最后一个启动器U+0065:
U+0065 U+031C U+0302 U+0303
L C
Run Code Online (Sandbox Code Playgroud)
C显然没有被阻挡,但是没有主要的复合等价物,<L, C>所以我们继续下一个字符:
U+0065 U+031C U+0302 U+0303
L C
Run Code Online (Sandbox Code Playgroud)
现在C仍然没有被阻止L(这是你可能误解的)因为ccc(U+031C) = 220 < 230 = ccc(U+0302)并且存在一个U+00EA等同于的主复合U+0065 U+0302.所以我们替换L并删除C:
U+00EA U+031C U+0303
L C
Run Code Online (Sandbox Code Playgroud)
同样,C不会被L阻挡,并且主要复合材料U+1EC5相当于U+00EA U+0303所以组合物的最终结果是:
U+1EC5 U+031C
Run Code Online (Sandbox Code Playgroud)
这与ICU的输出相匹配.
| 归档时间: |
|
| 查看次数: |
447 次 |
| 最近记录: |