Автор: Андрей Владимирович Лукьянов // © 2010 // e-mail: land@long.yar.ru
Опубликовано: 2010‑06‑15
Последняя правка: 2010-09-19
UTF-12 — это проект системы представления символов Юникода в виде потока 12-битных блоков.
В основном UTF-12 предполагается использовать в сочетании с кодированием Base64, поскольку 12-битному блоку данных соответствует последовательность из ровно двух знаков Base64, что может быть очень удобно.
В чистом виде UTF-12 могла бы использоваться в компьютере, в котором минимально адресуемые ячейки памяти имеют размер 12 бит. В 1960‑е годы действительно существовали миникомпьютеры, в которых машинное слово было 12 бит (например, PDP-8).
В дальнейшем 12‑битные блоки данных будут называться «байтами» в кавычках, чтобы было ясно, что это не обычные 8‑битные байты. Значения «байтов» — беззнаковые.
Предлагаемая система кодирования обладает следующими свойствами:
В зависимости от значения, «байты» распределяются по типам следующим образом:
Тип «байта» | Значение (hex.) | Двоичное представление (биты x — любые) |
|
от | до | ||
одиночный | 000 | 7BF | 0yyyyyxxxxxx, где хотя бы один из битов y равен 0 |
начальный | 7C0 | BFF | 011111xxxxxx или 10xxxxxxxxxx |
конечный | C00 | FFF | 11xxxxxxxxxx |
Юникодовские символы от 0000 до 07BF кодируются одним 12‑битным «байтом» с тем же значением. В частности, одним «байтом» кодируются все русские буквы (а также греческие, армянские, еврейские и арабские).
Юникодовские символы от 07C0 до 10FFFF кодируются последовательностью из двух «байтов» следующим образом:
Это можно изобразить в виде следующей таблицы (используется двоичное представление):
Символ Юникода из диапазона 0000—07BF |
Символ Юникода из диапазона 07C0—10FFFF |
||||||||||||||||||||||||||||||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | a | a | a | a | a | a | a | a | a | a | a | aaaaaaaaaaabbbbbbbbbb | ||||||||||||||||||||||||
↓ | + | a 1 |
a 1 |
a 1 |
a 1 |
a 1 |
a 0 |
a 0 |
a 0 |
a 0 |
a 0 |
a 0 |
b | b | b | b | b | b | b | b | b | b | |||||||||||||||||||||||
0 | a | a | a | a | a | a | a | a | a | a | a | c | c | c | c | c | c | c | c | c | c | c | c | 1 | 1 | b | b | b | b | b | b | b | b | b | b | ||||||||||
одиночный «байт» | начальный «байт» | конечный «байт» |
Значения свыше 10FFFF непредставимы в UTF-12.
Символ Юникода | UTF-12 | |||
двоичн. | 16-ричн. | 8-ричн. | Base64 | |
U+0000 | 000000000000 | 000 | 0000 | AA |
U+07BF | 011110111111 | 7BF | 3677 | e/ |
U+07C0 | 011111000001 111111000000 | 7C1 FC0 | 3701 7700 | fB/A |
U+0800 | 011111000010 110000000000 | 7C2 C00 | 3702 6000 | fCwA |
U+FEFF | 011111111111 111011111111 | 7FF EFF | 3777 7377 | f/7/ |
U+FFFF | 011111111111 111111111111 | 7FF FFF | 3777 7777 | f/// |
U+10000 | 100000000000 110000000000 | 800 C00 | 4000 6000 | gAwA |
U+10FFFF | 101111111111 111111111111 | BFF FFF | 5777 7777 | v/// |
Диапазон Юникода | Бит на символ | |||
от | до | UTF-8 | UTF-12 | UTF-16 |
0000 | 007F | 8 | 12 | 16 |
0080 | 07BF | 16 | 12 | 16 |
07C0 | 07FF | 16 | 24 | 16 |
0800 | FFFF | 24 | 24 | 16 |
10000 | 10FFFF | 32 | 24 | 32 |
Таким образом, UTF-12 является самой экономичной формой представления Юникода в диапазоне символов 0080—07BF (в этот диапазон попадают все русские, греческие, армянские, еврейские и арабские буквы), а также в диапазоне 10000—10FFFF (разные экзотические символы).
UTF-12 уступает UTF-8 в экономичности только в диапазонах 0000—007F (чистый ASCII) и 07C0—07FF (письмо нко).
Неправильные последовательности в UTF-12 имеют в принципе ту же природу, что и в UTF-8.
Неправильно сформированные последовательности UTF-12 возникают, например, если конечный «байт» идёт не после начального, а после другого конечного или после одиночного; или, наоборот, начальный или одиночный «байт» идут там, где ожидается конечный. Алгоритмы обработки должны обнаруживать такие ошибки.
Другой тип неправильных последовательностей — искусственно удлинённые. Формально можно закодировать юникодовские символы от 0000 до 07BF не только одним «байтом», но и двумя. Например, нулевой символ 0000 можно закодировать не только как один «байт» 000, но и как два «байта» 7С0+С00.
Также существует проблема с суррогатными па́рами (символами из диапазона D800—DFFF). Они используются в UTF-16, но в UTF-12 не нужны.
В UTF-12 искусственно удлинённые последовательности и символы из области суррогатных пар запрещены. Из этого следует, что в потоке UTF-12 не должны встречаться «байты» со значениями 7C0, 7F6 и 7F7. Там, где важна безопасность, лучше вообще не принимать какие-либо «неправильные» строки.
В нижеприведённых алгоритмах фразу «Сообщаем об ошибке» можно трактовать по-разному, например:
Пусть входной поток состоит из 21‑битных юникодовских символов, а выходной поток — из 12‑битных «байтов». Начинаем цикл:
Пусть входной поток состоит из 12‑битных «байтов», а выходной поток — из 21‑битных юникодовских символов. Начинаем цикл:
Возможно, кто-то захочет использовать UTF-12 (в двоичном виде) для представления данных в обычных компьютерах с 8‑битным байтами (например, для более компактного хранения русских текстов). В этом случае предлагается следующая система:
Пусть у нас текст состоит из трёх латышских букв ģ (код 0123): ģģģ. UTF-12 в файле из 8‑битных байтов будет выглядеть так:
12‑битные «байты» | 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 | |
8‑битные байты | 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 | 0 |
Тот же метод можно использовать для передачи текстов UTF-12 по протоколам, рассчитанным на передачу 8‑битных байтов.
Для передачи UTF-12 по протоколам, рассчитанным на 7‑битные данные, можно использовать дополнительное кодирование Base64 — для UTF-12 это особенно удобно, поскольку один 12‑битный «байт» кодируется ровно двумя знаками Base64. Вышеприведённая последовательность ģģģ в Base64 будет выглядеть как EjEjEj.
Base64 должно кодировать 12‑битные «байты» напрямую, без промежуточного преобразования в 8‑битные байты.