Как я могу вставлять строковые константы unicode в исходный файл?

Я пишу некоторые модульные тесты, которые будут проверять нашу обработку различных ресурсов, которые используют другие наборы символов, помимо обычного латинского алфавита: кириллица, иврит и т.д.

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

///
/// Protected: TestGetHebrewConfigString
///  
void CPrIniFileReaderTest::TestGetHebrewConfigString()
{
    prwstring strHebrewTestFilePath = GetTestFilePath( strHebrewTestFileName );
    CPrIniFileReader prIniListReader( strHebrewTestFilePath.c_str() );
    prIniListReader.SetCurrentSection( strHebrewSubSection );   

    CPPUNIT_ASSERT( prIniListReader.GetConfigString( L"דונדארןמע" ) == L"דונהשךוק") );
}

Это довольно просто не работает. Раньше я работал над этим с помощью макроса, который вызывает подпрограмму, чтобы преобразовать узкую строку в широкую строку (мы используем буксировку по всему месту в наших приложениях, так что существующий код)

#define UNICODE_CONSTANT( CONSTANT ) towstring( CONSTANT )

wstring towstring( LPCSTR lpszValue )
{
    wostringstream os;
    os << lpszValue;
    return os.str();
}

Тогда утверждение в вышеприведенном тесте получилось:

CPPUNIT_ASSERT( prIniListReader.GetConfigString( UNICODE_CONSTANT( "דונדארןמע" ) ) == UNICODE_CONSTANT( "דונהשךוק" ) );

Это работало нормально в OS X, но теперь я переношу на Linux, и я обнаружил, что тесты все проваливаются: все это тоже довольно хаки. Может ли кто-нибудь сказать мне, есть ли у них лучшее решение этой проблемы?

Ответ 1

Достойный, но переносимый способ состоит в том, чтобы построить ваши строки, используя числовые коды эвакуации. Например:

wchar_t *string = L"דונדארןמע";

становится:

wchar_t *string = "\x05d3\x05d5\x05e0\x05d3\x05d0\x05e8\x05df\x05de\x05e2";

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

Вы можете использовать онлайн-инструменты для преобразования, такие как этот. Он выводит формат escape-кода JavaScript \uXXXX, поэтому просто найдите и замените \u на \x, чтобы получить формат C.

Ответ 2

Вы должны указать GCC, который кодирует ваш файл, чтобы закодировать эти символы в файле.

Используйте опцию -finput-charset=charset, например -finput-charset=UTF-8. Затем вам нужно рассказать о кодировке, используемой для этих строковых литералов во время выполнения. Это определит значения элементов wchar_t в строках. Вы устанавливаете эту кодировку с помощью -fwide-exec-charset=charset, например -fwide-exec-charset=UTF-32. Остерегайтесь того, что размер кодировки (utf-32 требует 32 бит, utf-16 - 16 бит) не должен превышать размер использования wchar_t gcc.

Вы можете настроить это. Эта опция в основном полезна для компиляции программ для wine, предназначенных для совместимости с окнами. Опция называется -fshort-wchar, и, скорее всего, она будет 16 бит вместо 32 бит, что является ее обычной шириной для gcc на linux.

Эти параметры описаны более подробно в man gcc, gcc manpage.

Ответ 3

#define UNICODE_CONSTANT( CONSTANT ) towstring( CONSTANT )

wstring towstring( LPCSTR lpszValue ) {
    wostringstream os;
    os << lpszValue;
    return os.str(); 
}

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