05.09.2013, 10:20
|
Прохожий
|
|
Регистрация: 26.02.2013
Сообщения: 30
Версия Delphi: Lazarus, XE 3.
Репутация: 10
|
|
Декомпрессия алгоритма snappy от Google
Не так давно потребовалось распаковать на Delphi файлик сжатый snappy, в связи с чем и была написана данная функция. Работает как в Delphi так и в Lazarus.
Сжатие мне было не нужно, поэтому я его особо не ковырял.
Код:
procedure SnappyDecompress(Input: TByteArray; Offset,
Length: integer; var Output: TByteArray);
var
i, l, o, c,targetIndex,SourceIndex,targetLength: integer;
function incPP(var AVal: integer): integer;
begin
result := AVal;
inc(AVal);
end;
begin
sourceIndex:=offset;
targetIndex:=0;
targetLength:=0;
i:=0;
repeat
targetLength := targetLength + (input[sourceIndex] and $7f) shl (incPP(i) * 7);
until ((input[incPP(sourceIndex)] and $80) <> $80);
SetLength(Output,targetLength);
while (sourceIndex < offset + length) do
begin
if(targetIndex >= targetLength) then
raise Exception.Create('Superfluous input data encountered on offset '+IntToStr(sourceIndex));
case (input[sourceIndex] and 3) of
0: begin
l := (input[incPP(sourceIndex)] shr 2) and $3f;
case l of
60: begin
l := input[incPP(sourceIndex)] and $ff;
inc(l);
end;
61:
begin
l := input[incPP(sourceIndex)] and $ff;
l := l or ((input[incPP(sourceIndex)]) and $ff);
inc(l);
end;
62:
begin
l := input[incPP(sourceIndex)] and $ff;
l :=l or ((input[IncPP(sourceIndex)] and $ff) shl 8);
l :=l or ((input[IncPP(sourceIndex)] and $ff) shl 16);
inc(l);
end;
63:
begin
l := input[IncPP(sourceIndex)] and $ff;
l := l or ((input[IncPP(sourceIndex)] and $ff) shl 8);
l := l or ((input[IncPP(sourceIndex)] and $ff) shl 16);
l := l or ((input[IncPP(sourceIndex)] and $ff) shl 24);
inc(l);
end
else
inc(l);
end;
Move(Input[sourceIndex],Output[targetIndex],l);
sourceIndex := sourceIndex + l;
targetIndex :=targetIndex + l;
end;
1:
begin
l := 4 + ((input[sourceIndex] shr 2) and 7);
o := (input[IncPP(sourceIndex)] and $e0) shl 3;
o := o or (input[incPP(sourceIndex)] and $ff);
if (l < o) then
begin
move(output[targetIndex - o],output[targetIndex],l);
targetIndex:=targetIndex + l;
end
else
begin
if (o = 1) then
begin
FillChar(Output[targetIndex],l,output[targetIndex-l]);
targetIndex:= targetIndex + l;
end
else
begin
while (l > 0) do
begin
c:= ifthen( L > o, o, l);
Move(output[targetIndex-o],output[targetIndex],c);
targetIndex:= targetIndex + c;
l:= l - c;
end;
end;
end;
end;
2:
begin
l := ((input[IncPP(sourceIndex)] shr 2) and $3f) + 1;
o := input[IncPP(sourceIndex)] and $ff;
o := o or ((input[IncPP(sourceIndex)] and $ff) shl 8);
if (l < o) then
begin
move(output[abs(targetIndex - o)],output[targetIndex],l);
targetIndex:=targetIndex + l;
end
else
begin
if (o = 1) then
begin
FillChar(Output[targetIndex],l,output[targetIndex-l]);
targetIndex:= targetIndex + l;
end
else
begin
while (l > 0) do
begin
c:= ifthen( L > o, o, l);
Move(output[targetIndex-o],output[targetIndex],c);
targetIndex:= targetIndex + c;
l:= l - c;
end;
end;
end;
end;
3:
begin
l := ((input[IncPP(sourceIndex)] shr 2) and $3f) + 1;
o := input[IncPP(sourceIndex)] and $ff;
o := o or ((input[IncPP(sourceIndex)] and $ff) shl 8);
o := o or ((input[IncPP(sourceIndex)] and $ff) shl 16);
o := o or ((input[IncPP(sourceIndex)] and $ff) shl 24);
if (l < o) then
begin
move(output[targetIndex - o],output[targetIndex],l);
targetIndex:=targetIndex + l;
end
else
begin
if (o = 1) then
begin
FillChar(Output[targetIndex],l,output[targetIndex-l]);
targetIndex:= targetIndex + l;
end
else
begin
while (l > 0) do
begin
c:= ifthen( L > o, o, l);
Move(output[targetIndex-o],output[targetIndex],c);
targetIndex:= targetIndex + c;
l:= l - c;
end;
end;
end;
end;
end;
end;
end;
|