Каноническая Юникод строковая форма - PullRequest
1 голос
/ 23 января 2012

У меня есть строка в кодировке Юникод, скажем, как UTF8.Одна строка в Unicode может иметь несколько байтовых представлений.Интересно, существует ли или может быть создана какая-либо каноническая (нормализованная) форма строки Unicode - так что мы можем, например, сравнить такие строки с memcmp(3) и т. Д. Может ли, например, ICU или любая другая библиотека C/C++ сделать это?

Ответы [ 3 ]

6 голосов
/ 23 января 2012

Возможно, вы ищете нормализация Unicode .Существуют четыре различные нормальные формы, каждая из которых гарантирует, что все эквивалентные строки впоследствии будут иметь общую форму.Однако во многих случаях вам также необходимо принимать во внимание локаль, поэтому, хотя это может быть дешевым способом сравнения байтов (если вы обеспечиваете тот же формат преобразования Unicode, как UTF-8 или UTF-16и та же самая нормальная форма) это не принесет вам особой пользы от этого ограниченного варианта использования.

2 голосов
/ 23 января 2012

Сравнение кодовых последовательностей Unicode:

UTF-8 - это само каноническое представление. Две строки Unicode, которые составлены из одних и тех же кодовых точек Unicode, всегда будут кодироваться в одну и ту же последовательность байтов UTF-8 и, следовательно, могут сравниваться с memcmp. Это необходимое свойство кодировки UTF-8, в противном случае его нельзя будет легко декодировать. Но мы можем пойти дальше, это верно для всех официальных схем кодирования Unicode, UTF-8, UTF-16 и UTF-32. Они кодируют строку в разные последовательности байтов, но всегда кодируют одну и ту же строку в одну и ту же последовательность. Если вы учитываете порядок байтов и независимость от платформы, UTF-8 является рекомендуемой схемой кодирования, поскольку вам не приходится иметь дело с порядками байтов при чтении или записи 16-битных или 32-битных значений.

Таким образом, ответ таков: если две строки кодируются с одинаковой схемой кодирования (например, UTF-8) и endiannes (это не проблема с UTF-8), результирующая последовательность байтов будет то же самое.

Сравнение строк Юникода:

Есть еще одна проблема, с которой сложнее справиться. В Unicode некоторые глифы (символ, который вы видите на экране или на бумаге) могут быть представлены одной кодовой точкой или комбинацией двух последовательных кодовых точек (называемых объединяющими символами ). Это обычно справедливо для глифов с акцентами, диакритическими знаками и т. Д. Из-за различного представления кодовой точки их соответствующая последовательность байтов будет отличаться. Сравнение строк с учетом этих комбинирующих символов не может быть выполнено с помощью простого сравнения байтов, сначала вы должны его нормализовать.

В других ответах упоминаются некоторые методы нормализации Unicode, канонические формы и библиотеки, которые вы можете использовать для преобразования строк Unicode в их обычную форму. Тогда вы сможете сравнить их побайтно с любой схемой кодирования.

1 голос
/ 23 января 2012

Вы хотите нормализовать строку к одной из форм нормализации Unicode. libicu может сделать это для вас, но не для строки UTF-8. Вы должны сначала преобразовать его в UChar, используя, например, ucnv_toUChars, затем нормализовать с помощью unorm_normalize, затем преобразовать обратно с помощью ucnv_fromUChars. Я думаю, что есть также определенная версия ucnv_ * для кодировки UTF-8.

Если ваша единственная цель - memcmp, вы, конечно, можете сделать это непосредственно в массиве UChar после unorm_normalize.

...