Шаблонний клас std::codecvt являється стандартним класом facet-властивості локалі (похідний від класу std::locale::facet), і призначений для перетворень між двома наборами кодування символів. Оголошення класу приблизно виглядає наступним чином:
template <class internT,
class externT,
class stateT> class codecvt ;
Параметр шаблону internT призначений для позначення внутрішнього типу символів, зазвичай він являється розширеним типом символів, на подобі wchar_t. Параметр шаблону externT, призначений для вказування зовнішнього типу збереження символів. Параметр шаблону stateT призначений для вказування типу, який буде зберігати стан перетворення, зазвичай це mbstate_t.
Клас std::codecvt містить захищений деструктор - програми повинні конструювати об'єкти класів, які являються похідними від даного, або використовувати об'єкти, які присутні у об'єктах класу locale (через функцію std::use_facet).
Усі стандартні об'єкти класу locale підтримують наступні ініціалізовані об'єкти:
- codecvt<char, char, mbstate_t> не виконує перетворення;
- codecvt<wchar_t, char, mbstate_t> перетворює символи з рідного розширеного типу у звичайне кодування.
Поля, методи і внутрішні типи
Внутрішні типи
typedef internT intern_type ;
Перший параметр шаблону (internT). Внутрішній тип символів.
typedef externT extern_type ;
Другий параметр шаблону (externT). Зовнішній тип збереження символів.
typedef stateT state_type ;
Третій параметр шаблону (stateT). Тип стану перетворення.
typedef codecvt_base::result result ;
Даний тип успадкований від codecvt_base, і використовується методами in, out, i unshift.
Внутрішні константи
Наступні константи успадковані даним класом від codecvt_base і використовуються методами класу у якості повернутого значення.
codecvt_base::result ok ;
Константа означає успішне перетворення.
codecvt_base::result partial ;
Константа означає часткове перетворення.
codecvt_base::result error ;
Дане значення означає помилку під час перетворення.
codecvt_base::result noconv ;
Дана константа означає відсутнє перетворення.
static locale::id id ;
Унікально ідентифікує аспект локалі.
Методи
explicit codecvt (size_t refs = 0) ;
Конструктор. Конструює новий об'єкт класу. Параметр refs вказує на: 0 - коли об'єкт повинен бути автоматично видаленим, коли останній об'єкт locale, який містить даний об'єкт повинен бути видалений; 1 - об'єкт автоматично не видаляється.
result in (state_type& state,
const extern_type* from, /* вказівник на перший символ послідовності */
const extern_type* from_end, /* вказівник на останній символ послідовності */
const extern_type*& from_next, /* вказівник, який може вказувати на послідовність */
intern_type* to, /* початок послідовності збереження */
intern_type* to_limit, /* кінець послідовності збереження */
intern_type*& to_next) /* вказівник, який може вказувати на елемент послідовність */
const ;
Метод перетворює символи з проміжку [from, from_end) і поміщає їх у послідовність, яка починається з to. Метод не намагається зберегти більше символів ніж це дозволяє параметр to_limit. Параметри from_next i to_next, призначені для збереження вказівника на елемент відповідної послідовності, який розміщується після останнього успішного перетвореного символу. Параметр state призначений для ініціалізації аспекту локалі. Зазвичай він являється об'єктом типу mbstate_t, який може зберігати просування процесу перетворення.
Метод зупиняється перетворювати символи коли виникає помилка перетворення символу, або метод досягнув межу перетворення from_end і усі символи успішно збережено.
Повернене значення, разом з значеннями параметрів from_next i to_next після виклику методу можуть бути використаними для обрахунку успішності перетворення символів.
Даний метод насправді являється делегатом і викликає віртуальний захищений (protected) метод do_in, який реалізовується в похідних класах.
result out (state_type& state,
const intern_type* from,
const intern_type* from_end,
const intern_type*& from_next,
extern_type* to,
extern_type* to_limit,
extern_type*& to_next)
const ;
Перетворює закодовані символи у послідовності [from, from_end) і розміщує їх у послідовність [to, to_limit). Вказівники from_next i to_next повинні мати здатність вказувати на елементи своїх послідовностей. Параметр state утримує стан просування процесу перетворення.
Метод зупиняється перетворювати коди символів коли натрапляє на перший символ, який він не в змозі перетворити, або коли усі символи успішно перетворено і збережено в послідовність [to, to_limit).
Повернене значення, разом з значеннями параметрів from_next i to_next після виклику методу, можуть бути використаними для визначення успішності результату перетворення.
int always_noconv () const throw () ;
Повертає значення яке вказує на те, чи перетворення між внутрішнім і зовнішнім типами у двох напрямках, завжди виконує копіювання без будь-якого перетворення.
Якщо даний метод повертає true для конкретного типу codecvt, тоді його методи codecvt::in i codecvt::out завжди повертають codecvt_base::noconv (тобто копіюють дані без будь-якого перетворення).
int encoding () const throw () ;
Повертає ширину внутрішніх символів у кількостях зовнішніх комірок для зберігання, якщо його це значення є фіксованим. Якщо ж дане значення змінюється від символа до символа, повертає 0 (нуль). Якщо кодування зовнішнього типу символів являється залежним від стану, повертає -1. Даний метод викликає віртуальний метод do_encoding, який реалізовується в дочірніх класах.
int length (state_type& state,
const extern_type* from,
const extern_type* from_end,
size_t max)
const ;
Повертає довжину зовнішньої послідовності з проміжку [from, from_end), яка може бути перетвореною у максимальну кількість комірок, відносно кількості max внутрішніх символів. Після виклику даного методу стан state змінюється, як після виклику методу codecvt::in.
int max_length () const throw () ;
Повертає максимальну кількість необхідних внутрішніх символів, які потрібні для зовнішніх символів.
result unshift (state_type& state,
extern_type* to,
extern_type* to_limit,
extern_type*& to_next)
const ;
Змінює стан перетворення. Під час перетворення кодування символів (наприклад, методом codecvt::out) стан у state може бути зміненим, коли цільова послідовність не може абсорбувати усі символи, які згенеровані перетворенням. Викликаючи даний метод, з додатковим місцем для збереження, останні символи, які повинні бути збереженими, поміщаються у послідовність [to, to_limit), і стан state повертається до свого необхідного значення (або зміщується до кількості (to_limit-to)).
Після того, як функція виконує свою роботу, вказівник to_next вказує на елемент, який знаходиться за останнім успішно записаним елементом.
Метод повертає один з значень типу codecvt_base::result (ok, partial, error, noconv).
Приклад
Розглянемо простий приклад перетворення рядка символів у зовнішній тип за допомогою codecvt.
#include <locale>
#include <string.h>
#include <string>
#include <iostream>
using namespace std ;
int main (int argc, char** argv)
{
/* створюємо об'єкт для бажаної локалі
** в моєму випадку це uk_UA.UTF-8 */
locale u8loc ("") ;
/* підготовлюємо цільовий буфер */
const unsigned int rlen = 256 ; /* довжина цільового буферу */
char cstr [rlen] ; /* цільовий буфер */
char* cptr = NULL ; /* вказівник не елемент */
/* підготовлюємо джерельний буфер */
const wchar_t warray [] = L"Рядок на українській." ;
const wchar_t* ptr = NULL ; /* вказівник на елемент джерельного буферу */
int wlen = sizeof (warray)/sizeof (warray[0]) ; /* розмір джерельного буферу */
/* об'єкт стану перетворення*/
codecvt<wchar_t, char, mbstate_t>::state_type state ;
/* отримуємо facet-аспект перекладач локалі */
const codecvt<wchar_t, char, mbstate_t>& cvt = use_facet < codecvt<wchar_t, char, mbstate_t> > (u8loc) ;
/* виконуємо перетворення з розширеного буферу у звичайний */
codecvt<wchar_t, char, mbstate_t>::result res = cvt.out (state, warray, warray + wlen, ptr,
cstr, cstr+rlen, cptr) ;
/* перевіряємо результат і виводимо повідомлення */
if (res==cvt.ok)
{
/* cstr тепер містить UTF-8 послідовність байтів
** які представляють рядок warray */
cout << "Успішне транслювання: "
<< cstr /* УВАГА! це може не спрацювати у терміналі!!! */
<< endl ;
cout << "Розмір джерельного буферу: " << wlen
<< "; розмір цільового буферу: " << strlen (cstr) << endl ;
}
else
{
cout << "Помилка транслювання" << endl ;
}
return 0 ;
}
Вивід програми наступний: