zipada_56.0.2_b3043499/extras/bunzip.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
--  Standalone BZip2 decoder (for .bz2 files)

with BZip2.Decoding;

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

procedure bunzip is

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

  type Buffer is array (Natural range <>) of Unsigned_8;

  --  Code with SE_Buffer below:
  --  workaround for the severe xxx'Read xxx'Write performance
  --  problems in the GNAT and ObjectAda compilers (as in 2009)
  --  This possible if and only if Byte = Stream_Element and
  --  arrays types are both packed.

  procedure BU_Read (b : out Buffer) is
    use Ada.Streams;
    Last : Stream_Element_Offset;
    SE_Buffer : Stream_Element_Array (1 .. b'Length);
    for SE_Buffer'Address use b'Address;
    pragma Import (Ada, SE_Buffer);
  begin
    --    Buffer'Read(Stream(f_in), b);
    --  exception
    --    when Ada.Streams.Stream_IO.End_Error =>
    --      null;
    --      -- Nothing bad, just some garbage in the buffer
    --      -- after end of compressed code
    --
    Read (Stream (f_in).all, SE_Buffer, Last);
  end BU_Read;

  procedure BU_Write (b : in Buffer) is
    use Ada.Streams;
    SE_Buffer : Stream_Element_Array (1 .. b'Length);
    for SE_Buffer'Address use b'Address;
    pragma Import (Ada, SE_Buffer);
  begin
    --
    --  Buffer'Write(Stream(f_out), b);
    --
    --  ^ Using this, instead of the lines below, more than doubles
    --  the whole run time (incl. decompression and slow reading!) on GNAT 2008
    --  and makes +60% more time on ObjectAda 7.2.2
    --
    Write (Stream (f_out).all, SE_Buffer);
  end BU_Write;

  package My_BZip2 is new BZip2.Decoding
  (
    input_buffer_size  => 1024,
    output_buffer_size => 4096,
    Buffer             => Buffer,
    check_CRC          => True,
    Read               => BU_Read,
    Write              => BU_Write
  );

begin
  if Argument_Count = 0 then
    Put_Line ("Usage: bunzip <file>");
    New_Line;
    Put_Line ("Decompresses a bzip2 compressed file (.bz2)");
    New_Line;
    Put_Line ("Output is written in the file: bunzip.out");
  else
    Open (f_in, In_File, Argument (1));
    Create (f_out, Out_File, "bunzip.out");
    My_BZip2.Decompress;
    Close (f_out);
  end if;
end bunzip;