zipada_56.0.2_b3043499/extras/lzma_enc.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
--  Standalone, command-line, LZMA encoder (for .lzma files).

with LZMA.Encoding;

with Ada.Command_Line;                  use Ada.Command_Line;
with Ada.Text_IO;                       use Ada.Text_IO;
with Ada.Streams.Stream_IO;             use Ada.Streams.Stream_IO;

procedure LZMA_Enc is

  use LZMA, LZMA.Encoding;

  level                 : Compression_level           := Level_3;
  literal_context_bits  : Literal_context_bits_range  := 3;
  literal_position_bits : Literal_position_bits_range := 0;
  position_bits         : Position_bits_range         := 2;

  procedure Encode_LZMA_stream (s_in, s_out : Stream_Access) is
    EOS : Boolean := False;
    mem_b : Byte := Character'Pos ('X');  --  delayed by 1 byte to catch the EOS

    --  NB: The Byte I/O below is not buffered, so it is very slow.
    --  You need to implement a circular buffer of type Stream_Element_Array for a fast I/O.
    --  For instance, see the BlockRead in the Zip package for how to do it.

    function Read_byte return Byte is  --  One dummy call to Read_byte is needed before compression
      prev_b : Byte;
    begin
      prev_b := mem_b;
      Byte'Read (s_in, mem_b);
      return prev_b;
    exception
      when Ada.Streams.Stream_IO.End_Error =>
        EOS := True;
        return prev_b;
    end Read_byte;

    function More_bytes return Boolean is
    begin
      return not EOS;
    end More_bytes;

    procedure Put_byte (b : Byte) is
    begin
      Byte'Write (s_out, b);
    end Put_byte;

    procedure LZMA_Encode is new LZMA.Encoding.Encode (Read_byte, More_bytes, Put_byte);

    dummy : Byte := Read_byte;  --  Consume the initial 'X'

  begin
    --  Whole processing here:
    LZMA_Encode (
      level,
      literal_context_bits,
      literal_position_bits,
      position_bits,
      dictionary_size => 2**20,
      uncompressed_size_info => True
    );
  end Encode_LZMA_stream;

  f_in, f_out : Ada.Streams.Stream_IO.File_Type;

  procedure Print_Data_Bytes_Count (title : String; v : Data_Bytes_Count) is
    package CIO is new Integer_IO (Data_Bytes_Count);
  begin
    Put (title);
    Put (" : ");
    CIO.Put (v, 0);
    Put (" bytes");
    New_Line;
  end Print_Data_Bytes_Count;

  bench : Boolean := False;
  z : constant := Character'Pos ('0');

begin
  New_Line;
  Put_Line ("LZMA_Enc: a standalone LZMA encoder.");
  if Argument_Count = 0 then
    Put_Line ("Use: lzma_enc infile outfile [options]");
    New_Line;
    Put_Line ("NB: - The "".lzma"" extension automatically added to outfile.");
    Put_Line ("    - The I/O is not buffered => may be slow. Use the ZipAda tool for fast I/O.");
    New_Line;
    Put_Line ("Options: -b: benchmark LZ77's and the context parameters (900 .lzma output files!)");
    return;
  elsif Argument_Count < 2 then
    Put_Line ("You must specify at least two parameters");
    return;
  end if;
  for i in 3 .. Argument_Count loop
    bench := bench or Argument (i) = "-b";
  end loop;
  if bench then
    for lc in reverse Literal_context_bits_range loop
      for lp in reverse Literal_position_bits_range loop
        for pb in reverse Position_bits_range loop
          for lv in Level_0 .. Level_3 loop
            Open (f_in, In_File, Argument (1));
            Create (f_out, Out_File,
              Argument (2) & '_' &
              Character'Val (z + lc) & Character'Val (z + lp) & Character'Val (z + pb) &
              "_l" &
              Character'Val (z + Compression_level'Pos (lv)) & ".lzma"
            );
            literal_context_bits  := lc;
            literal_position_bits := lp;
            position_bits         := pb;
            level                 := lv;
            Encode_LZMA_stream (Stream (f_in), Stream (f_out));
            Close (f_in);
            Close (f_out);
          end loop;
        end loop;
      end loop;
    end loop;
  else
    Open (f_in, In_File, Argument (1));
    Create (f_out, Out_File, Argument (2) & ".lzma");
    Encode_LZMA_stream (Stream (f_in), Stream (f_out));
    New_Line;
    Print_Data_Bytes_Count ("Read    ", Data_Bytes_Count (Index (f_in) - 1));
    Print_Data_Bytes_Count ("Written ", Data_Bytes_Count (Index (f_out) - 1));
    Close (f_in);
    Close (f_out);
  end if;

end LZMA_Enc;