summaryrefslogtreecommitdiff
path: root/packages/bzip2
diff options
context:
space:
mode:
authormichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-07-23 15:52:29 +0000
committermichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2009-07-23 15:52:29 +0000
commit0843f1fc4dc534ef6c2f1b66dca853df0ee5cf5e (patch)
tree1e8e6febcc026367d674b7b3112ec5466bbe1a7a /packages/bzip2
parent2f54fe8d9cf5db1cbe8ceb190df419f68172405c (diff)
downloadfpc-0843f1fc4dc534ef6c2f1b66dca853df0ee5cf5e.tar.gz
* Added Classes version of BZip2 Stream
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@13430 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/bzip2')
-rw-r--r--packages/bzip2/Makefile132
-rw-r--r--packages/bzip2/Makefile.fpc2
-rw-r--r--packages/bzip2/src/bzip2.pas63
-rw-r--r--packages/bzip2/src/bzip2comn.pp76
-rw-r--r--packages/bzip2/src/bzip2si386.inc31
-rw-r--r--packages/bzip2/src/bzip2stream.pp669
6 files changed, 852 insertions, 121 deletions
diff --git a/packages/bzip2/Makefile b/packages/bzip2/Makefile
index 94ec0f8f5f..8a3c5068f6 100644
--- a/packages/bzip2/Makefile
+++ b/packages/bzip2/Makefile
@@ -1,5 +1,5 @@
#
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2008/10/22]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/06/27]
#
default: all
MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
@@ -265,178 +265,178 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F
override PACKAGE_NAME=bzip2
override PACKAGE_VERSION=2.2.2
ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=bzip2
+override TARGET_UNITS+=bzip2comn bzip2 bzip2stream
endif
override INSTALL_FPCPACKAGE=y
ifeq ($(FULL_TARGET),i386-linux)
@@ -1007,6 +1007,7 @@ endif
ifeq ($(OS_TARGET),go32v2)
STATICLIBPREFIX=
SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),watcom)
STATICLIBPREFIX=
@@ -1014,6 +1015,7 @@ OEXT=.obj
ASMEXT=.asm
SHAREDLIBEXT=.dll
SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),linux)
BATCHEXT=.sh
@@ -1050,6 +1052,7 @@ STATICLIBPREFIX=
SHAREDLIBEXT=.dll
SHORTSUFFIX=os2
ECHO=echo
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),emx)
BATCHEXT=.cmd
@@ -1058,6 +1061,7 @@ STATICLIBPREFIX=
SHAREDLIBEXT=.dll
SHORTSUFFIX=emx
ECHO=echo
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),amiga)
EXEEXT=
@@ -1097,17 +1101,20 @@ ifeq ($(OS_TARGET),netware)
EXEEXT=.nlm
STATICLIBPREFIX=
SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
endif
ifeq ($(OS_TARGET),netwlibc)
EXEEXT=.nlm
STATICLIBPREFIX=
SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
endif
ifeq ($(OS_TARGET),macos)
BATCHEXT=
EXEEXT=
DEBUGSYMEXT=.xcoff
SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
endif
ifeq ($(OS_TARGET),darwin)
BATCHEXT=.sh
@@ -1134,14 +1141,17 @@ STATICLIBEXT=.a1
SHAREDLIBEXT=.so1
STATICLIBPREFIX=
SHORTSUFFIX=v1
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),go32v2)
STATICLIBPREFIX=
SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),watcom)
STATICLIBPREFIX=
SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),linux)
BATCHEXT=.sh
@@ -1188,6 +1198,7 @@ STATICLIBEXT=.ao2
SHAREDLIBEXT=.dll
SHORTSUFFIX=os2
ECHO=echo
+IMPORTLIBPREFIX=
endif
ifeq ($(OS_TARGET),amiga)
EXEEXT=
@@ -1248,6 +1259,7 @@ STATICLIBEXT=.a
SHAREDLIBEXT=.nlm
EXEEXT=.nlm
SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
endif
ifeq ($(OS_TARGET),netwlibc)
STATICLIBPREFIX=
@@ -1259,6 +1271,7 @@ STATICLIBEXT=.a
SHAREDLIBEXT=.nlm
EXEEXT=.nlm
SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
endif
ifeq ($(OS_TARGET),macos)
BATCHEXT=
@@ -1270,6 +1283,7 @@ STATICLIBEXT=.a
EXEEXT=
DEBUGSYMEXT=.xcoff
SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
endif
endif
ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
diff --git a/packages/bzip2/Makefile.fpc b/packages/bzip2/Makefile.fpc
index 892c8ea345..8d86f52c78 100644
--- a/packages/bzip2/Makefile.fpc
+++ b/packages/bzip2/Makefile.fpc
@@ -7,7 +7,7 @@ name=bzip2
version=2.2.2
[target]
-units=bzip2
+units=bzip2comn bzip2 bzip2stream
[require]
package=rtl
diff --git a/packages/bzip2/src/bzip2.pas b/packages/bzip2/src/bzip2.pas
index b577dc1796..331463ddc3 100644
--- a/packages/bzip2/src/bzip2.pas
+++ b/packages/bzip2/src/bzip2.pas
@@ -26,25 +26,9 @@ interface
{$goto on}
-uses objects;
-
-const max_groups=6;
- max_alpha_size=258;
- max_code_len=23;
- group_size=50;
- iter_count=4;
- max_selectors=2+(900000 div group_size);
-
-const mtfa_size=4096;
- mtfl_size=16;
-
-type Tcardinal_array=array [0..899999] of cardinal;
- Pcardinal_array=^Tcardinal_array;
-
- Pcardinal=^cardinal;
- Thuffarray=array[0..max_alpha_size] of cardinal;
- Phuffarray=^Thuffarray;
+uses objects, bzip2comn;
+Type
Tbzip2_decode_stream=object(Tstream)
short:cardinal;
readstream:Pstream;
@@ -100,14 +84,6 @@ type Tcardinal_array=array [0..899999] of cardinal;
destructor done;virtual;
end;
-{A bzip2 stream starts with this:}
-const bzip2_stream_magic='BZh';
-
-{Error codes for stream errorinfo.}
-const bzip2_bad_header_magic =1;
- bzip2_bad_block_magic =2;
- bzip2_endoffile =3;
- bzip2_data_error =4;
implementation
@@ -115,41 +91,6 @@ implementation
{$i bzip2i386.inc}
{$endif}
-procedure hb_create_decode_tables(var limit,base,perm:array of cardinal;
- var length:array of byte;
- minlen,maxlen:byte;alphasize:cardinal);
-
-var pp,i,j,vec:cardinal;
-
-begin
- pp:=0;
- for i:=minlen to maxlen do
- for j:=0 to alphasize-1 do
- if length[j]=i then
- begin
- perm[pp]:=j;
- inc(pp);
- end;
- for i:=0 to max_code_len-1 do
- begin
- base[i]:=0;
- limit[i]:=0;
- end;
- for i:=0 to alphasize-1 do
- inc(base[length[i]+1]);
- for i:=1 to max_code_len-1 do
- inc(base[i],base[i-1]);
- vec:=0;
- for i:=minlen to maxlen do
- begin
- inc(vec,base[i+1]-base[i]);
- limit[i]:=vec-1;
- vec:=vec shl 1;
- end;
- for i:=minlen+1 to maxlen do
- base[i]:=((limit[i-1]+1) shl 1)-base[i];
-end;
-
{*****************************************************************************
Tbzip2_decode_stream
*****************************************************************************}
diff --git a/packages/bzip2/src/bzip2comn.pp b/packages/bzip2/src/bzip2comn.pp
new file mode 100644
index 0000000000..e7c233ac71
--- /dev/null
+++ b/packages/bzip2/src/bzip2comn.pp
@@ -0,0 +1,76 @@
+unit bzip2comn;
+
+interface
+
+const
+ max_groups = 6;
+ max_alpha_size = 258;
+ max_code_len = 23;
+ group_size = 50;
+ iter_count = 4;
+ max_selectors = 2+(900000 div group_size);
+
+ mtfa_size = 4096;
+ mtfl_size = 16;
+
+type
+ TCardinal_array = array [0..899999] of Cardinal;
+ PCardinal_array = ^TCardinal_array;
+
+ PCardinal = ^Cardinal;
+ Thuffarray = array[0..max_alpha_size] of Cardinal;
+ Phuffarray = ^Thuffarray;
+
+{A bzip2 stream starts with this:}
+const bzip2_stream_magic='BZh';
+
+{Error codes for stream errorinfo.}
+const
+ bzip2_bad_header_magic = 1;
+ bzip2_bad_block_magic = 2;
+ bzip2_endoffile = 3;
+ bzip2_data_error = 4;
+
+procedure hb_create_decode_tables(var limit,base,perm:array of cardinal;
+ var length:array of byte;
+ minlen,maxlen:byte;alphasize:cardinal);
+
+
+implementation
+
+procedure hb_create_decode_tables(var limit,base,perm:array of cardinal;
+ var length:array of byte;
+ minlen,maxlen:byte;alphasize:cardinal);
+
+var pp,i,j,vec:cardinal;
+
+begin
+ pp:=0;
+ for i:=minlen to maxlen do
+ for j:=0 to alphasize-1 do
+ if length[j]=i then
+ begin
+ perm[pp]:=j;
+ inc(pp);
+ end;
+ for i:=0 to max_code_len-1 do
+ begin
+ base[i]:=0;
+ limit[i]:=0;
+ end;
+ for i:=0 to alphasize-1 do
+ inc(base[length[i]+1]);
+ for i:=1 to max_code_len-1 do
+ inc(base[i],base[i-1]);
+ vec:=0;
+ for i:=minlen to maxlen do
+ begin
+ inc(vec,base[i+1]-base[i]);
+ limit[i]:=vec-1;
+ vec:=vec shl 1;
+ end;
+ for i:=minlen+1 to maxlen do
+ base[i]:=((limit[i-1]+1) shl 1)-base[i];
+end;
+
+end. \ No newline at end of file
diff --git a/packages/bzip2/src/bzip2si386.inc b/packages/bzip2/src/bzip2si386.inc
new file mode 100644
index 0000000000..3199a4ec75
--- /dev/null
+++ b/packages/bzip2/src/bzip2si386.inc
@@ -0,0 +1,31 @@
+{$ASMMODE intel}
+
+{$define HAVE_DETRANSFORM}
+
+procedure TDecompressBzip2Stream.detransform;assembler;
+
+asm
+{ mov edx,offset c
+ call mcount}
+ xor edx,edx
+ lea ebx,[esi+TDecompressBzip2Stream.cftab]
+ mov ecx,[esi+TDecompressBzip2Stream.tt_count]
+ push esi
+ push ebp
+ mov esi,[esi+TDecompressBzip2Stream.tt]
+ mov edi,esi
+ lea ebp,[4*ecx+esi]
+ jmp @a2
+@a1:
+ movzx eax,byte [esi]
+ mov ecx,[ebx+4*eax]
+ inc dword [ebx+4*eax]
+ or [edi+4*ecx],edx
+ add edx,$100
+ add esi,4
+@a2:
+ cmp esi,ebp
+ jne @a1
+ pop ebp
+ pop esi
+end ['eax','ebx','ecx','edx','edi'];
diff --git a/packages/bzip2/src/bzip2stream.pp b/packages/bzip2/src/bzip2stream.pp
new file mode 100644
index 0000000000..eaed1513ec
--- /dev/null
+++ b/packages/bzip2/src/bzip2stream.pp
@@ -0,0 +1,669 @@
+{$mode objfpc}
+{$h+}
+unit bzip2stream;
+{****************************************************************************
+
+ BZIP2 decompression unit
+
+ Copyright (C) 2002 by Daniel Mantione
+ Class port (C) 2009 by Michael Van Canneyt
+
+This unit provides a decompression stream to decode .bz2 files. It is
+inpired by Julian R. Seward's libbzip2 library and therefore you should
+send credits to him and bug reports to me :)
+
+This code is licensed under the same terms as the original libbz2 library,
+which is decsribed in the file LICENSE. If you don't have this file, look
+at http://www.freepascal.org for this bzip2 unit, the LICENSE file will
+be included. In case of problems, contact the author.
+
+E-mail addresses:
+
+Michael Van Canneyt <michael@freepascal.org>
+Daniel Mantione <daniel.mantione@freepascal.org>
+Julian R. Seward <jseward@acm.org>
+
+Please do not contact Julian about this Pascal library, he didn't wrote it.
+
+****************************************************************************}
+interface
+
+{$goto on}
+
+uses Classes,SysUtils, bzip2comn;
+
+Type
+ TDecompressBzip2Stream=Class(TOwnerStream)
+ Private
+ block_randomized:boolean;
+ blocksize:byte;
+ tt:Pcardinal_array;
+ tt_count:cardinal;
+ rle_run_left,rle_run_data:byte;
+ nextrle:Pbyte;
+ decode_available:cardinal;
+ block_origin:cardinal;
+ current_block:cardinal;
+ read_data,bits_available:byte;
+ inuse16:set of 0..15;
+ inuse:set of 0..255;
+ inuse_count:cardinal;
+ seq_to_unseq:array[0..255] of byte;
+ alphasize:cardinal;
+ group_count,group_pos,gsel,gminlen:byte;
+ group_no:cardinal;
+ glimit,gperm,gbase:Phuffarray;
+ selector_count:cardinal;
+ selector,selector_mtf:array[0..max_selectors] of byte;
+ len:array[0..max_groups,0..max_alpha_size] of byte;
+ limit:array[0..max_groups,0..max_alpha_size] of cardinal;
+ base:array[0..max_groups,0..max_alpha_size] of cardinal;
+ perm:array[0..max_groups,0..max_alpha_size] of cardinal;
+ minlens:array[0..max_groups] of byte;
+ cftab:array[0..257] of cardinal;
+ mtfbase:array[0..256 div mtfl_size-1] of cardinal;
+ mtfa:array[0..mtfa_size-1] of byte;
+
+ function get_bits(n:byte):byte;
+ function get_boolean:boolean;
+ function get_byte:byte;
+ function get_cardinal24:cardinal;
+ function get_cardinal:cardinal;
+ procedure receive_mapping_table;
+ procedure receive_selectors;
+ procedure undo_mtf_values;
+ procedure receive_coding_tables;
+ procedure make_hufftab;
+ procedure init_mtf;
+ function get_mtf_value:cardinal;
+ procedure move_mtf_block;
+ procedure receive_mtf_values;
+ procedure detransform;
+ function decode_block : boolean;
+ Function new_block : boolean;
+ Function consume_rle : Boolean; inline;
+ Function rle_read(bufptr:Pbyte;count:Longint) : longint;
+ Procedure Error(Msg : String; ACode : Integer);
+ Public
+ Constructor Create(ASource : TStream);
+ Destructor Destroy; override;
+ function Read(var Buffer; Count: Longint): Longint; override;
+ end;
+
+ EBzip2 = Class(Exception)
+ ErrCode : Integer;
+ end;
+
+implementation
+
+{$ifdef i386}
+ {$i bzip2si386.inc}
+{$endif}
+
+{*****************************************************************************
+ TDecompressBzip2Stream
+*****************************************************************************}
+
+Resourcestring
+ BZip2Initialize = 'Invalid BZip2 stream: invalid header';
+ SDecodingError = 'Decoding error';
+ SErrUnimplemented = 'Feature not implemented';
+
+Constructor TDecompressBzip2Stream.Create(ASource: TStream);
+
+var magic:array[1..3] of char;
+ c:char;
+
+begin
+ Inherited Create(ASource);
+ {Read the magic.}
+ Source.ReadBuffer(magic,sizeof(magic));
+ if magic<>bzip2_stream_magic then
+ Error(BZip2Initialize,bzip2_bad_header_magic);
+ {Read the block size and allocate the working array.}
+ Source.ReadBuffer(c,1);
+ blocksize:=byte(c)-byte('0');
+ GetMem(tt,blocksize*100000*sizeof(cardinal));
+ decode_available:=high(decode_available);
+end;
+
+Procedure TDecompressBzip2Stream.Error(Msg : String; ACode : Integer);
+
+Var
+ BE : EBzip2;
+
+begin
+ BE:=EBzip2.Create(Msg);
+ BE.ErrCode:=ACode;
+ Raise BE;
+end;
+
+function TDecompressBzip2Stream.get_bits(n:byte):byte;
+
+var data:byte;
+
+begin
+ if n>bits_available then
+ begin
+ Source.ReadBuffer(data,1);
+ get_bits:=(read_data shr (8-n)) or data shr (8-(n-bits_available));
+ read_data:=data shl (n-bits_available);
+ inc(bits_available,8);
+ end
+ else
+ begin
+ get_bits:=read_data shr (8-n);
+ read_data:=read_data shl n;
+ end;
+ dec(bits_available,n);
+end;
+
+function TDecompressBzip2Stream.get_boolean:boolean;
+
+begin
+ get_boolean:=boolean(get_bits(1));
+end;
+
+function TDecompressBzip2Stream.get_byte:byte;
+
+begin
+ get_byte:=get_bits(8);
+end;
+
+function TDecompressBzip2Stream.get_cardinal24:cardinal;
+
+begin
+ get_cardinal24:=get_bits(8) shl 16 or get_bits(8) shl 8 or get_bits(8);
+end;
+
+
+function TDecompressBzip2Stream.get_cardinal:cardinal;
+
+begin
+ get_cardinal:=get_bits(8) shl 24 or get_bits(8) shl 16 or get_bits(8) shl 8 or
+ get_bits(8);
+end;
+
+procedure TDecompressBzip2Stream.receive_mapping_table;
+
+{Receive the mapping table. To save space, the inuse set is stored in pieces
+ of 16 bits. First 16 bits are stored which pieces of 16 bits are used, then
+ the pieces follow.}
+
+var i,j:byte;
+
+begin
+ inuse16:=[];
+ {Receive the first 16 bits which tell which pieces are stored.}
+ for i:=0 to 15 do
+ if get_boolean then
+ include(inuse16,i);
+
+ {Receive the used pieces.}
+ inuse:=[];
+ inuse_count:=0;
+ for i:=0 to 15 do
+ if i in inuse16 then
+ for j:=0 to 15 do
+ if get_boolean then
+ begin
+ include(inuse,16*i+j);
+ seq_to_unseq[inuse_count]:=16*i+j;
+ inc(inuse_count);
+ end;
+{ system.write('Mapping table: ');
+ for i:=0 to 255 do
+ if i in inuse then
+ system.write(i,' ');
+ writeln;}
+end;
+
+procedure TDecompressBzip2Stream.receive_selectors;
+
+{Receives the selectors.}
+
+var i:cardinal;
+ j:byte;
+
+begin
+ group_count:=get_bits(3);
+ selector_count:=get_bits(8) shl 7 or get_bits(7);
+ for i:=0 to selector_count-1 do
+ begin
+ j:=0;
+ while get_boolean do
+ begin
+ inc(j);
+ if j>5 then
+ error(SDecodingError,bzip2_data_error);
+ end;
+ selector_mtf[i]:=j;
+ end;
+{ system.write('Selector_mtf: ');
+ for i:=0 to selector_count-1 do
+ system.write(selector_mtf[i],' ');
+ writeln;}
+end;
+
+procedure TDecompressBzip2Stream.undo_mtf_values;
+
+{Undo the MTF values for the selectors.}
+
+var pos:array[0..max_groups] of byte;
+ i:cardinal;
+ v,tmp:byte;
+
+begin
+ for v:=0 to group_count-1 do
+ pos[v]:=v;
+ for i:=0 to selector_count-1 do
+ begin
+ v:=selector_mtf[i];
+ tmp:=pos[v];
+ while v<>0 do
+ begin
+ pos[v]:=pos[v-1];
+ dec(v);
+ end;
+ pos[0]:=tmp;
+ selector[i]:=tmp;
+ end;
+end;
+
+procedure TDecompressBzip2Stream.receive_coding_tables;
+
+var t,curr:byte;
+ i:cardinal;
+
+begin
+ for t:=0 to group_count-1 do
+ begin
+ curr:=get_bits(5);
+ for i:=0 to alphasize-1 do
+ begin
+ repeat
+ if not(curr in [1..20]) then
+ error(SDecodingError,bzip2_data_error);
+ if not get_boolean then
+ break;
+ if get_boolean then
+ dec(curr)
+ else
+ inc(curr);
+ until false;
+ len[t,i]:=curr;
+ end;
+ end;
+end;
+
+procedure TDecompressBzip2Stream.make_hufftab;
+
+{Builds the Huffman tables.}
+
+var i:cardinal;
+ t,minlen,maxlen:byte;
+
+begin
+ for t:=0 to group_count-1 do
+ begin
+ minlen:=32;
+ maxlen:=0;
+ for i:=0 to alphasize-1 do
+ begin
+ if len[t,i]>maxlen then
+ maxlen:=len[t,i];
+ if len[t,i]<minlen then
+ minlen:=len[t,i];
+ end;
+ hb_create_decode_tables(limit[t],base[t],perm[t],len[t],
+ minlen,maxlen,alphasize);
+ minlens[t]:=minlen;
+ end;
+end;
+
+procedure TDecompressBzip2Stream.init_mtf;
+
+var i,j:byte;
+ k:cardinal;
+
+begin
+ k:=mtfa_size-1;
+ for i:=256 div mtfl_size-1 downto 0 do
+ begin
+ for j:=mtfl_size-1 downto 0 do
+ begin
+ mtfa[k]:=i*mtfl_size+j;
+ dec(k);
+ end;
+ mtfbase[i]:=k+1;
+ end;
+end;
+
+function TDecompressBzip2Stream.get_mtf_value:cardinal;
+
+var zn:byte;
+ zvec:cardinal;
+
+begin
+ if group_pos=0 then
+ begin
+ inc(group_no);
+ group_pos:=group_size;
+ gsel:=selector[group_no];
+ gminlen:=minlens[gsel];
+ glimit:=@limit[gsel];
+ gperm:=@perm[gsel];
+ gbase:=@base[gsel];
+ end;
+ dec(group_pos);
+ zn:=gminlen;
+ zvec:=get_bits(zn);
+ while zvec>glimit^[zn] do
+ begin
+ inc(zn);
+ zvec:=zvec shl 1 or byte(get_boolean);
+ end;
+ get_mtf_value:=gperm^[zvec-gbase^[zn]];
+end;
+
+procedure TDecompressBzip2Stream.move_mtf_block;
+
+var i:byte;
+ j,k:cardinal;
+
+begin
+ k:=MTFA_SIZE;
+ for i:=256 div MTFL_SIZE-1 downto 0 do
+ begin
+ j:=mtfbase[i];
+ Pcardinal(@mtfa[k- 4])^:=Pcardinal(@mtfa[j+12])^;
+ Pcardinal(@mtfa[k- 8])^:=Pcardinal(@mtfa[j+ 8])^;
+ Pcardinal(@mtfa[k-12])^:=Pcardinal(@mtfa[j+ 4])^;
+ dec(k,16);
+ Pcardinal(@mtfa[k ])^:=Pcardinal(@mtfa[j ])^;
+ mtfbase[i]:=k;
+ end;
+end;
+
+procedure TDecompressBzip2Stream.receive_mtf_values;
+
+const run_a=0;
+ run_b=1;
+
+var t,next_sym:cardinal;
+ es:cardinal;
+ n:byte;
+ nn,i:cardinal;
+ p,q:Pbyte;
+ u,v:Pcardinal;
+ lno,off:cardinal;
+
+begin
+ group_no:=high(group_no);
+ group_pos:=0;
+ t:=0;
+ for i:=0 to 257 do
+ cftab[i]:=0;
+ init_mtf;
+ next_sym:=get_mtf_value;
+ while next_sym<>inuse_count+1 do
+ begin
+{ writeln(t,' ',next_sym);
+ if t=22296 then
+ t:=t; }
+ if next_sym<=run_b then
+ begin
+ es:=0;
+ n:=0;
+ repeat
+ inc(es,(next_sym+1) shl n);
+ inc(n);
+ next_sym:=get_mtf_value;
+ until next_sym>run_b;
+ n:=seq_to_unseq[mtfa[mtfbase[0]]];
+ inc(cftab[n],es);
+ if t+es>100000*blocksize then
+ error(SDecodingError,bzip2_data_error);
+ while es>0 do
+ begin
+ tt^[t]:=n;
+ dec(es);
+ inc(t);
+ end;
+ end
+ else
+ begin
+ nn:=next_sym-1;
+ if nn<mtfl_size then
+ begin
+ {Avoid the costs of the general case.}
+ p:=@mtfa[mtfbase[0]];
+ q:=p+nn;
+ n:=q^;
+ repeat
+ q^:=(q-1)^;
+ dec(q);
+ until q=p;
+ q^:=n;
+ end
+ else
+ begin
+ {General case.}
+ lno:=nn div MTFL_SIZE;
+ off:=nn and (MTFL_SIZE-1);
+ p:=@mtfa[mtfbase[lno]];
+ q:=p+off;
+ n:=q^;
+ while(q<>p) do
+ begin
+ q^:=(q-1)^;
+ dec(q);
+ end;
+ u:=@mtfbase;
+ v:=u+lno;
+ repeat
+ mtfa[v^]:=mtfa[(v-1)^+MTFL_SIZE-1];
+ dec(v);
+ dec(v^);
+ until v=u;
+ mtfa[v^]:=n;
+ if v^=0 then
+ move_mtf_block;
+ end;
+ inc(cftab[seq_to_unseq[n]]);
+ tt^[t]:=cardinal(seq_to_unseq[n]);
+ inc(t);
+ if t>100000*blocksize then
+ error(SDecodingError,bzip2_data_error);
+ next_sym:=get_mtf_value;
+ end;
+ end;
+ tt_count:=t;
+ {Setup cftab to facilitate generation of T^(-1).}
+ t:=0;
+ for i:=0 to 256 do
+ begin
+ nn:=cftab[i];
+ cftab[i]:=t;
+{ writeln(i,' ',t);}
+ inc(t,nn);
+ end;
+end;
+
+{$ifndef HAVE_DETRANSFORM}
+
+procedure TDecompressBzip2Stream.detransform;
+
+var a:cardinal;
+ p,q,r:Pcardinal;
+
+begin
+ a:=0;
+ p:=@tt^[0];
+ q:=p+tt_count;
+ while p<>q do
+ begin
+ r:=@tt^[cftab[p^ and $ff]];
+ inc(cftab[p^ and $ff]);
+ r^:=r^ or a;
+ inc(a,256);
+ inc(p);
+ end;
+end;
+
+{$endif}
+
+function TDecompressBzip2Stream.decode_block:boolean;
+
+{Decode a new compressed block.}
+
+var magic:array[1..6] of char;
+ stored_blockcrc:cardinal;
+ i:byte;
+
+begin
+ for i:=1 to 6 do
+ magic[i]:=char(get_byte);
+ if magic='1AY&SY' then
+ begin
+ inc(current_block);
+ stored_blockcrc:=get_cardinal;
+ block_randomized:=get_boolean;
+ block_origin:=get_cardinal24;
+
+ {Receive the mapping table.}
+ receive_mapping_table;
+ alphasize:=cardinal(inuse_count)+2;
+
+ {Receive the selectors. Raises exception}
+ receive_selectors;
+ {Undo the MTF values for the selectors.}
+ undo_mtf_values;
+ {Receive the coding tables.}
+ receive_coding_tables;
+ {Build the Huffman tables.}
+ make_hufftab;
+ {Receive the MTF values.}
+ receive_mtf_values;
+ {Undo the Burrows Wheeler transformation.}
+ detransform;
+ decode_available:=tt_count;
+ Result:=True;
+ end
+ else
+ begin
+ if magic<>#$17'rE8P'#$90 then
+ error(SDecodingError,bzip2_bad_block_magic);
+ Result:=false;
+ end;
+end;
+
+Function TDecompressBzip2Stream.new_block : Boolean;
+
+begin
+ Result:=decode_block;
+ If result then
+ nextrle:=@tt^[tt^[block_origin] shr 8]
+ else
+ nextrle:=nil;
+end;
+
+Function TDecompressBzip2Stream.consume_rle : Boolean;inline;
+
+{Make nextrle point to the next decoded byte. If nextrle did point to the last
+ byte in the current block, decode the next block.}
+
+begin
+{ Pcardinal(nextrle)^:=Pcardinal(nextrle)^ shr 8;}
+ nextrle:=@tt^[Pcardinal(nextrle)^ shr 8];
+ dec(decode_available);
+ if decode_available=0 then
+ Result:=new_block
+ else
+ Result:=True;
+end;
+
+Function TDecompressBzip2Stream.rle_read(bufptr:Pbyte;Count:Longint) : LongInt;
+
+var rle_len:cardinal;
+ data:byte;
+
+label rle_write;
+
+begin
+ Result:=0;
+ rle_len:=rle_run_left;
+ data:=rle_run_data;
+ if block_randomized then
+ {Not yet implemented.}
+ Error(SErrUnimplemented,-1)
+ else
+ begin
+ if rle_len<>0 then
+ {Speed is important. Instead of an if statement within the
+ repeat loop use a goto outside the loop.}
+ goto rle_write;
+ repeat
+ if decode_available=0 then
+ break;
+ rle_len:=1;
+ data:=nextrle^;
+ if consume_rle and (decode_available>0) and (data=nextrle^) then
+ begin
+ inc(rle_len);
+ if consume_rle and (decode_available>0) and (data=nextrle^) then
+ begin
+ inc(rle_len);
+ if consume_rle and (decode_available>0) and (data=nextrle^) then
+ begin
+ if consume_rle then
+ inc(rle_len,nextrle^+1);
+ consume_rle;
+ end;
+ end;
+ end;
+rle_write:
+ repeat
+ bufptr^:=data;
+ inc(bufptr);
+ dec(count);
+ dec(rle_len);
+ inc(Result);
+ until (rle_len=0) or (count=0);
+ until count=0;
+ end;
+ rle_run_data:=data;
+ rle_run_left:=rle_len;
+end;
+
+Function TDecompressBzip2Stream.Read(var Buffer; Count : Longint) : LongInt;
+
+var bufptr:Pbyte;
+
+begin
+ bufptr:=@buffer;
+ if decode_available=high(decode_available) then
+ begin
+ {Initialize the rle process:
+ - Decode a block
+ - Initialize pointer.}
+ system.Write('.');
+ if not decode_block then
+ begin
+ nextrle:=nil;
+ error(SDecodingError,bzip2_endoffile);
+ end;
+ nextrle:=@tt^[tt^[block_origin] shr 8];
+ end;
+ Result:=rle_read(bufptr,count);
+end;
+
+Destructor TDecompressBzip2Stream.Destroy;
+
+begin
+ if tt<>nil then
+ FreeMem(tt,blocksize*100000*sizeof(cardinal));
+ Inherited;
+end;
+
+end.