home *** CD-ROM | disk | FTP | other *** search
- {You won't get that sort of compression from my routines, but here
- they are anyway. When testing, you'll get best compression if you
- use English and longish Strings.
- }
- Unit Compress;
-
- Interface
-
- Const
- CompressedStringArraySize = 500; { err on the side of generosity }
-
- Type
- tCompressedStringArray = Array[1..CompressedStringArraySize] of Byte;
-
- Function GetCompressedString(Arr : tCompressedStringArray) : String;
-
- Procedure CompressString(st : String; Var Arr : tCompressedStringArray;
- Var len : Integer);
- { converts st into a tCompressedStringArray of length len }
-
- Implementation
-
- Const
- FreqChar : Array[4..14] of Char = 'etaonirshdl';
- { can't be in [0..3] because two empty bits signify a space }
-
-
- Function GetCompressedString(Arr : tCompressedStringArray) : String;
- Var
- Shift : Byte;
- i : Integer;
- ch : Char;
- st : String;
- b : Byte;
-
- Function GetHalfNibble : Byte;
- begin
- GetHalfNibble := (Arr[i] shr Shift) and 3;
- if Shift = 0 then begin
- Shift := 6;
- inc(i);
- end else dec(Shift,2);
- end;
-
- begin
- st := '';
- i := 1;
- Shift := 6;
- Repeat
- b := GetHalfNibble;
- if b = 0 then
- ch := ' '
- else begin
- b := (b shl 2) or GetHalfNibble;
- if b = $F then begin
- b := GetHalfNibble shl 6;
- b := b or GetHalfNibble shl 4;
- b := b or GetHalfNibble shl 2;
- b := b or GetHalfNibble;
- ch := Char(b);
- end else
- ch := FreqChar[b];
- end;
- if ch <> #0 then st := st + ch;
- Until ch = #0;
- GetCompressedString := st;
- end;
-
- Procedure CompressString(st : String; Var Arr : tCompressedStringArray;
- Var len : Integer);
- { converts st into a tCompressedStringArray of length len }
- Var
- i : Integer;
- Shift : Byte;
-
- Procedure OutHalfNibble(b : Byte);
- begin
- Arr[len] := Arr[len] or (b shl Shift);
- if Shift = 0 then begin
- Shift := 6;
- inc(len);
- end else dec(Shift,2);
- end;
-
- Procedure OutChar(ch : Char);
- Var
- i : Byte;
- bych : Byte Absolute ch;
- begin
- if ch = ' ' then
- OutHalfNibble(0)
- else begin
- i := 4;
- While (i<15) and (FreqChar[i]<>ch) do inc(i);
- OutHalfNibble(i shr 2);
- OutHalfNibble(i and 3);
- if i = $F then begin
- OutHalfNibble(bych shr 6);
- OutHalfNibble((bych shr 4) and 3);
- OutHalfNibble((bych shr 2) and 3);
- OutHalfNibble(bych and 3);
- end;
- end;
- end;
-
- begin
- len := 1;
- Shift := 6;
- fillChar(Arr,sizeof(Arr),0);
- For i := 1 to length(st) do OutChar(st[i]);
- OutChar(#0); { end of compressed String signaled by #0 }
- if Shift = 6
- then dec(len);
- end;
-
- end.