home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / extra18 / compress / compress.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-01-28  |  13.2 KB  |  369 lines

  1. (* ------------------------------------------------- *)
  2. (*                    COMPRESS.PAS                   *)
  3. (*                                                   *)
  4. (* Die Unit »CompressU« dient zum Komprimieren und   *)
  5. (* Dekomprimieren von beliebigen Daten. Der Algo-    *)
  6. (* rithmus faßt dabei sich wiederholende Bytes in    *)
  7. (* ein Zählbyte und ein Datenbyte zusammen. Treten   *)
  8. (* in einer Datei keine Wiederholungen auf, so ist   *)
  9. (* der Algorithmus ungeeignet, da er die Datei nur   *)
  10. (* vergrößert.                                       *)
  11. (* Die Unit definiert ein Objekt 'compressOBJ', das  *)
  12. (* dem Benutzer 5 Methoden zur Verfügung stellt. Die *)
  13. (* Methode 'Init' muß vor allen anderen einmal auf-  *)
  14. (* gerufen werden, da sie wichtige Initialisierungen *)
  15. (* vornimmt.                                         *)
  16. (* Die Methode 'Compress' komprimiert ihr übergebene *)
  17. (* Daten und gibt sie an die abstrakte Methode       *)
  18. (* 'Write_bytes' weiter.                             *)
  19. (* Die Methode 'Decompress' dekomprimiert Daten, die *)
  20. (* sie aus der abstrakten Methode 'Read_bytes' liest *)
  21. (*                                                   *)
  22. (*       (c) 1991 Uwe Dirksen & DMV-Verlag           *)
  23. (* ------------------------------------------------- *)
  24. UNIT CompressU; 
  25.  
  26. INTERFACE
  27.  
  28. TYPE
  29.   compressOBJ = OBJECT
  30.  
  31.     CONSTRUCTOR Init;
  32.     PROCEDURE   Compress(VAR database;
  33.                          VAR laenge : WORD);
  34.     PROCEDURE   Decompress(VAR database;
  35.                            VAR laenge : WORD);
  36.     PROCEDURE   Read_bytes(VAR database;
  37.                            VAR laenge : WORD);
  38.       VIRTUAL;
  39.     PROCEDURE   Write_bytes(VAR database;
  40.                             VAR laenge : WORD);
  41.       VIRTUAL;
  42.     PRIVATE
  43.     is_command : BOOLEAN;
  44.                          (* TRUE= command enthält    *)
  45.                          (*   restlichen Befehlscode *)
  46.     data       : BYTE;
  47.     command    : WORD;
  48.   END; (* compressOBJ *)
  49.  
  50. IMPLEMENTATION
  51.  
  52.   PROCEDURE compressOBJ.Read_bytes(VAR database;
  53.                                    VAR laenge : WORD);
  54.     (* abstrakte Methode, Definition erfolgt bei     *)
  55.     (* Bildung eines Nachfahren von »compressOBJ«    *)
  56.     (*  IN : laenge   = Anzahl der zu lesenen Bytes  *)
  57.     (* OUT : database = untypisierte Variable        *)
  58.     (*                  ( d.h. Typ ist beliebig )    *)
  59.     (* OUT : laenge   = Länge der wirklich gelesenen *)
  60.     (*                  Bytes                        *)
  61.   BEGIN
  62.   END;
  63.  
  64.   PROCEDURE compressOBJ.Write_bytes(VAR database;
  65.                                     VAR laenge : WORD);
  66.     (* abstrakte Methode, Definition erfolgt bei     *)
  67.     (* Bildung eines Nachfahren von »compressOBJ«    *)
  68.     (*  IN : database = untypisierte Variable        *)
  69.     (*                  ( d.h. Typ ist beliebig )    *)
  70.     (*  IN : laenge   = Anzahl der zu schreibenen    *)
  71.     (*                  Bytes                        *)
  72.     (* OUT : laenge   = Länge der wirklich           *)
  73.     (*                  geschriebenen Bytes          *)
  74.   BEGIN
  75.   END;
  76.  
  77.   CONSTRUCTOR compressOBJ.Init;
  78.   BEGIN
  79.     is_command:= FALSE;
  80.       (* kein restlicher Befehlscode in 'command'    *)
  81.       (* vorhanden                                   *)
  82.   END;
  83.  
  84.   PROCEDURE compressOBJ.Compress(VAR database;
  85.                                  VAR laenge : WORD);
  86.     (* »Compress« komprimiert Daten und gibt sie an  *)
  87.     (* die Methode »Write_bytes« weiter.             *)
  88.     (*  IN : database = untypisierte Variable        *)
  89.     (*                  ( d.h. Typ ist beliebig )    *)
  90.     (*  IN : laenge   = Länge der zu komprimierenden *)
  91.     (*                  Daten in Bytes               *)
  92.     (* OUT : laenge   = Länge der wirklich           *)
  93.     (*                  komprimierten Bytes          *)
  94.   VAR
  95.     Befehlscode,
  96.     Groesse,
  97.     Datum            : BYTE;
  98.     Data_Seg,
  99.     Data_Ofs,
  100.     Anzahl,
  101.     Laenge1,
  102.     Bytes_Write,
  103.     Bytes_Real_Write : WORD;
  104.     Status : (_start, _eins, _compress_a, _compress_b,
  105.               _compress_c, _not_compress_a,
  106.               _not_compress_b, _not_compress_c);
  107.   BEGIN
  108.     Data_Seg         := Seg(database);
  109.     Data_Ofs         := Ofs(database);
  110.     Bytes_Write      := 0;
  111.     Bytes_Real_Write := 0;
  112.     Status           := _start;
  113.     REPEAT
  114.       CASE status OF
  115.         _compress_b :
  116.           BEGIN
  117.             IF datum=Mem[data_seg:data_ofs] THEN BEGIN
  118.               INC(anzahl);
  119.               INC(data_ofs);
  120.             END ELSE
  121.               Status := _compress_c;
  122.           END;
  123.         _compress_a :
  124.           BEGIN
  125.             IF datum=Mem[data_seg:data_ofs] THEN
  126.               status:= _compress_b
  127.             ELSE BEGIN
  128.               status:= _not_compress_a;
  129.               datum:= MEM[data_seg:data_ofs];
  130.             END; (* if *)
  131.             INC (anzahl);
  132.             INC (data_ofs);
  133.           END;
  134.         _not_compress_a :
  135.           BEGIN
  136.             IF datum = MEM[data_seg:data_ofs] THEN
  137.               status:= _not_compress_b
  138.             ELSE
  139.               datum:= MEM[data_seg:data_ofs];
  140.             INC (anzahl);
  141.             INC (data_ofs);
  142.           END;
  143.         _not_compress_b :
  144.           BEGIN
  145.            IF datum = MEM[data_seg:data_ofs] THEN BEGIN
  146.               DEC(anzahl,2);
  147.               DEC(data_ofs,2);
  148.               status := _not_compress_c;
  149.             END ELSE BEGIN
  150.               datum := MEM[data_seg:data_ofs];
  151.               INC(anzahl);
  152.               INC(data_ofs);
  153.               status := _not_compress_a;
  154.             END;
  155.           END;
  156.         _start :
  157.           BEGIN
  158.             datum  := MEM[data_seg:data_ofs];
  159.             anzahl := 1;
  160.             INC(data_ofs);
  161.             status := _eins;
  162.           END;
  163.         _eins :
  164.           BEGIN
  165.             IF datum = MEM[data_seg:data_ofs] THEN
  166.               status := _compress_a
  167.             ELSE BEGIN
  168.               status := _not_compress_a;
  169.               datum  := MEM[data_seg:data_ofs];
  170.             END;
  171.             INC(anzahl);
  172.             INC(data_ofs);
  173.           END;
  174.         _compress_c :
  175.           BEGIN
  176.             befehlscode := 257 - anzahl;
  177.             laenge1 := 1;
  178.             Write_bytes(befehlscode, laenge1);
  179.             Write_bytes(datum, laenge1);
  180.               (* wenn »befehlscode« nicht, »datum«   *)
  181.               (* aber geschrieben werden konnte ->   *)
  182.               (* keine Fehlererkennung               *)
  183.             INC(bytes_write, anzahl);
  184.             IF laenge1 = 1 THEN
  185.               bytes_real_write := bytes_write;
  186.             anzahl := 0;
  187.             status := _start;
  188.           END;
  189.         _not_compress_c :
  190.           BEGIN
  191.             befehlscode := anzahl - 1;
  192.             laenge1     := 1;
  193.             Write_bytes(befehlscode, laenge1);
  194.             laenge1 := anzahl;
  195.             Write_bytes(MEM[data_seg:data_ofs-anzahl],
  196.                         laenge1);
  197.             INC(bytes_write, anzahl);
  198.             INC(bytes_real_write, laenge1);
  199.             anzahl := 0;
  200.             status := _start;
  201.           END;
  202.         END;
  203.         IF (bytes_write+anzahl = laenge) OR
  204.            (anzahl = 127) THEN BEGIN
  205.           IF status = _compress_b THEN
  206.             status := _compress_c
  207.           ELSE
  208.             status := _not_compress_c;
  209.         END;
  210.       UNTIL (bytes_write = laenge) OR
  211.             (bytes_real_write <> bytes_write);
  212.       laenge := bytes_real_write;
  213.     END;
  214.  
  215.     PROCEDURE compressOBJ.Decompress(VAR database;
  216.                                     VAR laenge : WORD);
  217.       (* »Decompress« liest Daten von der Methode    *)
  218.       (* »Read_bytes« und dekomprimiert sie.         *)
  219.       (*  IN : laenge   = Länge der zu dekomprimie-  *)
  220.       (*                  renden Daten in Bytes      *)
  221.       (* OUT : database = untypisierte Variable      *)
  222.       (*                  ( d.h. Typ ist beliebig )  *)
  223.       (* OUT : laenge   = Länge der wirklich dekom-  *)
  224.       (*                  primierten Bytes           *)
  225.     VAR
  226.       commandlaenge : BYTE;
  227.       laenge1       : WORD;
  228.  
  229.       PROCEDURE Read_compress_data(VAR database;
  230.                                    VAR laenge : WORD);
  231.         (* »Read_compress_data« liest Daten von der  *)
  232.         (* Methode »Read_bytes« und dekomprimiert    *)
  233.         (* sie.                                      *)
  234.         (*  IN : laenge   = Länge der zu dekompri-   *)
  235.         (*                  mierenden Daten in Bytes *)
  236.         (* OUT : database = untypisierte Variable    *)
  237.         (*                 ( d.h. Typ ist beliebig ) *)
  238.         (* OUT : laenge   = Länge der wirklich dekom-*)
  239.         (*                  primierten Bytes         *)
  240.       VAR
  241.         ende : BOOLEAN;
  242.         commandlaenge : BYTE;
  243.         laenge1,data_seg,data_ofs,bytes_read : WORD;
  244.       BEGIN
  245.         data_seg   := Seg(database);
  246.         data_ofs   := Ofs(database);
  247.         bytes_read := 0;
  248.         ende       := FALSE;
  249.         command    := 0;
  250.         REPEAT
  251.           laenge1 := 1;
  252.           Read_bytes(command, laenge1);
  253.           IF laenge1 = 1 THEN BEGIN
  254.             IF command < 128 THEN BEGIN
  255.               commandlaenge := BYTE(command)+1;
  256.               IF laenge <= commandlaenge THEN BEGIN
  257.                 laenge1 := laenge;
  258.                 Read_bytes(MEM[data_seg:data_ofs +
  259.                                bytes_read], laenge1);
  260.                 IF laenge1 = commandlaenge THEN
  261.                   is_command := FALSE
  262.                 ELSE BEGIN
  263.                   DEC(command, laenge1);
  264.                   is_command := TRUE;
  265.                 END;
  266.                 laenge := bytes_read + laenge1;
  267.                 ende   := TRUE;
  268.               END ELSE BEGIN
  269.                 laenge1 := commandlaenge;
  270.                 Read_bytes(MEM[data_seg:data_ofs +
  271.                                bytes_read], laenge1);
  272.                 IF laenge1 = commandlaenge THEN BEGIN
  273.                   INC(bytes_read, laenge1);
  274.                   DEC(laenge, laenge1);
  275.                 END ELSE BEGIN
  276.                   laenge := bytes_read + laenge1;
  277.                   ende   := TRUE;
  278.                 END;
  279.               END;
  280.             END ELSE BEGIN   (* command  > 128 *)
  281.               commandlaenge := BYTE(257 - command);
  282.               laenge1 := 1;
  283.               Read_bytes(data, laenge1);
  284.               IF laenge1 = 1 THEN BEGIN
  285.                 IF laenge <= commandlaenge THEN BEGIN
  286.                   FillChar(MEM[data_seg:data_ofs +
  287.                             bytes_read], laenge, data);
  288.                   IF laenge = commandlaenge THEN
  289.                     is_command := FALSE
  290.                   ELSE BEGIN
  291.                     INC(command, laenge);
  292.                     is_command := TRUE;
  293.                   END;
  294.                   INC(laenge, bytes_read);
  295.                   ende := TRUE;
  296.                 END ELSE BEGIN
  297.                   FillChar(MEM[data_seg:data_ofs +
  298.                              bytes_read],commandlaenge,
  299.                              data);
  300.                   INC(bytes_read, commandlaenge);
  301.                   DEC(laenge, commandlaenge);
  302.                 END;
  303.               END ELSE BEGIN
  304.                 laenge     := bytes_read;
  305.                 is_command := FALSE;
  306.                 ende       := TRUE;
  307.               END;
  308.             END;
  309.           END ELSE BEGIN
  310.             laenge := bytes_read;
  311.             ende   := TRUE;
  312.           END;
  313.         UNTIL ende;
  314.       END;
  315.  
  316.     BEGIN
  317.       IF is_command THEN BEGIN
  318.         IF command < 128 THEN BEGIN
  319.           commandlaenge:= BYTE(command) + 1;
  320.           IF laenge <= commandlaenge THEN BEGIN
  321.             laenge1:= laenge;
  322.             Read_bytes(database, laenge1);
  323.             IF laenge1 = commandlaenge THEN
  324.               is_command:= FALSE
  325.             ELSE
  326.               DEC(command, laenge1);
  327.             laenge:= laenge1;
  328.           END ELSE BEGIN
  329.             laenge1 := commandlaenge;
  330.             Read_bytes(database, laenge1);
  331.             IF laenge1 = commandlaenge THEN BEGIN
  332.               DEC(laenge, laenge1);
  333.               Read_compress_data(MEM[Seg(database):
  334.                                 Ofs(database)+laenge1],
  335.                                 laenge);
  336.               INC(laenge, laenge1);
  337.             END ELSE BEGIN
  338.               laenge := laenge1;
  339.               DEC(command, laenge1);
  340.             END;
  341.           END
  342.         END ELSE BEGIN
  343.           commandlaenge := BYTE(257 - command);
  344.           IF laenge <= commandlaenge THEN BEGIN
  345.             FillChar(database, laenge, data);
  346.             IF laenge = commandlaenge THEN
  347.               is_command := FALSE
  348.             ELSE
  349.               INC(command, laenge);
  350.           END ELSE BEGIN
  351.             FillChar(database, commandlaenge, data);
  352.             DEC(laenge, commandlaenge);
  353.             Read_compress_data(MEM[Seg(database):
  354.                                Ofs(database)+
  355.                                commandlaenge],
  356.                                laenge);
  357.             INC(laenge, commandlaenge);
  358.           END;
  359.         END;
  360.       END ELSE
  361.         Read_compress_data(database, laenge);
  362.     END;
  363.  
  364. BEGIN
  365.   (* keine Initialisierung notwendig *)
  366. END.
  367. (* ------------------------------------------------- *)
  368. (*               Ende von COMPRESS.PAS               *)
  369.