procedure DecodeASCII85(ASource:
string;
var ADest: TFPVUByteArray);
var
CurSrcPos, CurDestPos: Integer;
lDataDWordPtr: PCardinal;
lDataCurChar: Char;
begin
SetLength(ADest, 0);
CurDestPos := 0;
CurSrcPos := 1;
while CurSrcPos <= Length(ASource)
do
begin
lDataCurChar := ASource[CurSrcPos];
// Compressed block of zeroes
if lDataCurChar = '
z'
then
begin
SetLength(ADest, Length(ADest)+4);
ADest[CurDestPos] := 0;
ADest[CurDestPos+1] := 0;
ADest[CurDestPos+2] := 0;
ADest[CurDestPos+3] := 0;
Inc(CurDestPos, 4);
Inc(CurSrcPos, 1);
Continue;
end;
// Common block of data: 5 input bytes generate 4 output bytes
SetLength(ADest, Length(ADest)+4);
lDataDWordPtr := @(ADest[CurDestPos]);
if CurSrcPos+4 <= Length(ASource)
then
begin
lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
+ (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
+ (Byte(ASource[CurSrcPos+3])-33)*85 + (Byte(ASource[CurSrcPos+4])-33);
lDataDWordPtr^ := NToBE(lDataDWordPtr^);
end
else if CurSrcPos+3 <= Length(ASource)
then
begin
lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
+ (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
+ (Byte(ASource[CurSrcPos+3])-33)*85 + (Byte('
u')-33);
lDataDWordPtr^ := NToBE(lDataDWordPtr^);
SetLength(ADest, Length(ADest)-1);
end
else if CurSrcPos+2 <= Length(ASource)
then
begin
lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
+ (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
+ (Byte('
u')-33)*85 + (Byte('
u')-33);
lDataDWordPtr^ := NToBE(lDataDWordPtr^);
SetLength(ADest, Length(ADest)-2);
end
else if CurSrcPos+1 <= Length(ASource)
then
begin
lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
+ (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte('
u')-33)*85*85
+ (Byte('
u')-33)*85 + (Byte('
u')-33);
lDataDWordPtr^ := NToBE(lDataDWordPtr^);
SetLength(ADest, Length(ADest)-3);
end
else
begin
raise Exception.Create('
[DecodeASCII85] Too few bytes remaining to decode!');
end;
Inc(CurDestPos, 4);
Inc(CurSrcPos, 5);
end;
end;