На этом шаге мы рассмотрим средства преобразования кодировок.
Фацет codecvt выполняет преобразования между внутренней и внешней кодировками символов. Например, с его помощью можно преобразовывать символы из Unicode в EUC (Extended UNIX Code) при условии, что реализация стандартной библиотеки C++ поддерживает соответствующий фацет.
Этот фацет используется классом basic_filebuf для преобразования между внутренней кодировкой и представлением, хранящимся в файле. Класс basic_filebuf<charT,traits> задействует для этой цели специализацию codecvt <charT,char,typename traits::state_type>. Применяемый фацет берется из локального контекста, связанного с basic_filebuf. Данный способ применения фацета является основным, напрямую с этим фацетом работают крайне редко. На 527 шаге были приведены начальные сведения о кодировке символов. Чтобы понять, как работает фацет codecvt, необходимо знать о существовании двух схем кодировки: в одной схеме каждый символ кодируется фиксированным количеством байтов (расширенная кодировка), а в другой используется переменное количество байтов на символ (многобайтовая кодировка).
Также необходимо знать о том, что в многобайтовых кодировках для повышения эффективности представления используется так называемое состояние сдвига. Чтобы правильно интерпретировать байт, необходимо знать состояние сдвига для данной позиции. Состояние сдвига определяется только полным перебором всей последовательности многобайтовых символов (за подробностями обращайтесь к 527 шагу).
Шаблон фацета codecvt<> получает три аргумента:
Промежуточное состояние может состоять из незавершенных символов в расширенной кодировке или текущего состояния сдвига. Стандарт C++ не делает никаких ограничений по поводу того, что должно храниться в объектах, представляющих состояние.
Во внутреннем представлении символы всегда кодируются фиксированным количеством байтов. Как правило, программы работают с символьными данными типов char и wchar_t, а во внешнем представлении может использоваться многобайтовая или расширенная кодировка. В случае многобайтовой кодировки второй аргумент шаблона определяет тип представления ее базовых единиц. Каждый многобайтовый символ состоит из одного или нескольких объектов этого типа. Обычно для этой цели применяется тип char.
В третьем аргументе передается тип, используемый для представления текущего состояния преобразования. Например, если одна из кодировок является многобайтовой, обработка многобайтового символа может быть прервана из-за переполнения исходного или приемного буфера. В этом случае текущее состояние преобразования сохраняется в объекте заданного типа.
По аналогии с другими фацетами стандарт требует обязательной поддержки минимального количества специализаций. Стандартная библиотека C++ поддерживает только две специализации:
Стандарт C++ не определяет конкретную семантику второго преобразования. Единственное естественное решение заключается в разбиении каждого объекта wchar_t на sizeof(wchar_t) объектов типа char для преобразования wchar_t в char и сборке wchar_t из того же количества объектов char при обратном преобразовании. Обратите внимание на принципиальные отличия этого преобразования от тех, которые выполняются функциями widen() и narrow() фацета ctype: если функции codecvt используют биты нескольких объектов char для формирования одного объекта wchar_t (или наоборот), функции ctype преобразуют символ из одной кодировки в соответствующий символ другой кодировки (если он существует).
На следующем шаге мы закончим изучение этого вопроса.