Как преобразовать массив ushort utf16 в std :: string utf8?

В настоящее время я пишу плагин, который представляет собой просто оболочку существующей библиотеки. Хост плагина передает мне строку в формате utf-16, определенную следующим образом

typedef unsigned short PA_Unichar;

И обернутая библиотека принимает только const char * или строку в формате std :: string utf-8. Я попытался написать функцию преобразования, например

std::string toUtf8(const PA_Unichar* data)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
return std::string(convert.to_bytes(static_cast<const char16_t*>(data));
}

Но, очевидно, это не работает, вызывая ошибку компиляции «static_cast from 'const pointer' (aka 'const unsigned short *') в 'const char16_t *' не допускается»

Итак, как это сделать наиболее элегантно / правильно?

Заранее спасибо.


person Robotex    schedule 15.12.2012    source источник
comment
Какая ценность std::is_same<unsigned short, char16_t>::value на вашей платформе? Кроме того, какой компилятор?   -  person moshbear    schedule 15.12.2012
comment
std::is_same<unsigned short, char16_t >::value имеет значение 0 (ложь), и я компилирую на Mac с помощью компилятора Apple LLVM 4.1, хотя я также компилирую его с помощью Visual Studio 2012.   -  person Robotex    schedule 15.12.2012
comment
Согласно open-std.org/jtc1/ sc22 / wg21 / docs / paper / 2006 / n2018.html, char16_t равно uint16_least_t, а не uint16_t. На вашей платформе похоже, что uint16_least_t не имеет псевдоним unsigned short, поэтому sizeof(char16_t) != sizeof(unsigned short). static_cast не будет работать с типами указателей, если базовые sizeof не совпадают.   -  person moshbear    schedule 15.12.2012
comment
char16_t по определению является 16-битным. Если unsigned short используется для UTF-16, тогда он также должен быть 16-битным. Я бы либо изменил PA_Unicode на uint16_t, либо использовал reinterpret_cast вместо static_cast.   -  person Remy Lebeau    schedule 15.12.2012
comment
Прежде чем я увидел ответ, я использовал второй способ, конечно, я мог бы заменить typedef, но, поскольку я не поддерживаю API, я не могу позволить себе рисковать сломать код при каждом обновлении. Желаю, чтобы ребята, написавшие интерфейс, использовали стандартные типы   -  person Robotex    schedule 16.12.2012
comment
Теперь, когда есть стандартные типы char16_t и char32_t (которые являются новыми, отдельными типами в C ++ 11, но определениями типов для существующих типов в C11), вероятно, библиотеки начнут их использовать. Библиотека ICU уже поддерживает сборку как C ++ 11, и в этом случае используется стандартный charNN_t типы.   -  person Jonathan Wakely    schedule 16.12.2012


Ответы (1)


Вы можете преобразовать строку PA_unichar в строку char16_t с помощью конструктора basic_string(Iterator, Iterator), а затем использовать фасет std::codecvt_utf8_utf16, как вы пытались:

std::string conv(const PA_unichar* str, size_t len)
{
  std::u16string s(str, str+len);
  std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
  return convert.to_bytes(s);
}

Я думаю, что это правильно. К сожалению, я не могу это проверить, так как моя реализация еще не поддерживает это. У меня есть реализация wstring_convert, которую я планирую включить в GCC 4.9, но у меня нет реализации codecvt_utf8_utf16, чтобы протестировать ее.

person Jonathan Wakely    schedule 15.12.2012
comment
Спасибо большое, вроде работает хорошо, и это тоже спасло меня от ужасных типов приведения в порядок :) - person Robotex; 16.12.2012
comment
Отлично, я рад, что компилятор в моей голове правильно проверил типы! Интересно, какой компилятор вы используете, который поддерживает эти классы? - person Jonathan Wakely; 16.12.2012
comment
Я компилирую компилятор LLVM 4.1 в системах на базе Mac (после установки флага -std=c++11) и Visual Studio 2012 в системах Windows - person Robotex; 16.12.2012
comment
Спасибо за внимание - думаю, мне лучше закончить реализацию GCC, тогда, если она есть у конкурентов! Я не видел спроса на классы, я не думаю, что большинство людей даже знают, что они существуют - person Jonathan Wakely; 19.12.2012
comment
Черт, codecvt_utf8_utf16 отсутствует в gcc 4.8. Будем надеяться, что Джонатан Уэйкли достиг отметки gcc 4.9. Слишком поздно для меня. - person BSalita; 15.05.2014