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
;