使用ICU实现我自己的codecvt方面

时间:2011-12-30 15:25:44

标签: c++ iostream icu codecvt

我想使用ICU实现codecvt方面,以便在内部将任何字符编码(ICU支持)转换为UTF-8。我知道codecvt_byname存在,并且它可用于执行我想要的部分内容,如this example所示。该示例的问题在于它(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. 我应该如上所述为“pivot”缓冲区指定nullptr,还是提供我自己的?{/ li>
  2. 我不确定何时,如果有的话,我应该将reset参数(目前是上面的第一个false)设置为true
  3. 目前尚不清楚我怎么知道何时将flush参数(目前是上面的第二个false)设置为true,即我怎么知道输入结束的时间已经到达。
  4. 一点帮助?

1 个答案:

答案 0 :(得分:0)

codecvt方面旨在在不同编码之间进行转换。相反,它从外部编码转换,其中一个字符可能使用多个外部字(通常为字节)编码为内部表示,其中每个字符由一个字(例如char,wchar_t,char16_t等)表示。

从这个角度来看,“结束”内部字符序列是没有意义的。如果没有可用的外部单词,则转换完成,如果最后一个字符仍未完成,则这是转移中的错误。因此,不需要指示转换是完整的,并且相应地,没有指示接口。这应该澄清“冲洗”论证确实应该总是“假”。

我意识到UTF-8并不适合让一个单词代表一个字符。但是,这将困扰您使用标准类型处理字符串来使用UTF-8处理。只要你不清楚syring修改,通常情况下工作正常。

“reset”参数可能用于处理流中的搜索。我认为filebuf应该在搜索时提供一个新的state_type对象。这可能表明ICU内部需要重置。但是,我不知道ICU接口。因此,我也不知道您是否想要提供数据透视缓冲区。