Unicode чехол складывается в верхний регистр
Я пытаюсь реализовать библиотеку для чтения файлов формата Microsoft CFB (Compound File Binary) в соответствии с официальной спецификацией этого формата. Спецификация доступна с этого сайта.
В двух словах - некоторые структуры файла хранятся в красно-черном дереве. У меня проблема с предикатом сравнения, используемым для хранения этих структур в этом дереве. В спецификации говорится, что если имена (строки хранятся как UTF-16, стандарт в API Windows) этих структур различны, необходимо выполнить итерацию по каждой кодовой точке UTF-16 и:
(...) преобразование в верхний регистр с помощью алгоритма преобразования регистра по умолчанию в Юникоде, простой вариант преобразования регистра (простые преобразования регистра) со следующими примечаниями.<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 "Отображение регистра", я понял, что сворачивание регистра определяется как операция, которая гораздо больше похожа на нижний регистр, а не на верхний регистр. корпус.
Используя CaseFolding-4.txt
, мы можем получить сопоставления заглавных букв в верхнем регистре и строчных. Отображение всегда 1 к 1, поскольку здесь не нужны полные свертки (те, которые расширяются до нескольких символов). Однако обратное отображение букв нижнего регистра в верхний регистр больше не является простым. Например,
0392; C; 03B2; # GREEK CAPITAL LETTER BETA
03D0; C; 03B2; # GREEK BETA SYMBOL
Таким образом, мы не можем знать, 03B2
следует преобразовать в 0392
или же 03D0
, Стандарт определяет что-то вроде складывания в верхний регистр? Может быть, я должен использовать сворачивание регистра, а затем преобразовать в верхний регистр? Или я правильно понял спецификацию?
2 ответа
Резюме: формулировка, используемая Microsoft... сбивает с толку, если не сказать больше. Похоже, что должно быть сделано простое отображение в верхнем регистре, хотя я не уверен.
Фон
Частично путаница может заключаться в разнице между свертыванием и отображением дел. Отображение регистра отображает каждый символ в указанном регистре. Свертывание регистра, хотя оно основано на нижнем регистре, определено так, чтобы приводить к символам без регистра ( UTR # 21 §1.3).
Сейчас существует два варианта картографирования и складывания карт, простой и полный. В отличие от простого преобразования, полное можно изменить длину строки, и, как вы правильно заметили, здесь не требуется. Спецификация конкретно упоминает простую и, вероятно, единственную ясную вещь в этом ответе. Я чувствую необходимость упомянуть в будущем, что в текущем стандарте Unicode (6.3.0) упоминается, что преобразование регистра по умолчанию является полным, хотя версия, на которую ссылается Microsoft (3.1.1), по-видимому, не делает этого различия.
Спек Анализ
(...) преобразование в верхний регистр с помощью алгоритма преобразования регистра по умолчанию в Юникоде, простой вариант преобразования регистра (простые преобразования регистра) со следующими примечаниями.<2> Сравните каждое двоичное значение кодовой точки UTF-16 в верхнем регистре.
Мне кажется, эта цитата говорит о том, что они хотят использовать верхний регистр, и просто допустила ошибку, сказав, что регистр складывается вместо отображения регистра. Но потом приходит та ссылка, которую вы цитировали:
Для Windows XP и Windows Server 2003: реализация составного файла соответствует стандартному алгоритму преобразования регистра Unicode 3.0.1, простое сворачивание регистра ( http://www.unicode.org/Public/3.1-Update1/CaseFolding-4.txt) со следующими исключениями.
Они на самом деле упоминают файл данных сворачивания дела! На данный момент, я не уверен, что думать. Моя основная мысль заключается в том, что Microsoft хочет сворачивать корпус, хотя ошибочно полагал, что он основан на верхнем, а не на нижнем корпусе. Хотя это даже натянуто, но ближе всего я смог примирить это возможное противоречие, и я надеюсь, что есть лучшее объяснение.
В разделе 2.6.1 я нашел следующее, которое поддерживает некоторую форму верхнего регистра:
[...] имя записи каталога сравнивается с помощью специального нечувствительного к регистру отображения верхнего регистра, описанного в Красно-черном дереве.
Обратите внимание, что они на самом деле используют термин сопоставление здесь.
Список исключений
Взглянув на список исключений для упомянутых Windows XP и Windows Server 2003, большинство записей представляют собой вычитания, указывающие на то, что Microsoft хочет сохранить четкие позиции кода. Однако в таблице кодовые точки фактически перечислены в обратном порядке по отношению к файлу данных свертывания регистра Unicode.
Одно из объяснений этого заключается в том, что это просто причуды дисплея. Эта идея сбита последним рядом, где они вычитают преобразование случая 0x03C2 -> 0x03C2
, Это преобразование не существует в файле данных, так как преобразование 0x03C2 -> 0x03C3
делает (преобразование в незарегистрированном случае считается преобразованным в себя).
Другое объяснение состоит в том, что они действительно ошибочно полагают, что это правильное обратное отображение. Как вы уже упоминали, это создает проблемы, так как обратное отображение не всегда простое. В противном случае это толкование было бы хорошо.
Третье толкование состоит в том, чтобы считать их ссылку на файл свертывания данных случая Unicode неправильной. Это, конечно, заставляет меня чувствовать себя неловко, но если бы они действительно имели в виду первоначальное отображение случаев, они могли просто предоставить ссылку в качестве краткого справочного ориентира. Список исключений, о котором они упоминают, имеет заголовки столбцов, такие как "Кодовая точка UTF-16 в нижнем регистре", но мы знаем, что на самом деле сворачивание регистров происходит без учета регистра.
Кроме того, я рассмотрел список исключений для более поздних операционных систем, надеясь получить более глубокое понимание. Я нашел больше путаницы. В частности добавление 0x03C3 -> 0x03A3
беспокоит меня Так как список исключений и файл Unicode перечисляют их кодовые точки в обратном порядке, оказывается, что преобразование уже находится в файле данных и не нуждается в добавлении. Эта часть спецификации не хочет быть понятой!
Заключение
Если вы прочитали все вышеизложенное, вы, вероятно, догадаетесь, что этот вывод будет не идеальным. Очевидно, в одной или нескольких точках спецификация ошибочна, но трудно сказать, где. На самом деле есть три возможности, в зависимости от вашей интерпретации относительно того, какой вид трансформации необходимо выполнить.
- Простое отображение в верхнем регистре
- Простое сворачивание регистра с последующим простым отображением верхнего регистра
- Простой чехол складной
Мне кажется, что Microsoft действительно хочет верхний корпус. Оттуда я полагаю, что ссылка на свертывание регистра является ошибкой, и, таким образом, я предполагаю, что они просто хотят простого отображения верхнего регистра.
Я очень сомневаюсь, что это последний простой вариант складывания только в одном случае. Оба других варианта дали бы очень похожие результаты с небольшим количеством точек кода, возможно, дающих разные результаты.
Кажется, что единственный способ узнать наверняка - это связаться с Microsoft или тщательно изучить двоичные файлы, чтобы узнать, какой метод используется.
В разделе 3.13 Алгоритмы регистров по умолчанию (стр. 115) Стандартной версии Unicode 6.2 - Базовая спецификация текст ссылается на 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 для граничных случаев.