Транскодирование символов на лету с использованием iostreams и ICU - PullRequest
0 голосов
/ 10 декабря 2011

Я бы хотел перекодировать кодировку символов на лету. Я хотел бы использовать iostreams и свое собственное транскодирование streambuf, например ::100100

xcoder_streambuf xbuf( "UTF-8", "ISO-8859-1", cout.rdbuf() );
cout.rdbuf( &xbuf );

char *utf8_s;    // pointer to buffer containing UTF-8 encoded characters
// ...
cout << utf8_s;  // characters are written in ISO-8859-1

Реализация xcoder_streambuf будет использовать API конвертеров ICU. Он будет принимать поступающие данные (в данном случае от utf8_s), перекодировать их и записывать с использованием оригинального iostream steambuf.

Это разумный путь? Если нет, то что будет лучше?

1 Ответ

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

Это разумный путь?

Да, но это не то, что от вас ожидают в современном (как в 1997 году) iostream.

Поведение вывода через basic_streambuf<> определяется виртуальной функцией overflow(int_type c).

Описание basic_filebuf<>::overflow(int_type c = traits::eof()) включает a_codecvt.out(state, b, p, end, xbuf, xbuf+XSIZE, xbuf_end);, где a_codecvt определяется как:

const codecvt<charT,char,typename traits::state_type>& a_codecvt 
     = use_facet<codecvt<charT,char,typename traits::state_type> >(getloc());

, поэтому ожидается, что вы получите imbue a locale с соответствующим codecvt<charT,char,typename traits::state_type> конвертером.

Класс codecvt<internT,externT,stateT> предназначен для использования при преобразовании из одной кодировки символов в другую, например из широких символов в многобайтовые символы, или между кодировками широких символов, такими как Unicode и EUC.

Стандартная поддержка библиотеки Unicode достигла определенного прогресса с 1997 года:

код специализации конвертирует между схемами кодирования UTF-32 и UTF-8.

Похоже, что вы хотите (коды ISO-8859-1 - это коды USC-4 = UTF-32).

Если нет, то что будет лучше?

Я бы ввел другой тип для UTF8, например:

struct utf8 {
    unsigned char d; // d for data
};

struct latin1 {
    unsigned char c; // c for character 
};

Таким образом, вы не можете случайно пройти UTF8 там, где ожидается ISO-8859- *. Но тогда вам придется написать некоторый код интерфейса, и тип ваших потоков не будет istream / ostream.

Отказ от ответственности: я никогда не делал ничего подобного, поэтому я не знаю, насколько это реально на практике.

...