OZip.Mod 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. MODULE OZip; (** AUTHOR GF; PURPOSE "files and streams compression tool"; *)
  2. IMPORT Streams, Commands, Files, Strings, BW := BorrowsWheeler, Huffman, Log := KernelLog;
  3. (*
  4. Format = ComprTag { Block }
  5. Block = Index Freqs Code
  6. Freqs = num { freq } (num = 0, (256 * freq))
  7. | num { freq patt } (num = 1..127)
  8. Code = size { CHAR } (size in bits ! )
  9. num = CHAR
  10. patt = CHAR
  11. freq = RawNum
  12. Index = RawNum
  13. size = RawNum
  14. *)
  15. CONST
  16. BlockSize = 8*1024;
  17. ComprTag = LONGINT(0FEFD1F2FH);
  18. Suffix = ".oz";
  19. PROCEDURE Compress*( r: Streams.Reader; w: Streams.Writer );
  20. VAR
  21. huff: Huffman.Encoder;
  22. bw: BW.Encoder; index: LONGINT;
  23. buffer: ARRAY BlockSize OF CHAR; len: LONGINT;
  24. BEGIN
  25. NEW( huff, w ); NEW( bw );
  26. w.RawLInt( ComprTag );
  27. LOOP
  28. r.Bytes( buffer, 0, BlockSize, len );
  29. IF len < 1 THEN EXIT END;
  30. index := bw.EncodeBlock( buffer, len );
  31. w.RawNum( index );
  32. huff.CompressBlock( buffer, len );
  33. IF r IS Files.Reader THEN Log.Char( '.' ) END
  34. END
  35. END Compress;
  36. PROCEDURE Uncompress*( r: Streams.Reader; w: Streams.Writer; VAR msg: ARRAY OF CHAR ): BOOLEAN;
  37. VAR
  38. huff: Huffman.Decoder;
  39. tag, len, i, bwIndex: LONGINT;
  40. bw: BW.Decoder;
  41. buffer: ARRAY BlockSize OF CHAR;
  42. BEGIN
  43. r.RawLInt( tag );
  44. IF tag # ComprTag THEN
  45. msg := "OZip.Uncompress: bad input (compressed stream expected)";
  46. RETURN FALSE
  47. END;
  48. NEW( huff, r ); NEW( bw );
  49. WHILE r.Available( ) > 0 DO
  50. r.RawNum( bwIndex );
  51. huff.ExtractBlock( buffer, len );
  52. bw.DecodeBlock( buffer, len, bwIndex );
  53. FOR i := 0 TO len - 1 DO w.Char( buffer[i] ) END;
  54. IF w IS Files.Writer THEN Log.Char( '.' ) END
  55. END;
  56. w.Update;
  57. RETURN TRUE
  58. END Uncompress;
  59. PROCEDURE NewFile( CONST name: ARRAY OF CHAR ): Files.File;
  60. VAR
  61. name2: ARRAY 128 OF CHAR; res: LONGINT;
  62. BEGIN
  63. IF Files.Old( name ) # NIL THEN
  64. COPY( name, name2); Strings.Append( name2, ".Bak" );
  65. Files.Rename( name, name2, res );
  66. END;
  67. RETURN Files.New( name )
  68. END NewFile;
  69. (** OZip.CompressFile infile [outfile] ~ *)
  70. PROCEDURE CompressFile*( c: Commands.Context );
  71. VAR
  72. f1, f2: Files.File;
  73. r: Files.Reader; w: Files.Writer;
  74. name1, name2: ARRAY 128 OF CHAR;
  75. BEGIN
  76. IF c.arg.GetString( name1 ) THEN
  77. IF ~c.arg.GetString( name2 ) THEN
  78. name2 := name1; Strings.Append( name2, Suffix )
  79. END;
  80. f1 := Files.Old( name1 );
  81. IF f1 # NIL THEN
  82. Log.String( "OZip.Compress " ); Log.String( name1 ); Log.Char( ' ' );
  83. Files.OpenReader( r, f1, 0 );
  84. f2 := NewFile( name2 ); Files.OpenWriter( w, f2, 0 );
  85. Compress( r, w ); w.Update; Files.Register( f2 );
  86. Log.String( " => " ); Log.String( name2 ); Log.Ln;
  87. ELSE
  88. c.error.String( "could not open file " ); c.error.String( name1 ); c.error.Ln
  89. END
  90. ELSE
  91. c.error.String( "usage: OZip.CompressFile infile [outfile] ~ " ); c.error.Ln;
  92. END;
  93. c.error.Update
  94. END CompressFile;
  95. (** OZip.UncompressFile infile [outfile] ~ *)
  96. PROCEDURE UncompressFile*( c: Commands.Context );
  97. VAR
  98. f1, f2: Files.File;
  99. r: Files.Reader; w: Files.Writer;
  100. name1, name2, msg: ARRAY 128 OF CHAR;
  101. BEGIN
  102. IF c.arg.GetString( name1 ) THEN
  103. IF ~c.arg.GetString( name2 ) THEN
  104. name2 := name1;
  105. IF Strings.EndsWith( Suffix, name2 ) THEN name2[Strings.Length( name2 ) - 3] := 0X
  106. ELSE Strings.Append( name2, ".uncomp" )
  107. END
  108. END;
  109. f1 := Files.Old( name1 );
  110. IF f1 # NIL THEN
  111. Files.OpenReader( r, f1, 0 );
  112. f2 := NewFile( name2 ); Files.OpenWriter( w, f2, 0 );
  113. Log.String( "OZip.Uncompress " ); Log.String( name1 ); Log.Char( ' ' );
  114. IF Uncompress( r, w, msg ) THEN
  115. w.Update; Files.Register( f2 );
  116. Log.String( " => " ); Log.String( name2 ); Log.Ln;
  117. ELSE
  118. c.error.String( msg ); c.error.Ln
  119. END
  120. ELSE
  121. c.error.String( "could not open file " ); c.error.String( name1 ); c.error.Ln
  122. END
  123. ELSE
  124. c.error.String( "usage: OZip.UncompressFile infile [outfile] ~ " ); c.error.Ln;
  125. END;
  126. c.error.Update
  127. END UncompressFile;
  128. END OZip.
  129. OZip.CompressFile OZip.Mod ~
  130. OZip.CompressFile OZip.GofU ~
  131. OZip.CompressFile guide.pdf ~
  132. OZip.UncompressFile OZip.Mod.oz TTT.Mod ~
  133. OZip.UncompressFile OZip.GofU.oz TTT.GofU ~
  134. OZip.UncompressFile guide.pdf.oz TTT.pdf ~
  135. System.Free OZip Huffman BorrowsWheeler ~