---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2004 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------
with Ada.Exceptions; with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation;
with Interfaces.C.Strings;
with ZLib.Thin;
packagebody ZLib is
usetype Thin.Int;
type Z_Stream isnew Thin.Z_Stream;
type Return_Code_Enum is
(OK,
STREAM_END,
NEED_DICT,
ERRNO,
STREAM_ERROR,
DATA_ERROR,
MEM_ERROR,
BUF_ERROR,
VERSION_ERROR);
type Flate_Step_Function isaccess function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
pragma Convention (C, Flate_Step_Function);
type Flate_End_Function isaccess function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
pragma Convention (C, Flate_End_Function);
type Flate_Type isrecord
Step : Flate_Step_Function;
Done : Flate_End_Function; endrecord;
subtype Footer_Array is Stream_Element_Array (1 .. 8);
Simple_GZip_Header : constant Stream_Element_Array (1 .. 10)
:= (16#1f#, 16#8b#, -- Magic header
16#08#, -- Z_DEFLATED
16#00#, -- Flags
16#00#, 16#00#, 16#00#, 16#00#, -- Time
16#00#, -- XFlags
16#03# -- OS code
); -- The simplest gzip header is not for informational, but just for -- gzip format compatibility. -- Note that some code below is using assumption -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make -- Simple_GZip_Header'Last <= Footer_Array'Last.
function To_Thin_Access isnew Ada.Unchecked_Conversion
(Z_Stream_Access, Thin.Z_Streamp);
procedure Translate_GZip
(Filter : inout Filter_Type;
In_Data : in Ada.Streams.Stream_Element_Array;
In_Last : out Ada.Streams.Stream_Element_Offset;
Out_Data : out Ada.Streams.Stream_Element_Array;
Out_Last : out Ada.Streams.Stream_Element_Offset;
Flush : in Flush_Mode); -- Separate translate routine for make gzip header.
procedure Translate_Auto
(Filter : inout Filter_Type;
In_Data : in Ada.Streams.Stream_Element_Array;
In_Last : out Ada.Streams.Stream_Element_Offset;
Out_Data : out Ada.Streams.Stream_Element_Array;
Out_Last : out Ada.Streams.Stream_Element_Offset;
Flush : in Flush_Mode); -- translate routine without additional headers.
procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is usetype Thin.Int; begin if Code /= Thin.Z_OK then
Raise_Error
(Return_Code_Enum'Image (Return_Code (Code))
& ": " & Last_Error_Message (Stream)); endif; end Check_Error;
----------- -- Close -- -----------
procedure Close
(Filter : inout Filter_Type;
Ignore_Error : in Boolean := False) is
Code : Thin.Int; begin ifnot Ignore_Error andthennot Is_Open (Filter) then raise Status_Error; endif;
if Ignore_Error orelse Code = Thin.Z_OK then
Free (Filter.Strm); else declare
Error_Message : constant String
:= Last_Error_Message (Filter.Strm.all); begin
Free (Filter.Strm);
Ada.Exceptions.Raise_Exception
(ZLib_Error'Identity,
Return_Code_Enum'Image (Return_Code (Code))
& ": " & Error_Message); end; endif; end Close;
----------- -- CRC32 -- -----------
function CRC32
(CRC : in Unsigned_32;
Data : in Ada.Streams.Stream_Element_Array) return Unsigned_32 is use Thin; begin return Unsigned_32 (crc32 (ULong (CRC),
Data'Address,
Data'Length)); end CRC32;
procedure CRC32
(CRC : inout Unsigned_32;
Data : in Ada.Streams.Stream_Element_Array) is begin
CRC := CRC32 (CRC, Data); end CRC32;
procedure Deflate_Init
(Filter : inout Filter_Type;
Level : in Compression_Level := Default_Compression;
Strategy : in Strategy_Type := Default_Strategy;
Method : in Compression_Method := Deflated;
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
Memory_Level : in Memory_Level_Type := Default_Memory_Level;
Header : in Header_Type := Default) is usetype Thin.Int;
Win_Bits : Thin.Int := Thin.Int (Window_Bits); begin if Is_Open (Filter) then raise Status_Error; endif;
-- We allow ZLib to make header only in case of default header type. -- Otherwise we would either do header by ourselves, or do not do -- header at all.
if Header = None orelse Header = GZip then
Win_Bits := -Win_Bits; endif;
-- For the GZip CRC calculation and make headers.
if Header = GZip then
Filter.CRC := 0;
Filter.Offset := Simple_GZip_Header'First; else
Filter.Offset := Simple_GZip_Header'Last + 1; endif;
procedure Inflate_Init
(Filter : inout Filter_Type;
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
Header : in Header_Type := Default) is usetype Thin.Int;
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
procedure Check_Version; -- Check the latest header types compatibility.
procedure Check_Version is begin if Version <= "1.1.4"then
Raise_Error
("Inflate header type " & Header_Type'Image (Header)
& " incompatible with ZLib version " & Version); endif; end Check_Version;
begin if Is_Open (Filter) then raise Status_Error; endif;
case Header is when None =>
Check_Version;
-- Inflate data without headers determined -- by negative Win_Bits.
Win_Bits := -Win_Bits; when GZip =>
Check_Version;
-- Inflate gzip data defined by flag 16.
Win_Bits := Win_Bits + 16; when Auto =>
Check_Version;
-- Inflate with automatic detection -- of gzip or native header defined by flag 32.
Win_Bits := Win_Bits + 32; when Default => null; endcase;
function Stream_End (Filter : in Filter_Type) return Boolean is begin if Filter.Header = GZip and Filter.Compression then return Filter.Stream_End andthen Filter.Offset = Footer_Array'Last + 1; else return Filter.Stream_End; endif; end Stream_End;
-------------- -- Total_In -- --------------
function Total_In (Filter : in Filter_Type) return Count is begin return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); end Total_In;
--------------- -- Total_Out -- ---------------
function Total_Out (Filter : in Filter_Type) return Count is begin return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); end Total_Out;
--------------- -- Translate -- ---------------
procedure Translate
(Filter : inout Filter_Type;
In_Data : in Ada.Streams.Stream_Element_Array;
In_Last : out Ada.Streams.Stream_Element_Offset;
Out_Data : out Ada.Streams.Stream_Element_Array;
Out_Last : out Ada.Streams.Stream_Element_Offset;
Flush : in Flush_Mode) is begin if Filter.Header = GZip andthen Filter.Compression then
Translate_GZip
(Filter => Filter,
In_Data => In_Data,
In_Last => In_Last,
Out_Data => Out_Data,
Out_Last => Out_Last,
Flush => Flush); else
Translate_Auto
(Filter => Filter,
In_Data => In_Data,
In_Last => In_Last,
Out_Data => Out_Data,
Out_Last => Out_Last,
Flush => Flush); endif; end Translate;
procedure Translate_GZip
(Filter : inout Filter_Type;
In_Data : in Ada.Streams.Stream_Element_Array;
In_Last : out Ada.Streams.Stream_Element_Offset;
Out_Data : out Ada.Streams.Stream_Element_Array;
Out_Last : out Ada.Streams.Stream_Element_Offset;
Flush : in Flush_Mode) is
Out_First : Stream_Element_Offset;
procedure Add_Data (Data : in Stream_Element_Array); -- Add data to stream from the Filter.Offset till necessary, -- used for add gzip headr/footer.
procedure Put_32
(Item : inout Stream_Element_Array;
Data : in Unsigned_32);
pragma Inline (Put_32);
procedure Put_32
(Item : inout Stream_Element_Array;
Data : in Unsigned_32) is
D : Unsigned_32 := Data; begin for J in Item'First .. Item'First + 3 loop
Item (J) := Stream_Element (D and 16#FF#);
D := Shift_Right (D, 8); endloop; end Put_32;
begin
Out_Last := Out_Data'First - 1;
ifnot Filter.Stream_End then
Add_Data (Simple_GZip_Header);
if Filter.Stream_End andthen Out_Last <= Out_Data'Last then -- This detection method would work only when -- Simple_GZip_Header'Last > Footer_Array'Last
if Filter.Offset = Simple_GZip_Header'Last + 1 then
Filter.Offset := Footer_Array'First; endif;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.