Поддержка Unicode C11
Я пишу некоторые функции преобразования строк, похожие на atoi()
или же strtoll()
, Я хотел включить версию моей функции, которая бы принимала char16_t* или char32_t* вместо просто char* или wchar_t*.
Моя функция работает нормально, но когда я ее писал, я понял, что не понимаю, что такое char16_t или char32_t. Я знаю, что стандарт требует, чтобы они имели целочисленный тип по крайней мере 16 или 32 бита соответственно, но подразумевается, что это UTF-16 или UTF-32.
Я также знаю, что стандарт определяет пару функций, но они не включают в себя функции *get или *put (как они делали, когда добавляли в wchar.h
в С99).
Поэтому мне интересно: что они ожидают от меня с char16_t и char32_t?
3 ответа
Это хороший вопрос без очевидного ответа.
uchar.h
типы и функции, добавленные в C11, в основном бесполезны. Они поддерживают только преобразования между новым типом (char16_t
или же char32_t
) и зависящее от локализации, определяемое реализацией многобайтовое кодирование, отображения которого не будут завершены, если локаль не будет на основе UTF-8. Полезные преобразования (в / из wchar_t
и в / из UTF-8) не поддерживаются. Конечно, вы можете свернуть свои собственные для преобразований в / из UTF-8, так как эти преобразования на 100% определены соответствующими стандартами RFC /UCS/Unicode, но будьте осторожны: большинство людей реализуют их неправильно и имеют опасные ошибки.
Обратите внимание, что новые функции уровня компилятора для литералов UTF-8, UTF-16 и UTF-32 (u8
, u
, а также U
соответственно) потенциально полезны; Вы можете обрабатывать получающиеся строки своими собственными функциями осмысленными способами, которые вообще не зависят от локали. Но поддержка Unicode на уровне библиотек в C11, на мой взгляд, в принципе бесполезна.
Проверка того, является ли устав UTF-16 или UTF-32 в диапазоне ASCII одной из "обычных" 10 цифр, +, - или "нормального" пробела, легко выполнить, а также преобразовать '0'-'9'
на цифру. При условии, atoi_utf16/32()
продолжается как atoi()
, Просто проверяйте одного персонажа за раз.
Проверить, является ли какой-либо другой UTF-16/UTF-32 цифрой или пробелом, - это сложнее. Кодекс потребуется расширенный isspace(), isdigit()
которые можно было бы поменять местами (setlocale()
) если необходимая локаль доступна. (Примечание: вероятно, потребуется восстановить языковой стандарт, когда функция будет выполнена.
Преобразование символа, который проходит isdigit()
но не один из обычных 10 для его значения проблематично. В любом случае, это, кажется, даже не допускается.
Этапы конвертации:
Установите локаль на соответствующую для UTF-16/UTF-32.
использование
isspace()
для обнаружения пробелов.Конвертировать подобная мода для
your_atof()
,Восстановление локальное.
Этот вопрос может быть немного старым, но я хотел бы коснуться реализации ваших функций с char16_t
а также char32_t
служба поддержки.
Самый простой способ сделать это - написать свой strtoull
функция с использованием char32_t
типа (назовите это как-то strtoull_c32
). Это облегчает анализ Unicode, потому что каждый символ в UTF-32
занимает четыре байта. Затем реализовать strtoull_c16
а также strtoull_c8
путем внутреннего преобразования обоих UTF-8
а также UTF-16
кодировки в UTF-32
и передать их strtoull_c32
,
Честно говоря, я не рассматривал возможности Unicode в стандартной библиотеке C11, но если они не предоставляют подходящий способ для преобразования этих типов в UTF-32
тогда вы можете использовать стороннюю библиотеку, чтобы сделать преобразование для вас.
Есть ICU, который был запущен IBM, а затем принят Консорциумом Unicode. Это очень многофункциональная и стабильная библиотека, которая существует уже давно.
Недавно я запустил библиотеку UTF ( UTFX) для C89, которую вы тоже можете использовать для этого. Это довольно просто и легко, проверено и задокументировано. Вы можете попробовать, или использовать его, чтобы узнать больше о том, как работают преобразования UTF.