Unicode案例折叠为大写

时间:2013-11-24 21:52:15

标签: unicode utf-16 case-folding

根据该格式的官方规范,我正在尝试实现一个用于读取Microsoft CFB(复合文件二进制)格式文件的库。该规范可用from this site

简而言之 - 文件的某些结构存储在一个红黑树中。我在用于在该树中存储这些结构的比较谓词时遇到问题。规范说,如果这些结构的名称(字符串存储为UTF-16,Windows API中的标准)不同,则必须遍历每个UTF-16代码点并且:

  

(...)使用Unicode默认大小写转换转换为大写   算法,简单案例转换变体(简单案例折叠),具有以下注释。< 2>比较每个大写的UTF-16代码点二进制值。

<2>引用说:

  

或Windows XP和Windows Server 2003:复合文件实现   符合Unicode 3.0.1默认大小写转换算法,简单的案例折叠   (http://www.unicode.org/Public/3.1-Update1/CaseFolding-4.txt),但有以下例外情况。

然而,当我查阅引用的案例折叠文件,并阅读那里引用的UTR #21 "Case Mapping"时,我意识到案例折叠被定义为一种与下套管更相似的操作,而不是上部-casing。

通过使用CaseFolding-4.txt,我们可以获得大写字母到小写字母的大小写折叠映射。映射始终为1对1,因为此处不需要完全折叠(扩展为多个字符的折叠)。但是,小写字母到大写字母的反向映射不再是直截了当的。例如,

0392; C; 03B2; # GREEK CAPITAL LETTER BETA
03D0; C; 03B2; # GREEK BETA SYMBOL

因此,我们无法知道03B2是否应转换为039203D0。标准是否定义了折叠成大写的东西?也许我应该使用case折叠,然后转换为大写?或者我完全错误地理解了规范?

2 个答案:

答案 0 :(得分:6)

摘要:微软使用的措辞至少令人困惑。似乎应该进行简单的大写映射,但我无法确定。


背景

部分混淆可能是案例折叠案例映射之间的区别。案例映射将每个字符映射到指定的案例。案例折叠虽然基于较低的套管,但定义为导致无案例字符(UTR #21 §1.3)。

现在有两种案例映射和案例折叠变体,简单完整。与简单的转换不同,完整的转换可以改变字符串长度,正如你在这里不需要正确指出的那样。该规范明确提到了简单,可能是这个答案中唯一明确的事情。我觉得有必要提一下,为了将来的参考,当前的Unicode标准(6.3.0)提到默认案例转换是完整的,尽管Microsoft引用的版本(3.1.1)似乎没有做出这种区分。

Spec Analysis

  

(...)使用Unicode默认大小写转换算法,简单大小写转换变体(简单大小写折叠)转换为大写,并附带以下注释。 &LT 2 - ;比较每个大写 UTF-16代码点二进制值。

对我来说这个引用似乎表明他们想要大写,并且只是通过说案例折叠而不是案例映射来做出错误。但接下来是你引用的参考文献:

  

对于Windows XP和Windows Server 2003:复合文件实现符合Unicode 3.0.1默认大小写转换算法,简单大小写折叠(http://www.unicode.org/Public/3.1-Update1/CaseFolding-4.txt),但有以下例外。

他们实际上提到了案例折叠数据文件!在这一点上,我不确定该怎么想。我的主要思路是,微软希望机箱折叠虽然错误地认为它是基于上壳而不是下壳。这甚至是一个延伸,但它最接近我能够调和这个可能的矛盾,我希望有更好的解释。

我在section 2.6.1中发现以下内容支持某种形式的上壳:

  

[...]使用Red-Black Tree中描述的特殊的不区分大小写的大写映射来比较目录条目名称。

请注意,他们确实在这里使用术语映射

例外列表

看一下上面提到的Windows XP和Windows Server 2003的exception list,大多数条目都是减法的,这表明微软希望保持与众不同的代码点。但是,在表中,代码点实际上以与Unicode案例折叠数据文件相反的顺序列出。

对此的一种解释是,它只是一个显示怪癖。这个想法被最后一行击落,它们减去了案例转换0x03C2 -> 0x03C2。数据文件中不存在此转换,因为转换0x03C2 -> 0x03C3确实存在(未列出的大小写转换被视为转换为自身)。

另一种解释是,他们确实错误地认为它的反向映射是正确的。正如您所提到的,这会遇到麻烦,因为反向映射并不总是直截了当。否则,这种解释会很好。

第三种解释是考虑他们对Unicode案例折叠数据文件的引用是错误的。这当然让我感到不安,但如果他们最初确实意味着案例映射,他们可能刚刚提供了链接作为快速参考点。他们提到的例外列表确实有列标题,如&#34;小写UTF-16代码点&#34;但我们知道案例折叠实际上是无案例。

顺便说一句,我确实查看了后续操作系统的例外列表,希望能够获得更多的洞察力。我发现更多的困惑。特别是0x03C3 -> 0x03A3增加了我的麻烦。由于异常列表和Unicode文件以相反的顺序列出其代码点,因此看起来转换已经在数据文件中并且不需要添加。这部分规范不希望被理解!

结论

如果你已经阅读了上述所有内容,你可能会猜到这个结论不太理想。显然,在一个或多个点上,规范是错误的,但很难分辨到哪里。实际上有三种可能性取决于您对需要进行何种案例转换的解释。

  • 简单大写映射
  • 简单的案例折叠,然后是简单的大写映射
  • 简单案例折叠

对我来说,似乎微软确实想要上壳。从那里我相信案例折叠参考是一个错误,因此我的猜测是他们只是想要简单的大写映射。

我非常怀疑它是最后一个简单的折叠选项。其他两个选项都会产生非常相似的结果,只有少量代码点可能会产生不同的结果。

似乎唯一可以确定的方法是联系微软,或者仔细查看二进制文件以了解遵循哪种方法。

答案 1 :(得分:4)

The Unicode Standard Version 6.2 – Core Specification的3.13默认案例算法(第115页)中,文本引用UnicodeData.txt。这包含:

03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392
03D0;GREEK BETA SYMBOL;Ll;0;L;<compat> 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392

表示希腊小写字母Beta 确实应映射到希腊语Beta符号,并且旁边表示这两个符号具有某种程度的兼容性。它还包含您正在寻找的双向大小写转换的其余部分。您可能还需要查看SpecialCasing.txt以查找边界情况。