|
kusano |
fc6ab3 |
----------------------------------------------------------------
|
|
kusano |
fc6ab3 |
-- ZLib for Ada thick binding. --
|
|
kusano |
fc6ab3 |
-- --
|
|
kusano |
fc6ab3 |
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
|
kusano |
fc6ab3 |
-- --
|
|
kusano |
fc6ab3 |
-- Open source license information is in the zlib.ads file. --
|
|
kusano |
fc6ab3 |
----------------------------------------------------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
with Ada.Exceptions;
|
|
kusano |
fc6ab3 |
with Ada.Unchecked_Conversion;
|
|
kusano |
fc6ab3 |
with Ada.Unchecked_Deallocation;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
with Interfaces.C.Strings;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
with ZLib.Thin;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
package body ZLib is
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
use type Thin.Int;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
type Z_Stream is new Thin.Z_Stream;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
type Return_Code_Enum is
|
|
kusano |
fc6ab3 |
(OK,
|
|
kusano |
fc6ab3 |
STREAM_END,
|
|
kusano |
fc6ab3 |
NEED_DICT,
|
|
kusano |
fc6ab3 |
ERRNO,
|
|
kusano |
fc6ab3 |
STREAM_ERROR,
|
|
kusano |
fc6ab3 |
DATA_ERROR,
|
|
kusano |
fc6ab3 |
MEM_ERROR,
|
|
kusano |
fc6ab3 |
BUF_ERROR,
|
|
kusano |
fc6ab3 |
VERSION_ERROR);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
type Flate_Step_Function is access
|
|
kusano |
fc6ab3 |
function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
|
|
kusano |
fc6ab3 |
pragma Convention (C, Flate_Step_Function);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
type Flate_End_Function is access
|
|
kusano |
fc6ab3 |
function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
|
|
kusano |
fc6ab3 |
pragma Convention (C, Flate_End_Function);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
type Flate_Type is record
|
|
kusano |
fc6ab3 |
Step : Flate_Step_Function;
|
|
kusano |
fc6ab3 |
Done : Flate_End_Function;
|
|
kusano |
fc6ab3 |
end record;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
subtype Footer_Array is Stream_Element_Array (1 .. 8);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Simple_GZip_Header : constant Stream_Element_Array (1 .. 10)
|
|
kusano |
fc6ab3 |
:= (16#1f#, 16#8b#, -- Magic header
|
|
kusano |
fc6ab3 |
16#08#, -- Z_DEFLATED
|
|
kusano |
fc6ab3 |
16#00#, -- Flags
|
|
kusano |
fc6ab3 |
16#00#, 16#00#, 16#00#, 16#00#, -- Time
|
|
kusano |
fc6ab3 |
16#00#, -- XFlags
|
|
kusano |
fc6ab3 |
16#03# -- OS code
|
|
kusano |
fc6ab3 |
);
|
|
kusano |
fc6ab3 |
-- The simplest gzip header is not for informational, but just for
|
|
kusano |
fc6ab3 |
-- gzip format compatibility.
|
|
kusano |
fc6ab3 |
-- Note that some code below is using assumption
|
|
kusano |
fc6ab3 |
-- Simple_GZip_Header'Last > Footer_Array'Last, so do not make
|
|
kusano |
fc6ab3 |
-- Simple_GZip_Header'Last <= Footer_Array'Last.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum
|
|
kusano |
fc6ab3 |
:= (0 => OK,
|
|
kusano |
fc6ab3 |
1 => STREAM_END,
|
|
kusano |
fc6ab3 |
2 => NEED_DICT,
|
|
kusano |
fc6ab3 |
-1 => ERRNO,
|
|
kusano |
fc6ab3 |
-2 => STREAM_ERROR,
|
|
kusano |
fc6ab3 |
-3 => DATA_ERROR,
|
|
kusano |
fc6ab3 |
-4 => MEM_ERROR,
|
|
kusano |
fc6ab3 |
-5 => BUF_ERROR,
|
|
kusano |
fc6ab3 |
-6 => VERSION_ERROR);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Flate : constant array (Boolean) of Flate_Type
|
|
kusano |
fc6ab3 |
:= (True => (Step => Thin.Deflate'Access,
|
|
kusano |
fc6ab3 |
Done => Thin.DeflateEnd'Access),
|
|
kusano |
fc6ab3 |
False => (Step => Thin.Inflate'Access,
|
|
kusano |
fc6ab3 |
Done => Thin.InflateEnd'Access));
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Flush_Finish : constant array (Boolean) of Flush_Mode
|
|
kusano |
fc6ab3 |
:= (True => Finish, False => No_Flush);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Raise_Error (Stream : in Z_Stream);
|
|
kusano |
fc6ab3 |
pragma Inline (Raise_Error);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Raise_Error (Message : in String);
|
|
kusano |
fc6ab3 |
pragma Inline (Raise_Error);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Free is new Ada.Unchecked_Deallocation
|
|
kusano |
fc6ab3 |
(Z_Stream, Z_Stream_Access);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function To_Thin_Access is new Ada.Unchecked_Conversion
|
|
kusano |
fc6ab3 |
(Z_Stream_Access, Thin.Z_Streamp);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Translate_GZip
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
In_Data : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
In_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode);
|
|
kusano |
fc6ab3 |
-- Separate translate routine for make gzip header.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Translate_Auto
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
In_Data : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
In_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode);
|
|
kusano |
fc6ab3 |
-- translate routine without additional headers.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------------
|
|
kusano |
fc6ab3 |
-- Check_Error --
|
|
kusano |
fc6ab3 |
-----------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is
|
|
kusano |
fc6ab3 |
use type Thin.Int;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Code /= Thin.Z_OK then
|
|
kusano |
fc6ab3 |
Raise_Error
|
|
kusano |
fc6ab3 |
(Return_Code_Enum'Image (Return_Code (Code))
|
|
kusano |
fc6ab3 |
& ": " & Last_Error_Message (Stream));
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Check_Error;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
-- Close --
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Close
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Ignore_Error : in Boolean := False)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
Code : Thin.Int;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if not Ignore_Error and then not Is_Open (Filter) then
|
|
kusano |
fc6ab3 |
raise Status_Error;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm));
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Ignore_Error or else Code = Thin.Z_OK then
|
|
kusano |
fc6ab3 |
Free (Filter.Strm);
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
declare
|
|
kusano |
fc6ab3 |
Error_Message : constant String
|
|
kusano |
fc6ab3 |
:= Last_Error_Message (Filter.Strm.all);
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Free (Filter.Strm);
|
|
kusano |
fc6ab3 |
Ada.Exceptions.Raise_Exception
|
|
kusano |
fc6ab3 |
(ZLib_Error'Identity,
|
|
kusano |
fc6ab3 |
Return_Code_Enum'Image (Return_Code (Code))
|
|
kusano |
fc6ab3 |
& ": " & Error_Message);
|
|
kusano |
fc6ab3 |
end;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Close;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
-- CRC32 --
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function CRC32
|
|
kusano |
fc6ab3 |
(CRC : in Unsigned_32;
|
|
kusano |
fc6ab3 |
Data : in Ada.Streams.Stream_Element_Array)
|
|
kusano |
fc6ab3 |
return Unsigned_32
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
use Thin;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
return Unsigned_32 (crc32 (ULong (CRC),
|
|
kusano |
fc6ab3 |
Data'Address,
|
|
kusano |
fc6ab3 |
Data'Length));
|
|
kusano |
fc6ab3 |
end CRC32;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure CRC32
|
|
kusano |
fc6ab3 |
(CRC : in out Unsigned_32;
|
|
kusano |
fc6ab3 |
Data : in Ada.Streams.Stream_Element_Array) is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
CRC := CRC32 (CRC, Data);
|
|
kusano |
fc6ab3 |
end CRC32;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
------------------
|
|
kusano |
fc6ab3 |
-- Deflate_Init --
|
|
kusano |
fc6ab3 |
------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Deflate_Init
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Level : in Compression_Level := Default_Compression;
|
|
kusano |
fc6ab3 |
Strategy : in Strategy_Type := Default_Strategy;
|
|
kusano |
fc6ab3 |
Method : in Compression_Method := Deflated;
|
|
kusano |
fc6ab3 |
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
|
kusano |
fc6ab3 |
Memory_Level : in Memory_Level_Type := Default_Memory_Level;
|
|
kusano |
fc6ab3 |
Header : in Header_Type := Default)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
use type Thin.Int;
|
|
kusano |
fc6ab3 |
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Is_Open (Filter) then
|
|
kusano |
fc6ab3 |
raise Status_Error;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- We allow ZLib to make header only in case of default header type.
|
|
kusano |
fc6ab3 |
-- Otherwise we would either do header by ourselfs, or do not do
|
|
kusano |
fc6ab3 |
-- header at all.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Header = None or else Header = GZip then
|
|
kusano |
fc6ab3 |
Win_Bits := -Win_Bits;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- For the GZip CRC calculation and make headers.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Header = GZip then
|
|
kusano |
fc6ab3 |
Filter.CRC := 0;
|
|
kusano |
fc6ab3 |
Filter.Offset := Simple_GZip_Header'First;
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
Filter.Offset := Simple_GZip_Header'Last + 1;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Filter.Strm := new Z_Stream;
|
|
kusano |
fc6ab3 |
Filter.Compression := True;
|
|
kusano |
fc6ab3 |
Filter.Stream_End := False;
|
|
kusano |
fc6ab3 |
Filter.Header := Header;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Thin.Deflate_Init
|
|
kusano |
fc6ab3 |
(To_Thin_Access (Filter.Strm),
|
|
kusano |
fc6ab3 |
Level => Thin.Int (Level),
|
|
kusano |
fc6ab3 |
method => Thin.Int (Method),
|
|
kusano |
fc6ab3 |
windowBits => Win_Bits,
|
|
kusano |
fc6ab3 |
memLevel => Thin.Int (Memory_Level),
|
|
kusano |
fc6ab3 |
strategy => Thin.Int (Strategy)) /= Thin.Z_OK
|
|
kusano |
fc6ab3 |
then
|
|
kusano |
fc6ab3 |
Raise_Error (Filter.Strm.all);
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Deflate_Init;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
-- Flush --
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Flush
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
No_Data : Stream_Element_Array := (1 .. 0 => 0);
|
|
kusano |
fc6ab3 |
Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush);
|
|
kusano |
fc6ab3 |
end Flush;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------------------
|
|
kusano |
fc6ab3 |
-- Generic_Translate --
|
|
kusano |
fc6ab3 |
-----------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Generic_Translate
|
|
kusano |
fc6ab3 |
(Filter : in out ZLib.Filter_Type;
|
|
kusano |
fc6ab3 |
In_Buffer_Size : in Integer := Default_Buffer_Size;
|
|
kusano |
fc6ab3 |
Out_Buffer_Size : in Integer := Default_Buffer_Size)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
In_Buffer : Stream_Element_Array
|
|
kusano |
fc6ab3 |
(1 .. Stream_Element_Offset (In_Buffer_Size));
|
|
kusano |
fc6ab3 |
Out_Buffer : Stream_Element_Array
|
|
kusano |
fc6ab3 |
(1 .. Stream_Element_Offset (Out_Buffer_Size));
|
|
kusano |
fc6ab3 |
Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
In_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
In_First : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Main : loop
|
|
kusano |
fc6ab3 |
Data_In (In_Buffer, Last);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
In_First := In_Buffer'First;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
loop
|
|
kusano |
fc6ab3 |
Translate
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => In_Buffer (In_First .. Last),
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Out_Buffer,
|
|
kusano |
fc6ab3 |
Out_Last => Out_Last,
|
|
kusano |
fc6ab3 |
Flush => Flush_Finish (Last < In_Buffer'First));
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Out_Buffer'First <= Out_Last then
|
|
kusano |
fc6ab3 |
Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
exit Main when Stream_End (Filter);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- The end of in buffer.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
exit when In_Last = Last;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
In_First := In_Last + 1;
|
|
kusano |
fc6ab3 |
end loop;
|
|
kusano |
fc6ab3 |
end loop Main;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
end Generic_Translate;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
------------------
|
|
kusano |
fc6ab3 |
-- Inflate_Init --
|
|
kusano |
fc6ab3 |
------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Inflate_Init
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
|
kusano |
fc6ab3 |
Header : in Header_Type := Default)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
use type Thin.Int;
|
|
kusano |
fc6ab3 |
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Check_Version;
|
|
kusano |
fc6ab3 |
-- Check the latest header types compatibility.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Check_Version is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Version <= "1.1.4" then
|
|
kusano |
fc6ab3 |
Raise_Error
|
|
kusano |
fc6ab3 |
("Inflate header type " & Header_Type'Image (Header)
|
|
kusano |
fc6ab3 |
& " incompatible with ZLib version " & Version);
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Check_Version;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Is_Open (Filter) then
|
|
kusano |
fc6ab3 |
raise Status_Error;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
case Header is
|
|
kusano |
fc6ab3 |
when None =>
|
|
kusano |
fc6ab3 |
Check_Version;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- Inflate data without headers determined
|
|
kusano |
fc6ab3 |
-- by negative Win_Bits.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Win_Bits := -Win_Bits;
|
|
kusano |
fc6ab3 |
when GZip =>
|
|
kusano |
fc6ab3 |
Check_Version;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- Inflate gzip data defined by flag 16.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Win_Bits := Win_Bits + 16;
|
|
kusano |
fc6ab3 |
when Auto =>
|
|
kusano |
fc6ab3 |
Check_Version;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-- Inflate with automatic detection
|
|
kusano |
fc6ab3 |
-- of gzip or native header defined by flag 32.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Win_Bits := Win_Bits + 32;
|
|
kusano |
fc6ab3 |
when Default => null;
|
|
kusano |
fc6ab3 |
end case;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Filter.Strm := new Z_Stream;
|
|
kusano |
fc6ab3 |
Filter.Compression := False;
|
|
kusano |
fc6ab3 |
Filter.Stream_End := False;
|
|
kusano |
fc6ab3 |
Filter.Header := Header;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Thin.Inflate_Init
|
|
kusano |
fc6ab3 |
(To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK
|
|
kusano |
fc6ab3 |
then
|
|
kusano |
fc6ab3 |
Raise_Error (Filter.Strm.all);
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Inflate_Init;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-------------
|
|
kusano |
fc6ab3 |
-- Is_Open --
|
|
kusano |
fc6ab3 |
-------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function Is_Open (Filter : in Filter_Type) return Boolean is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
return Filter.Strm /= null;
|
|
kusano |
fc6ab3 |
end Is_Open;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------------
|
|
kusano |
fc6ab3 |
-- Raise_Error --
|
|
kusano |
fc6ab3 |
-----------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Raise_Error (Message : in String) is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
|
|
kusano |
fc6ab3 |
end Raise_Error;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Raise_Error (Stream : in Z_Stream) is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Raise_Error (Last_Error_Message (Stream));
|
|
kusano |
fc6ab3 |
end Raise_Error;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
----------
|
|
kusano |
fc6ab3 |
-- Read --
|
|
kusano |
fc6ab3 |
----------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Read
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Item : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode := No_Flush)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
In_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
|
|
kusano |
fc6ab3 |
V_Flush : Flush_Mode := Flush;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
|
|
kusano |
fc6ab3 |
pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
loop
|
|
kusano |
fc6ab3 |
if Rest_Last = Buffer'First - 1 then
|
|
kusano |
fc6ab3 |
V_Flush := Finish;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
elsif Rest_First > Rest_Last then
|
|
kusano |
fc6ab3 |
Read (Buffer, Rest_Last);
|
|
kusano |
fc6ab3 |
Rest_First := Buffer'First;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Rest_Last < Buffer'First then
|
|
kusano |
fc6ab3 |
V_Flush := Finish;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Translate
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => Buffer (Rest_First .. Rest_Last),
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Item (Item_First .. Item'Last),
|
|
kusano |
fc6ab3 |
Out_Last => Last,
|
|
kusano |
fc6ab3 |
Flush => V_Flush);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Rest_First := In_Last + 1;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
exit when Stream_End (Filter)
|
|
kusano |
fc6ab3 |
or else Last = Item'Last
|
|
kusano |
fc6ab3 |
or else (Last >= Item'First and then Allow_Read_Some);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Item_First := Last + 1;
|
|
kusano |
fc6ab3 |
end loop;
|
|
kusano |
fc6ab3 |
end Read;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
----------------
|
|
kusano |
fc6ab3 |
-- Stream_End --
|
|
kusano |
fc6ab3 |
----------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function Stream_End (Filter : in Filter_Type) return Boolean is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Filter.Header = GZip and Filter.Compression then
|
|
kusano |
fc6ab3 |
return Filter.Stream_End
|
|
kusano |
fc6ab3 |
and then Filter.Offset = Footer_Array'Last + 1;
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
return Filter.Stream_End;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Stream_End;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
--------------
|
|
kusano |
fc6ab3 |
-- Total_In --
|
|
kusano |
fc6ab3 |
--------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function Total_In (Filter : in Filter_Type) return Count is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all));
|
|
kusano |
fc6ab3 |
end Total_In;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
---------------
|
|
kusano |
fc6ab3 |
-- Total_Out --
|
|
kusano |
fc6ab3 |
---------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function Total_Out (Filter : in Filter_Type) return Count is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all));
|
|
kusano |
fc6ab3 |
end Total_Out;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
---------------
|
|
kusano |
fc6ab3 |
-- Translate --
|
|
kusano |
fc6ab3 |
---------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Translate
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
In_Data : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
In_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode) is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Filter.Header = GZip and then Filter.Compression then
|
|
kusano |
fc6ab3 |
Translate_GZip
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => In_Data,
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Out_Data,
|
|
kusano |
fc6ab3 |
Out_Last => Out_Last,
|
|
kusano |
fc6ab3 |
Flush => Flush);
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
Translate_Auto
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => In_Data,
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Out_Data,
|
|
kusano |
fc6ab3 |
Out_Last => Out_Last,
|
|
kusano |
fc6ab3 |
Flush => Flush);
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Translate;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
--------------------
|
|
kusano |
fc6ab3 |
-- Translate_Auto --
|
|
kusano |
fc6ab3 |
--------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Translate_Auto
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
In_Data : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
In_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
use type Thin.Int;
|
|
kusano |
fc6ab3 |
Code : Thin.Int;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if not Is_Open (Filter) then
|
|
kusano |
fc6ab3 |
raise Status_Error;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Out_Data'Length = 0 and then In_Data'Length = 0 then
|
|
kusano |
fc6ab3 |
raise Constraint_Error;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length);
|
|
kusano |
fc6ab3 |
Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Code := Flate (Filter.Compression).Step
|
|
kusano |
fc6ab3 |
(To_Thin_Access (Filter.Strm),
|
|
kusano |
fc6ab3 |
Thin.Int (Flush));
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Code = Thin.Z_STREAM_END then
|
|
kusano |
fc6ab3 |
Filter.Stream_End := True;
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
Check_Error (Filter.Strm.all, Code);
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
In_Last := In_Data'Last
|
|
kusano |
fc6ab3 |
- Stream_Element_Offset (Avail_In (Filter.Strm.all));
|
|
kusano |
fc6ab3 |
Out_Last := Out_Data'Last
|
|
kusano |
fc6ab3 |
- Stream_Element_Offset (Avail_Out (Filter.Strm.all));
|
|
kusano |
fc6ab3 |
end Translate_Auto;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
--------------------
|
|
kusano |
fc6ab3 |
-- Translate_GZip --
|
|
kusano |
fc6ab3 |
--------------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Translate_GZip
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
In_Data : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
In_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Data : out Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
Out_First : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Add_Data (Data : in Stream_Element_Array);
|
|
kusano |
fc6ab3 |
-- Add data to stream from the Filter.Offset till necessary,
|
|
kusano |
fc6ab3 |
-- used for add gzip headr/footer.
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Put_32
|
|
kusano |
fc6ab3 |
(Item : in out Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Data : in Unsigned_32);
|
|
kusano |
fc6ab3 |
pragma Inline (Put_32);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
--------------
|
|
kusano |
fc6ab3 |
-- Add_Data --
|
|
kusano |
fc6ab3 |
--------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Add_Data (Data : in Stream_Element_Array) is
|
|
kusano |
fc6ab3 |
Data_First : Stream_Element_Offset renames Filter.Offset;
|
|
kusano |
fc6ab3 |
Data_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Data_Len : Stream_Element_Offset; -- -1
|
|
kusano |
fc6ab3 |
Out_Len : Stream_Element_Offset; -- -1
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Out_First := Out_Last + 1;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Data_First > Data'Last then
|
|
kusano |
fc6ab3 |
return;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Data_Len := Data'Last - Data_First;
|
|
kusano |
fc6ab3 |
Out_Len := Out_Data'Last - Out_First;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Data_Len <= Out_Len then
|
|
kusano |
fc6ab3 |
Out_Last := Out_First + Data_Len;
|
|
kusano |
fc6ab3 |
Data_Last := Data'Last;
|
|
kusano |
fc6ab3 |
else
|
|
kusano |
fc6ab3 |
Out_Last := Out_Data'Last;
|
|
kusano |
fc6ab3 |
Data_Last := Data_First + Out_Len;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Data_First := Data_Last + 1;
|
|
kusano |
fc6ab3 |
Out_First := Out_Last + 1;
|
|
kusano |
fc6ab3 |
end Add_Data;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
------------
|
|
kusano |
fc6ab3 |
-- Put_32 --
|
|
kusano |
fc6ab3 |
------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Put_32
|
|
kusano |
fc6ab3 |
(Item : in out Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Data : in Unsigned_32)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
D : Unsigned_32 := Data;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
for J in Item'First .. Item'First + 3 loop
|
|
kusano |
fc6ab3 |
Item (J) := Stream_Element (D and 16#FF#);
|
|
kusano |
fc6ab3 |
D := Shift_Right (D, 8);
|
|
kusano |
fc6ab3 |
end loop;
|
|
kusano |
fc6ab3 |
end Put_32;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Out_Last := Out_Data'First - 1;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if not Filter.Stream_End then
|
|
kusano |
fc6ab3 |
Add_Data (Simple_GZip_Header);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
Translate_Auto
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => In_Data,
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Out_Data (Out_First .. Out_Data'Last),
|
|
kusano |
fc6ab3 |
Out_Last => Out_Last,
|
|
kusano |
fc6ab3 |
Flush => Flush);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Filter.Stream_End and then Out_Last <= Out_Data'Last then
|
|
kusano |
fc6ab3 |
-- This detection method would work only when
|
|
kusano |
fc6ab3 |
-- Simple_GZip_Header'Last > Footer_Array'Last
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Filter.Offset = Simple_GZip_Header'Last + 1 then
|
|
kusano |
fc6ab3 |
Filter.Offset := Footer_Array'First;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
declare
|
|
kusano |
fc6ab3 |
Footer : Footer_Array;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
Put_32 (Footer, Filter.CRC);
|
|
kusano |
fc6ab3 |
Put_32 (Footer (Footer'First + 4 .. Footer'Last),
|
|
kusano |
fc6ab3 |
Unsigned_32 (Total_In (Filter)));
|
|
kusano |
fc6ab3 |
Add_Data (Footer);
|
|
kusano |
fc6ab3 |
end;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
end Translate_GZip;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-------------
|
|
kusano |
fc6ab3 |
-- Version --
|
|
kusano |
fc6ab3 |
-------------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
function Version return String is
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
return Interfaces.C.Strings.Value (Thin.zlibVersion);
|
|
kusano |
fc6ab3 |
end Version;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
-- Write --
|
|
kusano |
fc6ab3 |
-----------
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
procedure Write
|
|
kusano |
fc6ab3 |
(Filter : in out Filter_Type;
|
|
kusano |
fc6ab3 |
Item : in Ada.Streams.Stream_Element_Array;
|
|
kusano |
fc6ab3 |
Flush : in Flush_Mode := No_Flush)
|
|
kusano |
fc6ab3 |
is
|
|
kusano |
fc6ab3 |
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
|
kusano |
fc6ab3 |
In_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
Out_Last : Stream_Element_Offset;
|
|
kusano |
fc6ab3 |
In_First : Stream_Element_Offset := Item'First;
|
|
kusano |
fc6ab3 |
begin
|
|
kusano |
fc6ab3 |
if Item'Length = 0 and Flush = No_Flush then
|
|
kusano |
fc6ab3 |
return;
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
loop
|
|
kusano |
fc6ab3 |
Translate
|
|
kusano |
fc6ab3 |
(Filter => Filter,
|
|
kusano |
fc6ab3 |
In_Data => Item (In_First .. Item'Last),
|
|
kusano |
fc6ab3 |
In_Last => In_Last,
|
|
kusano |
fc6ab3 |
Out_Data => Buffer,
|
|
kusano |
fc6ab3 |
Out_Last => Out_Last,
|
|
kusano |
fc6ab3 |
Flush => Flush);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
if Out_Last >= Buffer'First then
|
|
kusano |
fc6ab3 |
Write (Buffer (1 .. Out_Last));
|
|
kusano |
fc6ab3 |
end if;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
exit when In_Last = Item'Last or Stream_End (Filter);
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
In_First := In_Last + 1;
|
|
kusano |
fc6ab3 |
end loop;
|
|
kusano |
fc6ab3 |
end Write;
|
|
kusano |
fc6ab3 |
|
|
kusano |
fc6ab3 |
end ZLib;
|