Интернет решения от доктора Боба | страница 3
Три символа из входного фала (3 * 8 = 24 бита) кодируются в четыре символа, так что каждый из них содержит только 6 бит, то есть значения от 0 до 63.
Результат затем используется как индекс в таблицу набора символов UUEncode.
Так как каждый кодированный символ представляет из себя простой символ таблицы ASCII начинающийся с позиции 33 и до позиции 64 + 32 = 96, то мы можем просто прибавить ASCII значение символа пробела, что бы получить требуемый UUкодированный символ.
Алгоритм преобразовывает три двоичных символа (Triplet) в четыре (Kwartet) UUкодированных символа и может быть реализован в Паскале следующим образом.
>procedure Triplet2Kwartet(const Triplet: TTriplet; var Kwartet: TKwartet);
> var
> i: Integer;
> begin
> Kwartet[0] := (Triplet[0] SHR 2);
> Kwartet[1] := ((Triplet[0] SHL 4) AND $30) +
> ((Triplet[1] SHR 4) AND $0F);
> Kwartet[2] := ((Triplet[1] SHL 2) AND $3C) +
> ((Triplet[2] SHR 6) AND $03);
> Kwartet[3] := (Triplet[2] AND $3F);
> for i:=0 to 3 do
> if Kwartet[i] = 0 then
> Kwartet[i] := $40 + Ord(SP)
> else Inc(Kwartet[i], Ord(SP))
> end{Triplet2Kwartet};
Данная процедура состоит из из двух частей: в первой части 24 бита (3 * 8) из триплета преобразовываются в 24 бита (4 * 6) квартета. Во второй части алгоритма, мы добавляем ASCII код символа пробела к каждому квартету. ASCII код символа пробела закодирован как Ord(SP), где SP определен как символ пробела или #32. Заметим, что для случая когда квартет равен 0, то мы не добавляем значение #32, поскольку многие почтовые программы имеют проблемы с этим символом, просто в этом случае добавляем код со значением 64 ($40), в результате получаем вместо пробела код обратного апострофа, который нейтрален к алгоритму декодирования, одинаково работающий как для пробела так и для апострофа.
Говоря о декодировании, реализация его в Паскале преобразования квартетов обратно в триплеты следующая:
>procedure Kwartet2Triplet(const Kwartet: TKwartet; var Triplet: TTriplet);
> var
> i: Integer;
> begin
> Triplet[0] := ((Kwartet[0] - Ord(SP)) SHL 2) +
> (((Kwartet[1] - Ord(SP)) AND $30) SHR 4);
> Triplet[1] := (((Kwartet[1] - Ord(SP)) AND $0F) SHL 4) +
> (((Kwartet[2] - Ord(SP)) AND $3C) SHR 2);
> Triplet[2] := (((Kwartet[2] - Ord(SP)) AND $03) SHL 6) +
> ((Kwartet[3] - Ord(SP)) AND $3F)
> end{Kwartet2Triplet};
Если размер триплета в файле менее 3 байт (4 байта в квартете), то производится добавление структуры нулями при кодировании и декодировании.