[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
XLC_LOCALE. Продолжение 2.
Дальше идут блоки - описание кодесетов (codeset).
Кодесет - это просто набор кодов, которые могут встретиться
в потоке "мультибайтов".
В каждом кодесете описаваются его "отличительные признаки" (дальше я расскажу
подробнее) и правила преобразования в другие представления.
Каждый блок выглядит как
cs<цифра> {.....}
Внутри ...
Сначала - "отличительные признаки".
side
Главный "отличительный признак".
В простейшем случае может быть GL или GR. Это означает, что -
- к данному кодесету относятся все байты типа GL (в диапазоне 0-127)
- или - все байты типа GR (коды 128-255)
После GL/GR может через двоеточие стоять слово Default.
Это имеет смысл если в данной кодировке может быть несколько кодесетов
с одинаковым "сайдом" (естественно, у них есть какие-то другие отличия).
Тогда один из таких кодесетов будет default, а другой - рассматривается
только при некоторых обстоятельствах (они описываются параметром mb_encoding).
Для iso8859 всегда существут только два кодесета - один - GL:Default,
другой - GR:Default.
Для CJK side может быть "none", тогда отличительным признаком будут
параметры вида - byte<цифра>.
length <число>
Длина "мультибайта".
Для iso8859 всегда - 1.
А для CJK может быть несколько разных кодесетов с разной длиной.
Например, если бы мы так описывали UTF, то там был бы кодесет с длиной 1,
который описывал бы ascii, несколько кодесетов длиной - 2 (один из них
соответствовал бы кириллице), несколько - 3 и т.д.
byte*
Еще один "отличительный признак" (встречается в sjis).
Если side = none, то этот параметр (byte*) просто задает диапазон кодов.
Этих byte должно быть столько, сколько указывает параметр length.
Например, если
side none
length 2
а дальше идет что-то типа
byte1 \x80,\xa0
byte2 \x20,\x40
то это означает - к данному кодесету относятся все mb коды, у которых
- первый байт в дипазоне 0x80-0xa0
- второй - в 0x20-0x40
Кстати, дипазонов может быть и несколько, они указываются через ";".
Для iso8859 этот параметр не требуется.
mb_encoding
Еще один "отличительный признак" (встречается в некоторых CJK).
Если есть несколько кодесетов с одинаковым side (или с одинаковыми byte*),
один из них должен быть default, а другой рассматривается, если в потоке
встретились "переключатели" (байт или последовательность байтов).
Естествеено, и для перехода в default должен быть "переключатель".
mb_encoding как-раз описывает - как выглядит "переключатель" на данный
кодесет.
Возможны три переключателя
<LSL> - locked shift left
<LSR> - locked shift right
<SS> - single shift
locked - означает, что все дальнейшие байты интерпретируются "по-новому",
пока не появится новый "переключатель" (или пока конвертор не будет
принудительно "ресетнут" программой, тогда выбирается кодесет default).
single shift - означает, что отдельно интерпретируется только один символ
(не байт, а мультибайт), непосредственно за "переключателем".
После "волшебных слов" <lsl>/<lsr>/<ss> идет последовательность кодов,
которая и является "переключателем".
Для iso8859 - смысла не имеет.
Ну и наконец - параметры, описавающие - как интерпретировать данный
кодесет.
wc_encoding
Как я уже говорил - описывает преобразование в wc (и обратно).
Если входной мультибайт относится к данному кодесету, он упаковывается
в соответствии с wc_shift_bits. А потом в этот w_char "вклеивается"
код, заданный wc_encoding.
Если нужно выполнить обратное преобразование, то
- в соответствии с wc_encoding_mask из w_char выделяется та часть, которая
различает кодесеты
- среди кодесетов ищется тот, в котором указан подходящий wc_encoding
- делается нужное преобразование в соответствии с параметрами выбраного
кодесета (side, length, mb_encoding и т.п.) и общего параметра wc_shift_bits
(он нужен для "раздергивания" wc на несколько байтов)
ct_encoding
Преобразование в ctext (и обратно).
В этом параметре указывается название чарсета. Считается, что Xlib
знает - какой "назначатель" (esc-sequence) соответствует данному чарсету
("назначатель" задан либо во внутренних таблицах Xlib, либо может быть
описан в XLC_LOCALE с помощью блока csd* - char set definition).
"Секвенция" может быть указана и прямо в ct_encoding, например -
ct_encoding KOI8-1:GR:\x1b-K
(к сожалению, так можно указывать только "секвенции", которые "похожи на
стандартные" в смысле стандарта CTEXT. Последовательности типа
\033%/1/200/210koi8-r/002 будут восприняты неправильно.)
Итак. Если нужно преобразовать mb или wc в ct, то конвертор должен найти
подоходящий кодесет и в соответствии с ct_encoding выбрать нужный
"назначатель".
При обратном преобразовании, по "назначателю" находится нужное название
чарсета, а потом среди кодесетов ищется тот, где это название встречается
в ct_encoding. Ну и делается дальнейшее преобразование.
Для iso8859 достаточно, чтобы в каждом кодесете был указан один чарсет.
Для GL - ISO8859-1:GL, а для GR - какой-нибудь "национальный", например -
KOI8-R:GR.
Но обычно, в GL указывают и "национальный":GL. По-видимому, для того,
чтобы конверторы не вставляли лишних "назначателей", если в потоке
GR кодов встретится GL. Хотя при нормальной реализации, этого и так не должно
быть.
А вот то, что в GR, кроме KOI8-R:GR добавлен и ISO8859-1:GR - "обход бага".
Вообще-то, это - нонсенс. Если GL для обоих чарсетов не отличется и можно
такие байты (0-128) интерпретировать как членов любого из этих чарсетов,
то в части GR эти чарсеты, как известно, не совпадают.
А "трюк" этот понадобился из-за того, что конверторы из ct неправильно
находили (сейчас это вроде бы уже исправили) по нестандартному "назначателю"
нужное название чарсета и заменяли его на "дефолтовый" ISO8859-1:GR.
Естественно, чтобы они могли найти среди кодесетов нужный - приходилось
вписывать в него и этот "дефолтовый" чарсет.
В некоторых CJK могут встретиться в описании кодесета некоторые другие
"слова". Но о них позже.
Продолжение следует...
--
Ivan U. Pascal | e-mail: pascal@tsu.ru
Administrator of | Tomsk State University
University Network | Tomsk, Russia