процедура состоит из из двух частей: в первой части 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 байта в квартете), то производится добавление структуры нулями при кодировании и декодировании.
1.1.2. XXEncode и XXDecode
UUкодирование было наиболее популярным форматом 64 битного кодирования. Ограничение состояло в том, что набор символов не мог транслироваться между наборами ASCII и EBCDIC (IBM мейнфреймы). XXencode очень похож на UUEncode, просто используется другой набор символов, что более удобно между различными типами систем, например как указано выше между EBCDIC и ASCII.
Набор символов XXEncode
0 +
8 6
16 E
24 M
32 U
40 c
48 k
56 s
1 –
9 7
17 F
25 N
33 V
41 d
49 l
57 t
2 0
10 8
18 G
26 O
34 W
42 e
50 m
58 u
3 1
11 9
19 H
27 P
35 X
43 f
51 n
59 v
4 2
12 A
20 I
28 Q
36 Y
44 g
52 o
60 w
5 3
13 B
21 J
29 R
37 Z
45 h
53 p
61 x
6 4
14 C
22 K
30 S
38 a
46 i
54 q
62 y
7 5
15 D
23 L
31 T
39 b
47 j
55 r
63 z
Заметим
что если для UUEncodeиспользуется подмножество набора символов ASCII (32..96), то для XXEncode это не так.
Для преобразования процедур Triplet2Kwartet и Kwartet2Triplet для поддержки мы вводим дополнительный массив из 64 символов.
Нам также необходимо модифицировать процедуры Triplet2Kwartet и Kwartet2Triplet следующим образом.
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));
if XXCode then
for i:=0 to 3 do Kwartet[i] := Ord(XX[(Kwartet[i] - Ord(SP)) mod $40])
end{Triplet2Kwartet};
Последние несколько строк новые для процедуры Triplet2Kwartet и мы используем набор символов XXencode для возврата правильно закодированных символов. Помните, что UUEncode возвращает индекс кодированного символа, после чего мы к нему добавляем код #32, так что если XXencode используется после преобразования в UUEncode, то мы должны вычесть 32 и использовать результат как индекс в таблицу символов XXencode.