zipada_58.0.0_08ab9be1/extras/lzhuf.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
with Ada.Command_Line;                  use Ada.Command_Line;
with Ada.Calendar;                      use Ada.Calendar;
with Ada.Text_IO;                       use Ada.Text_IO;
with Ada.Direct_IO;

with Interfaces;                        use Interfaces;

with LZH;

procedure LZHuf is

  package Byte_IO is new Ada.Direct_IO (Unsigned_8);
  use Byte_IO;
  package CIO is new Integer_IO (Byte_IO.Count);
  package FIO is new Float_IO (Float);

  Infile  : Byte_IO.File_Type;
  Outfile : Byte_IO.File_Type;

  Isize, Osize : Byte_IO.Count;

  Dots : constant := 16;
  Done_Dots : Natural := 0;
  Idot : Byte_IO.Count;

  procedure Display_Progress (Done : Float) is
    New_Done_Dots : constant Natural :=
      Natural (Float (Dots) * Done);
  begin
    for I in Done_Dots + 1 .. New_Done_Dots loop
      Put ('.');
    end loop;
    Done_Dots := New_Done_Dots;
  end Display_Progress;

  function Read_IO_Byte return Unsigned_8 is
  pragma Inline (Read_IO_Byte);
    B : Unsigned_8;
    I : constant Byte_IO.Count := Index (Infile);
  begin
    Read (Infile, B);
    if I = 1 then
      Display_Progress (0.0);
    elsif I = Isize then
      Display_Progress (1.0);
    elsif Idot = 0 or else I mod Idot = 0 then
      Display_Progress (Float (I) / Float (Isize));
    end if;
    return B;
  end Read_IO_Byte;

  function File_More_bytes return Boolean is
  begin
    return not End_Of_File (Infile);
  end File_More_bytes;

  procedure Write_IO_Byte (B : Unsigned_8) is
  pragma Inline (Write_IO_Byte);
  begin
    Write (Outfile, B);
  end Write_IO_Byte;

  package File_LZH is
    new LZH (
      Read_byte  => Read_IO_Byte,
      More_bytes => File_More_bytes,
      Write_byte => Write_IO_Byte
    );
  use File_LZH;

  type T_Action is (Do_Encode, Do_Decode);
  Action : T_Action;

  T0, T1 : Time;
  seconds_elapsed : Duration;

begin
  if Argument_Count /= 3 then
    Put_Line (
      "Usage: lzhuf e(ncode-compress)|d(ecode-decompress) infile outfile");
    return;
  end if;
  declare
    S : constant String := Argument (1);
  begin
    case S (1) is
      when 'e' | 'E' => Action := Do_Encode;
      when 'd' | 'D' => Action := Do_Decode;
      when others =>
        Put_Line (
          "! Use [d] for decoding-decompression or" &
          " [e] for encoding-compression"
        );
        return;
    end case;
  end;
  Byte_IO.Open (Infile, Byte_IO.In_File, Argument (2));
  Isize := Byte_IO.Size (Infile);
  Idot := Isize / Dots;
  Byte_IO.Create (Outfile, Name => Argument (3));
  Put (" In:"); CIO.Put (Isize); Put ("  [");
  T0 := Clock;
  --
  case Action is
    when Do_Encode => Encode;
    when Do_Decode => Decode;
  end case;
  --
  T1 := Clock;
  Byte_IO.Close (Infile);
  Osize := Byte_IO.Size (Outfile);
  Byte_IO.Close (Outfile);
  Put ("] Out:"); CIO.Put (Osize);
  if Isize /= 0 and Osize /= 0 then
    Put ("  ");
    case Action is
      when Do_Encode => CIO.Put ((100 * Osize) / Isize, 0);
      when Do_Decode => CIO.Put ((100 * Isize) / Osize, 0);
    end case;
    Put ("%,");
  end if;
  seconds_elapsed := T1 - T0;
  FIO.Put (Float (seconds_elapsed), 4, 2, 0);
  Put_Line (" seconds.");
end LZHuf;