Поддержка 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 для его значения проблематично. В любом случае, это, кажется, даже не допускается.

Этапы конвертации:

  1. Установите локаль на соответствующую для UTF-16/UTF-32.

  2. использование isspace() для обнаружения пробелов.

  3. Конвертировать подобная мода для your_atof(),

  4. Восстановление локальное.

Этот вопрос может быть немного старым, но я хотел бы коснуться реализации ваших функций с 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.

Другие вопросы по тегам