Я хочу реализовать фасет 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
Следовательно, я желаю сделать реализацию, подобную this , но используя 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
, то есть как узнать, когда достигнут конец ввода.
Небольшая помощь?