Как я могу вставлять строковые константы 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).