Использование ICU для реализации моего собственного фасета codecvt - PullRequest
0 голосов
/ 30 декабря 2011

Я хочу реализовать фасет 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.

Мои вопросы:

  1. Должен ли я указать nullptr для буфера "pivot", как указано выше, или указать свой собственный?
  2. Я не уверен, когда, если вообще, я должен установить аргумент reset (в настоящее время первый false выше) равным true.
  3. Непонятно, как я узнаю, когда установить для аргумента flush (в настоящее время второй false выше) значение true, то есть как узнать, когда достигнут конец ввода.

Небольшая помощь?

1 Ответ

0 голосов
/ 30 декабря 2011

Фаза codecvt не предназначена для преобразования между различными кодировками. Вместо этого он преобразуется из внешней кодировки, где один символ возможно закодирован с использованием нескольких внешних слов (обычно байтов), во внутреннее представление, где каждый символ представлен ровно одним словом (например, char, wchar_t, char16_t и т. Д.).

С этой точки зрения не имеет смысла «заканчивать» внутреннюю последовательность символов. Если больше нет доступных внешних слов, преобразование выполняется, и если последний символ остался неполным, это ошибка в переводе. Таким образом, нет необходимости указывать, что преобразование завершено и, соответственно, нет интерфейса. Это должно прояснить, что аргумент «flush» действительно всегда должен быть «false».

Я понимаю, что UTF-8 не совсем подходит для того, чтобы одно слово представляло один символ. Тем не менее, это будет мешать вам обрабатывать UTF-8 с использованием стандартных строк обработки типов. Пока вы держитесь подальше от модификаций шприца, все работает нормально.

Параметр "reset", вероятно, предназначен для поиска в потоке. Я думаю, что filebuf должен предоставлять свежий объект state_type при поиске. Это, вероятно, будет указанием на то, что внутренние компоненты отделения интенсивной терапии хотят быть сброшены. Тем не менее, я не знаю об интерфейсе ICU. Таким образом, я также не знаю, хотите ли вы предоставить сводный буфер.

...