Unicode Переносимость - PullRequest
       1

Unicode Переносимость

5 голосов
/ 14 февраля 2011

В настоящее время я забочусь о приложении, которое использует std::string и char для строковых операций - что нормально для linux , поскольку Linux не зависит от Unicode (или, похоже, я на самом деле не знаю, поэтому, пожалуйста, поправьте меня, если я рассказываю истории здесь). Этот текущий стиль естественным образом приводит к такого рода объявлениям функций / классов:

std::string doSomethingFunkyWith(const std::string& thisdata)
{
    /* .... */
}

Однако, если thisdata содержит символы Unicode, он будет отображаться неправильно в Windows, поскольку std::string не может содержать символы Unicode в Windows.

Вот я и придумал эту концепцию:

namespace MyApplication {
#ifdef UNICODE
    typedef std::wstring  string_type;
    typedef wchar_t       char_type;
#else
    typedef std::string   string_type;
    typedef char          char_type;
#endif

    /* ... */
    string_type doSomethingFunkyWith(const string_type& thisdata)
    {
        /* ... */
    }
}

Это хорошая идея для поддержки Unicode в Windows?

Мой текущий набор инструментов состоит из gcc / clang в Linux и поддержки wine + MinGW для Windows (кросс-тестирование также происходит через wine), если это имеет значение.

Ответы [ 4 ]

5 голосов
/ 14 февраля 2011

Как вы храните строку в вашем приложении, полностью зависит от вас - в конце концов, никто не узнает, пока строки остаются в вашем приложении.Проблема начинается, когда вы пытаетесь читать или записывать строки из внешнего мира (консоль, файлы, сокеты и т. Д.), И именно здесь ОС имеет значение.

Linux не совсем «агностичен» для Unicode -он распознает Unicode, но стандартные библиотечные функции предполагают кодировку UTF-8, поэтому строки Unicode вписываются в стандартные массивы char.Windows, с другой стороны, использует кодировку UTF-16, поэтому вам необходим массив wchar_t для представления 16-битных символов.

Предложенные вами typedef должны работать нормально, но имейте в виду, чтоодно это не делает ваш код переносимым.Например, если вы хотите хранить текст в файлах в переносимом виде, вы должны выбрать одну кодировку и придерживаться ее на всех платформах - для этого может потребоваться преобразование между кодировками на определенных платформах.

4 голосов
/ 14 февраля 2011

Многоплатформенные проблемы возникают из-за того, что существует много кодировок, и неправильный выбор кодировки приведет к возникновению проблем кодирования. Как только вы решите эту проблему, вы сможете использовать std::wstring во всех своих программах.

Обычный рабочий процесс:

raw_input_data = read_raw_data()
input_encoding = "???" // What is your file or terminal encoding?

unicode_data = convert_to_unicode(raw_input_data, input_encoding)

// Do something with the unicode_data, store in some var, etc.

output_encoding = "???" // Is your terminal output encoding the same as your input?
raw_output_data = convert_from_unicode(unicode_data, output_encoding)

print_raw_data(raw_data)

Большинство проблем с Unicode возникает из-за неправильного определения значений input_encoding и output_encoding. В современном дистрибутиве Linux это обычно UTF-8. На Windows YMMV.

Стандартный C ++ не знает о кодировках, вам следует использовать некоторую библиотеку, такую ​​как ICU , чтобы сделать преобразование.

3 голосов
/ 14 февраля 2011

Linux поддерживает Unicode, он просто использует UTF-8. Вероятно, лучшим способом сделать вашу систему переносимой было бы использование международных компонентов для Unicode и обработка всех std::string объектов как содержащих символы UTF-8, а также преобразование их в UTF-16 при необходимости при вызове Функции Windows. Почти всегда имеет смысл использовать UTF-8 вместо UTF-16, так как UTF-8 использует меньше места для некоторых наиболее часто используемых символов (например, английский *) и больше места для менее частых символов, тогда как UTF-16 тратит пространство в равной степени для всех персонажей, независимо от того, как часто они используются.

Хотя вы можете использовать свои typedefs, это будет означать, что вам нужно написать две копии каждой отдельной функции, которая имеет дело со строками. Я думаю, что было бы более эффективно просто выполнять все внутренние вычисления в UTF-8 и просто переводить их в / из UTF-16, если это необходимо, при вводе / выводе по мере необходимости.

* Для HTML, XML и JSON, которые используют английский как часть кодировки (например, ", и т. Д.), Независимо от языка значений, это все равно может быть выгодно для иностранных языков .

1 голос
/ 01 апреля 2012

Проблема для Linux и использования Unicode заключается в том, что все операции ввода-вывода и большинство системных функций используют UTF-8, а тип широких символов - 32-разрядный.Затем происходит взаимодействие с Java и другими программами, для которых требуется UTF-16.

В качестве предложения по поддержке Unicode см. Библиотеку OpenRTL по адресу http://code.google.com/p/openrtl, которая поддерживает все UTF-8, UTF-16 и UTF-32 в Windows, Linux, Osx и Ios.Поддержка Unicode - это не только типы символов, но также сортировка Unicode, нормализация, сворачивание регистра, регистр заголовка и около 64 различных свойств символов Unicode на полный 32-разрядный символ без знака.

Теперь код OpenRTL готов к поддержкеchar8_t, char16_t и char32_t также для новых стандартов C ++, хотя те же типы символов поддерживаются с помощью макросов для существующих компиляторов C и C ++.Я думаю, что для обработки Unicode и строк это может быть то, что вам нужно для вашей библиотеки.

Дело в том, что если вы используете OpenRTL, вы можете собрать систему, используя тип OpenRTL "char_t".Это поддерживает идею о том, что вся ваша библиотека может быть построена в режиме UTF8, UTF16 или UTF32, даже в Linux, потому что OpenRTL уже обрабатывает весь интерфейс многих системных функций, таких как файлы и другие вещи.Например, он имеет свои собственные функции print_f.

По умолчанию char_t соответствует типу широких символов.Так что в Windows это 32-битная версия, а в Linux она 32-битная.Но вы можете сделать это также, например, 8 бит везде.Также имеется поддержка быстрого UTF-декодирования внутри циклов с использованием макросов.

Таким образом, вместо ifdeffing между wchar_t и char, вы можете построить все, используя char_t, а OpenRTL позаботится обо всем остальном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...