Использование ICU для реализации моего собственного фасета codecvt
Я хочу реализовать codecvt
использовать ICU для преобразования из любой кодировки символов (которую поддерживает ICU) в UTF-8 внутри. Я знаю что codecvt_byname
существует и что его можно использовать для выполнения части того, что я хочу, как показано в этом примере. Проблемы с этим примером состоят в том, что он (1) использует широкие символьные потоки (я хочу использовать "обычные", ориентированные на байты потоки) и (2) требует 2 потока для выполнения преобразования. Вместо этого я хочу один поток, как:
locale loc( locale(), new icu_codecvt( "ISO-8859-1" ) );
ifstream ifs;
ifs.imbue( loc );
ifs.open( "/path/to/some/file.txt" );
// data read from ifs here will have been converted from ISO-8859-1 to UTF-8
Следовательно, я хочу сделать реализацию, как это, но с использованием ICU, а не iconv
, Учитывая это, моя реализация do_in()
является:
icu_codecvt::result icu_codecvt::do_in( state_type &state,
extern_type const *from, extern_type const *from_end,
extern_type const *&from_next, intern_type *to,
intern_type *to_end, intern_type *&to_next ) const {
from_next = from;
to_next = to;
if ( always_noconv_ )
return noconv;
our_state *const s = state_store_.get( state );
UErrorCode err = U_ZERO_ERROR;
ucnv_convertEx(
s->utf8_conv_, s->extern_conv_, &to_next, to_end, &from_next, from_end,
nullptr, nullptr, nullptr, nullptr, false, false, &err
);
if ( err == U_TRUNCATED_CHAR_FOUND )
return partial;
return U_SUCCESS( err ) ? ok : error;
}
our_state
объект поддерживает два UConverter*
указатели, один для "внешней" кодировки (в этом примере ISO-8859-1) и один для кодировки UTF-8.
Мои вопросы:
- Должен ли я указать
nullptr
для буфера "pivot", как указано выше, или поставьте мой собственный? - Я не уверен, когда, если когда-либо, я должен установить
reset
аргумент (в настоящее время первыйfalse
выше) доtrue
, - Не понятно, как я узнаю, когда устанавливать
flush
аргумент (в настоящее время второйfalse
выше) доtrue
то есть, как я знаю, когда был достигнут конец ввода.
Небольшая помощь?
1 ответ
Фасет codecvt не предназначен для преобразования между различными кодировками. Вместо этого он преобразуется из внешнего кодирования, где один символ, возможно, кодируется с использованием нескольких внешних слов (обычно байтов), во внутреннее представление, где каждый символ представлен ровно одним словом (например, char, wchar_t, char16_t и т. Д.).
С этой точки зрения не имеет смысла "заканчивать" внутреннюю последовательность символов. Если больше нет доступных внешних слов, преобразование выполняется, и если последний символ остался неполным, это ошибка в переводе. Таким образом, нет необходимости указывать, что преобразование завершено и, соответственно, нет интерфейса. Это должно прояснить, что аргумент "flush" действительно всегда должен быть "false".
Я понимаю, что UTF-8 не совсем подходит для того, чтобы одно слово представляло один символ. Однако это будет мешать вам обрабатывать UTF-8, используя стандартные строки обработки типов. Пока вы держитесь подальше от модификаций шприца, все обычно работает нормально.
Параметр "reset", вероятно, предназначен для поиска в потоке. Я думаю, что filebuf должен предоставлять свежий объект state_type при поиске. Это, вероятно, будет указанием на то, что внутренние компоненты отделения интенсивной терапии хотят быть сброшены. Тем не менее, я не знаю об интерфейсе ICU. Таким образом, я также не знаю, хотите ли вы предоставить сводный буфер.