| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |
размер получается от одного до шести байт, итого: 6, 12, 16, 22, 28 и 34 бита
полезной информации. Для дальнейшего расширения предполагается зарезервировать
"лишнюю" страницу двухбайтной последовательности (с ведущим байтом: 10111111
т.е. BF); проблема забоя решается за счет того, что ведущим байтом из всех
единиц — FF придётся пожертвовать.
Хотя если ограничиться трёхбайтными символами — 18 полезных битов (что
даже уникоду — за глаза: там из миллиона зарезервированных позиций заполнено
чуть более ста тысяч, а 2^18 это 256 тысяч) то можно и проще: если два старших
бита = 11, то байтов продолжения всегда два.
Кстати, это позволяет сделать комбинированный вариант с "переключением
регистров": шесть или двенадцать бит номера страницы многобайтного символа
запоминаются и для всех следующих байтов продолжения остаются те же самые,
а символы со старшими битами 00 их не меняют. А возможные расширения (например
переключение кодировок) — за счет "лишней" страницы с ведущим байтом BF.
(Это может быть номер кодировки, упакованной вот таким вот образом.)
Так пожалуй и сделаем. Хотя это конешно чисто на перспективу, но таки
должно получиться раза в полтора компактнее utf-8 — за счет переключения
регистров. Разумеется для нас а не для наглов — для них будет как и для всех
остальных: никаких преимуществ латинскому алфавиту больше не полагается.
И наконец то, что можно условно назвать K-3U, К-3R и К-3П ("К" — потому
что комбинированная) различающиеся между собою только умолчаниями, а от
вышеописанного — самим фактом их наличия. В K-3U по умолчанию упаковывается
уникод, К-3П — П-12 и наконец К-3R — переходная между ними "рациональная"
кодировка...
Будем различать кодировку и её упаковку. Так 20-и битная кодировка
"уникод" упакована в восьмибитные байты пятью (!) разными способами: по четыре
байта на символ что известно как utf-32; по два байта на символ плюс для
символов за пределами "первой плоскости" (т.е. длиннее 16 бит) — "сурогатные
пары"; при чем то и другое — в двух варианта: старшим и младшим байтами вперёд;
и неравномерная utf-8 с одним ключевым битом, описанная выше. (А мы здесь в
Фокале еще, чисто из вредности, добавили к ним трёхбайтный вариант utf-24.)
Соответственно К-3 это способ упаковки РАЗНЫХ кодировок с двумя ключевыми
битами — вот как описано выше: комбинированный неравномерно-регистровый. (Да,
"регистровый" — это только для потока. Но ничто не мешает помещая текст в
память, добавить к каждому ведомому байту причитающиеся ему ведущие,
преобразовать в упаковку utf-8, или полностью распаковать, сделав по 2, 3 или
4 байта на символ.) Указать, какая именно кодировка вот так упакована, можно в
любой момент с помощью символа на "лишней" странице с ведущим байтом BF. (Хотя
я вот сейчас засомневался — правильно ли это? Может назначить "лишней" самую
первую страницу с ведущим байтом 80, или даже какую-то в середине... Подумаем.)
Но изначально, пока такое указание не поступило — действуют умолчания. Для
K-3U упаковывается уникод, вернее первые его 4 "плоскости", которых ему — за
глаза. Для К-3П соответственно наша промежуточная П-12, а вот для К-3R то, что
описано ниже:
— в качестве нулевой страницы — первые 64 символа ASCII
— следующие 64 (где латинские буквы и еще 11 полезных символов) — далеко не
под первым номером, но включена по-умолчанию. То есть пока не встретилось ни
одного не-ASCII-шного символа, от ASCII это ничем не отличается...
— остальные страницы — скроены из фрагментов уникода. Но под каждый алфавит
или силабарий — целое число 64-символьных страниц. Под алфавиты с заглавными и
строчными буквами — по две соседние. Так девангари — один в один. Другие пока
что малознакомые нам алфавиты — тоже. А русский — две страницы, где заглавные
с кода 410 — с начала первой страницы, а четвертушка с буквой Ё и
дополнительными символами для славянских языков, которая с кода 400 — после
них. Для строчных проще: с 430 по 45F.
— для латинского алфавита — никаких куч букв А с разными черточками.
(И никаких дополнительных страниц, где в уникоде весь этот мусор размещается!)
Все эти многочисленные символы с дополнительными элементами образуются из
основных с помощью ВШ (шаг назад) и одного из символов нулевой страницы. Так
например кружочек над буквой указывается звёздочкой, точка — точкой, а умляут
(двоеточие) — двоеточием. (А под сопутствующий мусор выделить специальную
мусорную страницу из резерва первых страниц, там же где и псевдографика.)
Хотя здесь надо иметь в виду способ отображения всех этих символов на
экране. Если он графический — то как указано выше. Если же текстовый (то есть
выводится только код символа, а в знакогенераторе должно быть энное количество
картинок для каждого из таких кодов) — то таки придётся выделить пару страниц
под расширения латинского алфавита.
(Примечание: что-то не видно, чтобы ИСО, сооружая свой пресловутый
стандарт ИСО-8859 заботилось вот о таком отображении символов: нефига было
пихать всем дополнительные 32 никому не нужных управляющих кодов — глядишь,
для латиницы не 10 кодировок бы понадобилось а одна, ну максимум две.)
Упоминавшийся "курсив", он же "системный алфавит" (типа чтобы командовать
операционной системой — алфавит по-умолчанию) построенный по "типографскому"
принципу, так же как, например, уже упоминавшиеся УПК и ДКОИ: русские буквы и
плюс к ним не совпадающие с ними по написанию латинские. Русские буквы в первой
половине страницы — как "основные", а все остальные (начиная с буквы Ё) — во
второй как "дополнительные". Но по "фонетическому" принципу: В-V а не W!
Осталась масса свободных позиций, куда можно поместить буквы "с элементами":
эсперантские "со шляпами", немецкие "с умляутами" плюс "гросе-ЭС; некоторые
буквы из телеграфной азбуки: N E A-с_кружочком (уж коли они там удостоились
отдельных позиций, значит и в самом деле кому-то реально нужны).
А если сделать еще и маленькие курсивные буквы, то вместе с нулевой
страницей и псевдографикой получится вполне себе самодостаточная восьмибитная
кодировка. Но с проблемами. Во-первых дополнительные маленькие буквы не совсем
такие-же как заглавные:
v d ё z i j k l r s t f h q w
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я
V G Ё Z I J L N R S U F Q Y W
о гр. ^ ^ : ^ ^ ^ ~ ' : :
А Эс G J O H C S N E U A
А во-вторых с одной стороны всё равно остаются незанятые позиции (но занять-то
их придумаем чем — например некоторыми из букв греческого алфавита), при этом
на одну позицию претендуют сразу несколько символов. Позиция буквы Ж в
Эсперанто это J-со_шляпой, но Z-со_шляпой было бы логичнее. (Хотя вот как раз
это — вопрос шрифта а не кодировки!) И сюда же (вслед за телетайпетной МКТТ-2)
обычно относят букву V, а W — на место В-русской, что по-моему неправильно.
Вот только приткнуть эту самую лигатуру W получается реально некуда. И в
позицию буквы Д так и просится G-со_шляпой, обозначающая звук ДЖ, но тогда
некуда будет приткнуть букву Д-маленькая_латинская, таки отличающуся от
русской по написанию. По поводу Н-со_шляпой и мелкой латинской h — то же самое.
Так что придётся пойти на ряд компромисов: сделать написание Д-строчной
русской такое, чтобы её можно было принять и за Д-строчное латинское, а не как
рукописное, совпадающее с G-строчной латинской. Соответственно такую букву
поместить как парную к Г-маленькой. Парной к Д и большой и маленькой ДЖ в виде
G со шляпой. Эсперантскую h-со шляпой, обозначающую непридыхательную Х
совпадающую по звучанию с русскою, так и придётся перенести в позицию мягкого
знака. Выселив оттуда лигатуру W. Её так уж и быть сохраним — в основном чтобы
строчная изображала за одно и букву омега, но перенесём в позицию буквы Ц.
А в качестве эсперантского У-краткого придётся использовать У-с_умляутом.
(Впрочем, это тоже вопрос шрифта: двоеточие там или черточка.) И получается:
| v g | ё | z i j k l | r s t f h w | | q | | | | |
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я
| | V G | Ё | Z I J L N | R S U F W | | Q | Y | | | |
о гр. ^ ^ : ^ ^ ~ ^ ' : :
А эс G J O C S N H E U A
Итого остаётся 11 свободных позиций. Куда можно поместить буквы альфа,
(где Б-строчное), бета у нас уже есть, гамма (где К-заглавное), дельта, мю, ню
(где М и Н-строчное), пи, ро (где буква П), омега-большое (где Х-заглавное),
фи (на пару к букве У-строчное) и еще что ни будь (например сигма) на пару к Ы.
И еще проблема с преобразованием в другие кодировки, где русские и
латинские буквы — раздельные. Впрочем, у ДКОИ и УПК — то же самое. Ну да с ним
не детей крестить... И вообще, это пока — так, мысли вслух.
Конец лирического отступления.))
Однако, вернемся к нашим баранам: одной только базовой кодировки мало,
нужен еще и инструмент для её использования. Который бы что-то делал с
символами, рассматривая их как битовые наборы и/или беззнаковые целые.
Соответственно "что-то" это операции арифметические и побитовые. И разумеется
желательно, чтобы набор этих операций был функционально-полным.
Вот для этого и приспособили %r. Реверс — вещь не больно то нужная. Вот и
нечего фигнёй страдать — пусть чем-то более полезным занимается. И уж коли ему
таки положен аргумент — пусть это и будет операция. А он пусть выполняет её
последовательно над каждым байтом фрагмента под маркером... Ага-ага, а ничего,
что у большинства операций по два операнда? И что промежуточные результаты, в
том числе как символ уникода так и во внутренней кодировке, которую вот только
что обсуждали, будет размером более восьми бит? Это я к тому, что для %r нужно
место, для хранения вот этих вот операндов и промежуточных результатов.
По-моему тут идеально подойдёт примерно такой-же стэк, какой был у советского
программируемого микрокалькулятора Б3-34 (и у МК-56). Всего четыре ячейки, но
хватало. И тут, думаю, хватит. Так что основная тактика — считать очередной
байт на стэк, что-то там с ним сделать и вернуть взад. Или, например, добавить
к содержимому регистра... Но это не одна, а несколько операций. А что нам
мешает передать %r несколько, заключив их в скобки или в кавычки?
Но у нас ведь куда конь с копытом, туда и рак с клешнёй: %R которому тоже
делать особо нечего, тоже пожелал во всём этом поучаствовать! Только возиться
с каждым из байтов, как %r, ему в лом (слишком вишь мелко, для такого
солидного!) — хочет чтобы со всем фрагментом одним махом, рассматривая его как
единое число или битовый набор. В результате получилась арифметика
неограниченной точности, правда пока только целочисленная. (Но, например,
чтобы поэкспериментировать с кодами Рида-Соломона — уже достаточно.)
Набор операций и для %r и для %R практически один и тот же: включает
арифметические и логические (вернее побитовые) операции и выполняется над
числами, снимаемыми с вершины собственного операционного стэка. И туда же
помещается результат. Но для %r его ячейки — это просто целые числа, в
данный момент 32-х разрядные, а для %R — аналог регистров форматного механизма,
содержащих многобайтные значения неопределенной длины.
Каждая операция тоже (как правило) обозначается одним символом:
, . ; -чтение, запись и обмен с фрагментом строки под маркером
[ ] : @ -дублирование, удаление, обмен пары и черырёх ячеек стэка
& | ^ ~ -побитовые операции И, ИЛИ, исключающее ИЛИ и инверсия.
+ — * / — арифметические операции. Деление даёт сразу и частное и остаток.
^ $ % — лентяйская арифметика — без переносов (якобы "с полиномами")
Но некоторые — таки двумя символами ( < > = # приходится уточнять):
N -циклический сдвиг на 0..9 разрядов (N — одна цифра);
<< >> -нециклический сдвиг на указанное первым аргументом число битов
< <= > >= = <> >< -"предикаты": сравнивают две верхние ячейки стэка
#N =N #X =X -(где N — цифра, X — буква) чтение/запись регистра и переменной
`А -ввод константы — кода указанного символа (кавычка — любая)
А так же и константы в виде числа:
NNN 0xNNN 0oNNN 0bNNN -в 10-ой, 16-й, 8-ой и двоичной системе счисления
Однако спецсимволов мало, пришлось пустить в ход и буковки. Уже известные:
б д в к и у -преобразовать операнд из указанной буквой кодировки в П-12
Б Д В К И У -преобразовать из П-12 обратно в указанную (Б — в текущую)
u U -прочитать и записать один символ уникода
(впрочем — всё это только и исключительно для %r)
Но так же и:
r R -сгенерировать и поместить на стэк псевдослучайное число
ч х (или 'h') -определить четность и вычислить код хеминга
л -получить размер ненулевой части операнда (в байтах)
m -создать "маску" из указанного операндом количества единичных битов
i -получить индекс (номер) текущего байта в обрабатываемом фрагменте
l -получить количество оставшихся байт (то и другое — только для %r)
i N -получить и установить "номинальный" размер операнда (только для %R)
l L -получить и установить размер операнда (в байтах) (только для %R)
А а -запись текущего значения в числовой аккумулятор А1 и чтение из него
F f -запись логического результата предыдущей операции в А1 как -1 0 +1
Дело в том, что предикаты, не изменяя операндов, вырабатывают некий
логический результат — "статус", как-то действующий на следующую операцию.
Впрочем, большинство операций его игнорирует, а сами вырабатывают
"нейтральный". Но вот следующие:
M S -константы ("младший" и "старший") дают отрицательный и положительный
p n c -операции ("позитив", "негатив" и "циклатив") — изменяют
? -выполняют или пропускают следующую за ними операцию, (или группу)
( ) -заключают в себе группу операций; для статуса "прозрачны" (не меняют)
{ } -цикл: { запоминает место; } переход к запомненному. Баланс, в отличии
от круглых скобок — не отслеживается: цикл может быть только один.
! -немедленно прекращает выполнение последовательности операций (для %r
только для очередного байта и провоцирует переход к следующему; чтобы — совсем,
надо совершить серьёзную ошибку, типа деления на ноль)
Как видим — имеются даже некоторые средства управления порядком действий.
Это не всё — но за кадром осталась еще буквально парочка операций.
Логические константы M S происходят от слов "младший" и "старший" потому
что влияют еще и на следующее непосредственно за ними обращение к регистру
=N и #N организуя "вагонку" — не замену или считывание целиком находящегося в
| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |