702 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Ada
		
	
	
	
	
	
		
		
			
		
	
	
			702 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Ada
		
	
	
	
	
	
| 
								 | 
							
								----------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								--  ZLib for Ada thick binding.                               --
							 | 
						||
| 
								 | 
							
								--                                                            --
							 | 
						||
| 
								 | 
							
								--  Copyright (C) 2002-2004 Dmitriy Anisimkov                 --
							 | 
						||
| 
								 | 
							
								--                                                            --
							 | 
						||
| 
								 | 
							
								--  Open source license information is in the zlib.ads file.  --
							 | 
						||
| 
								 | 
							
								----------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								--  $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								with Ada.Exceptions;
							 | 
						||
| 
								 | 
							
								with Ada.Unchecked_Conversion;
							 | 
						||
| 
								 | 
							
								with Ada.Unchecked_Deallocation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								with Interfaces.C.Strings;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								with ZLib.Thin;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package body ZLib is
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   use type Thin.Int;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   type Z_Stream is new 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 is access
							 | 
						||
| 
								 | 
							
								     function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
							 | 
						||
| 
								 | 
							
								   pragma Convention (C, Flate_Step_Function);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   type Flate_End_Function is access
							 | 
						||
| 
								 | 
							
								      function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
							 | 
						||
| 
								 | 
							
								   pragma Convention (C, Flate_End_Function);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   type Flate_Type is record
							 | 
						||
| 
								 | 
							
								      Step : Flate_Step_Function;
							 | 
						||
| 
								 | 
							
								      Done : Flate_End_Function;
							 | 
						||
| 
								 | 
							
								   end record;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   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.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum
							 | 
						||
| 
								 | 
							
								     := (0 => OK,
							 | 
						||
| 
								 | 
							
								         1 => STREAM_END,
							 | 
						||
| 
								 | 
							
								         2 => NEED_DICT,
							 | 
						||
| 
								 | 
							
								        -1 => ERRNO,
							 | 
						||
| 
								 | 
							
								        -2 => STREAM_ERROR,
							 | 
						||
| 
								 | 
							
								        -3 => DATA_ERROR,
							 | 
						||
| 
								 | 
							
								        -4 => MEM_ERROR,
							 | 
						||
| 
								 | 
							
								        -5 => BUF_ERROR,
							 | 
						||
| 
								 | 
							
								        -6 => VERSION_ERROR);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Flate : constant array (Boolean) of Flate_Type
							 | 
						||
| 
								 | 
							
								     := (True  => (Step => Thin.Deflate'Access,
							 | 
						||
| 
								 | 
							
								                   Done => Thin.DeflateEnd'Access),
							 | 
						||
| 
								 | 
							
								         False => (Step => Thin.Inflate'Access,
							 | 
						||
| 
								 | 
							
								                   Done => Thin.InflateEnd'Access));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Flush_Finish : constant array (Boolean) of Flush_Mode
							 | 
						||
| 
								 | 
							
								     := (True => Finish, False => No_Flush);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Raise_Error (Stream : in Z_Stream);
							 | 
						||
| 
								 | 
							
								   pragma Inline (Raise_Error);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Raise_Error (Message : in String);
							 | 
						||
| 
								 | 
							
								   pragma Inline (Raise_Error);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Free is new Ada.Unchecked_Deallocation
							 | 
						||
| 
								 | 
							
								      (Z_Stream, Z_Stream_Access);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   function To_Thin_Access is new Ada.Unchecked_Conversion
							 | 
						||
| 
								 | 
							
								     (Z_Stream_Access, Thin.Z_Streamp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Translate_GZip
							 | 
						||
| 
								 | 
							
								     (Filter    : in out 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    : in out 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.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------------
							 | 
						||
| 
								 | 
							
								   -- Check_Error --
							 | 
						||
| 
								 | 
							
								   -----------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is
							 | 
						||
| 
								 | 
							
								      use type Thin.Int;
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if Code /= Thin.Z_OK then
							 | 
						||
| 
								 | 
							
								         Raise_Error
							 | 
						||
| 
								 | 
							
								            (Return_Code_Enum'Image (Return_Code (Code))
							 | 
						||
| 
								 | 
							
								              & ": " & Last_Error_Message (Stream));
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   end Check_Error;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								   -- Close --
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Close
							 | 
						||
| 
								 | 
							
								     (Filter       : in out Filter_Type;
							 | 
						||
| 
								 | 
							
								      Ignore_Error : in     Boolean := False)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      Code : Thin.Int;
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if not Ignore_Error and then not Is_Open (Filter) then
							 | 
						||
| 
								 | 
							
								         raise Status_Error;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Ignore_Error or else 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;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   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  : in out Unsigned_32;
							 | 
						||
| 
								 | 
							
								      Data : in     Ada.Streams.Stream_Element_Array) is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      CRC := CRC32 (CRC, Data);
							 | 
						||
| 
								 | 
							
								   end CRC32;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   ------------------
							 | 
						||
| 
								 | 
							
								   -- Deflate_Init --
							 | 
						||
| 
								 | 
							
								   ------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Deflate_Init
							 | 
						||
| 
								 | 
							
								     (Filter       : in out 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
							 | 
						||
| 
								 | 
							
								      use type Thin.Int;
							 | 
						||
| 
								 | 
							
								      Win_Bits : Thin.Int := Thin.Int (Window_Bits);
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if Is_Open (Filter) then
							 | 
						||
| 
								 | 
							
								         raise Status_Error;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      --  We allow ZLib to make header only in case of default header type.
							 | 
						||
| 
								 | 
							
								      --  Otherwise we would either do header by ourselfs, or do not do
							 | 
						||
| 
								 | 
							
								      --  header at all.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Header = None or else Header = GZip then
							 | 
						||
| 
								 | 
							
								         Win_Bits := -Win_Bits;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      --  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;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Filter.Strm        := new Z_Stream;
							 | 
						||
| 
								 | 
							
								      Filter.Compression := True;
							 | 
						||
| 
								 | 
							
								      Filter.Stream_End  := False;
							 | 
						||
| 
								 | 
							
								      Filter.Header      := Header;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Thin.Deflate_Init
							 | 
						||
| 
								 | 
							
								           (To_Thin_Access (Filter.Strm),
							 | 
						||
| 
								 | 
							
								            Level      => Thin.Int (Level),
							 | 
						||
| 
								 | 
							
								            method     => Thin.Int (Method),
							 | 
						||
| 
								 | 
							
								            windowBits => Win_Bits,
							 | 
						||
| 
								 | 
							
								            memLevel   => Thin.Int (Memory_Level),
							 | 
						||
| 
								 | 
							
								            strategy   => Thin.Int (Strategy)) /= Thin.Z_OK
							 | 
						||
| 
								 | 
							
								      then
							 | 
						||
| 
								 | 
							
								         Raise_Error (Filter.Strm.all);
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   end Deflate_Init;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								   -- Flush --
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Flush
							 | 
						||
| 
								 | 
							
								     (Filter    : in out Filter_Type;
							 | 
						||
| 
								 | 
							
								      Out_Data  :    out Ada.Streams.Stream_Element_Array;
							 | 
						||
| 
								 | 
							
								      Out_Last  :    out Ada.Streams.Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      Flush     : in     Flush_Mode)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      No_Data : Stream_Element_Array := (1 .. 0 => 0);
							 | 
						||
| 
								 | 
							
								      Last    : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush);
							 | 
						||
| 
								 | 
							
								   end Flush;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------------------
							 | 
						||
| 
								 | 
							
								   -- Generic_Translate --
							 | 
						||
| 
								 | 
							
								   -----------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Generic_Translate
							 | 
						||
| 
								 | 
							
								     (Filter          : in out ZLib.Filter_Type;
							 | 
						||
| 
								 | 
							
								      In_Buffer_Size  : in     Integer := Default_Buffer_Size;
							 | 
						||
| 
								 | 
							
								      Out_Buffer_Size : in     Integer := Default_Buffer_Size)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      In_Buffer  : Stream_Element_Array
							 | 
						||
| 
								 | 
							
								                     (1 .. Stream_Element_Offset (In_Buffer_Size));
							 | 
						||
| 
								 | 
							
								      Out_Buffer : Stream_Element_Array
							 | 
						||
| 
								 | 
							
								                     (1 .. Stream_Element_Offset (Out_Buffer_Size));
							 | 
						||
| 
								 | 
							
								      Last       : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      In_Last    : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      In_First   : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      Out_Last   : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      Main : loop
							 | 
						||
| 
								 | 
							
								         Data_In (In_Buffer, Last);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         In_First := In_Buffer'First;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         loop
							 | 
						||
| 
								 | 
							
								            Translate
							 | 
						||
| 
								 | 
							
								              (Filter   => Filter,
							 | 
						||
| 
								 | 
							
								               In_Data  => In_Buffer (In_First .. Last),
							 | 
						||
| 
								 | 
							
								               In_Last  => In_Last,
							 | 
						||
| 
								 | 
							
								               Out_Data => Out_Buffer,
							 | 
						||
| 
								 | 
							
								               Out_Last => Out_Last,
							 | 
						||
| 
								 | 
							
								               Flush    => Flush_Finish (Last < In_Buffer'First));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if Out_Buffer'First <= Out_Last then
							 | 
						||
| 
								 | 
							
								               Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
							 | 
						||
| 
								 | 
							
								            end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            exit Main when Stream_End (Filter);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            --  The end of in buffer.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            exit when In_Last = Last;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            In_First := In_Last + 1;
							 | 
						||
| 
								 | 
							
								         end loop;
							 | 
						||
| 
								 | 
							
								      end loop Main;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   end Generic_Translate;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   ------------------
							 | 
						||
| 
								 | 
							
								   -- Inflate_Init --
							 | 
						||
| 
								 | 
							
								   ------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Inflate_Init
							 | 
						||
| 
								 | 
							
								     (Filter      : in out Filter_Type;
							 | 
						||
| 
								 | 
							
								      Window_Bits : in     Window_Bits_Type := Default_Window_Bits;
							 | 
						||
| 
								 | 
							
								      Header      : in     Header_Type      := Default)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      use type 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);
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								      end Check_Version;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if Is_Open (Filter) then
							 | 
						||
| 
								 | 
							
								         raise Status_Error;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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;
							 | 
						||
| 
								 | 
							
								      end case;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Filter.Strm        := new Z_Stream;
							 | 
						||
| 
								 | 
							
								      Filter.Compression := False;
							 | 
						||
| 
								 | 
							
								      Filter.Stream_End  := False;
							 | 
						||
| 
								 | 
							
								      Filter.Header      := Header;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Thin.Inflate_Init
							 | 
						||
| 
								 | 
							
								         (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK
							 | 
						||
| 
								 | 
							
								      then
							 | 
						||
| 
								 | 
							
								         Raise_Error (Filter.Strm.all);
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   end Inflate_Init;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -------------
							 | 
						||
| 
								 | 
							
								   -- Is_Open --
							 | 
						||
| 
								 | 
							
								   -------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   function Is_Open (Filter : in Filter_Type) return Boolean is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      return Filter.Strm /= null;
							 | 
						||
| 
								 | 
							
								   end Is_Open;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------------
							 | 
						||
| 
								 | 
							
								   -- Raise_Error --
							 | 
						||
| 
								 | 
							
								   -----------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Raise_Error (Message : in String) is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
							 | 
						||
| 
								 | 
							
								   end Raise_Error;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Raise_Error (Stream : in Z_Stream) is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      Raise_Error (Last_Error_Message (Stream));
							 | 
						||
| 
								 | 
							
								   end Raise_Error;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   ----------
							 | 
						||
| 
								 | 
							
								   -- Read --
							 | 
						||
| 
								 | 
							
								   ----------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Read
							 | 
						||
| 
								 | 
							
								     (Filter : in out Filter_Type;
							 | 
						||
| 
								 | 
							
								      Item   :    out Ada.Streams.Stream_Element_Array;
							 | 
						||
| 
								 | 
							
								      Last   :    out Ada.Streams.Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      Flush  : in     Flush_Mode := No_Flush)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      In_Last    : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
							 | 
						||
| 
								 | 
							
								      V_Flush    : Flush_Mode := Flush;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
							 | 
						||
| 
								 | 
							
								      pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      loop
							 | 
						||
| 
								 | 
							
								         if Rest_Last = Buffer'First - 1 then
							 | 
						||
| 
								 | 
							
								            V_Flush := Finish;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         elsif Rest_First > Rest_Last then
							 | 
						||
| 
								 | 
							
								            Read (Buffer, Rest_Last);
							 | 
						||
| 
								 | 
							
								            Rest_First := Buffer'First;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if Rest_Last < Buffer'First then
							 | 
						||
| 
								 | 
							
								               V_Flush := Finish;
							 | 
						||
| 
								 | 
							
								            end if;
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Translate
							 | 
						||
| 
								 | 
							
								           (Filter   => Filter,
							 | 
						||
| 
								 | 
							
								            In_Data  => Buffer (Rest_First .. Rest_Last),
							 | 
						||
| 
								 | 
							
								            In_Last  => In_Last,
							 | 
						||
| 
								 | 
							
								            Out_Data => Item (Item_First .. Item'Last),
							 | 
						||
| 
								 | 
							
								            Out_Last => Last,
							 | 
						||
| 
								 | 
							
								            Flush    => V_Flush);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Rest_First := In_Last + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         exit when Stream_End (Filter)
							 | 
						||
| 
								 | 
							
								           or else Last = Item'Last
							 | 
						||
| 
								 | 
							
								           or else (Last >= Item'First and then Allow_Read_Some);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Item_First := Last + 1;
							 | 
						||
| 
								 | 
							
								      end loop;
							 | 
						||
| 
								 | 
							
								   end Read;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   ----------------
							 | 
						||
| 
								 | 
							
								   -- Stream_End --
							 | 
						||
| 
								 | 
							
								   ----------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   function Stream_End (Filter : in Filter_Type) return Boolean is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if Filter.Header = GZip and Filter.Compression then
							 | 
						||
| 
								 | 
							
								         return Filter.Stream_End
							 | 
						||
| 
								 | 
							
								            and then Filter.Offset = Footer_Array'Last + 1;
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								         return Filter.Stream_End;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   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    : in out 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 and then 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);
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   end Translate;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   --------------------
							 | 
						||
| 
								 | 
							
								   -- Translate_Auto --
							 | 
						||
| 
								 | 
							
								   --------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Translate_Auto
							 | 
						||
| 
								 | 
							
								     (Filter    : in out 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
							 | 
						||
| 
								 | 
							
								      use type Thin.Int;
							 | 
						||
| 
								 | 
							
								      Code : Thin.Int;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if not Is_Open (Filter) then
							 | 
						||
| 
								 | 
							
								         raise Status_Error;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Out_Data'Length = 0 and then In_Data'Length = 0 then
							 | 
						||
| 
								 | 
							
								         raise Constraint_Error;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length);
							 | 
						||
| 
								 | 
							
								      Set_In  (Filter.Strm.all, In_Data'Address, In_Data'Length);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Code := Flate (Filter.Compression).Step
							 | 
						||
| 
								 | 
							
								        (To_Thin_Access (Filter.Strm),
							 | 
						||
| 
								 | 
							
								         Thin.Int (Flush));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Code = Thin.Z_STREAM_END then
							 | 
						||
| 
								 | 
							
								         Filter.Stream_End := True;
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								         Check_Error (Filter.Strm.all, Code);
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      In_Last  := In_Data'Last
							 | 
						||
| 
								 | 
							
								         - Stream_Element_Offset (Avail_In (Filter.Strm.all));
							 | 
						||
| 
								 | 
							
								      Out_Last := Out_Data'Last
							 | 
						||
| 
								 | 
							
								         - Stream_Element_Offset (Avail_Out (Filter.Strm.all));
							 | 
						||
| 
								 | 
							
								   end Translate_Auto;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   --------------------
							 | 
						||
| 
								 | 
							
								   -- Translate_GZip --
							 | 
						||
| 
								 | 
							
								   --------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Translate_GZip
							 | 
						||
| 
								 | 
							
								     (Filter    : in out 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 : in out Stream_Element_Array;
							 | 
						||
| 
								 | 
							
								         Data : in     Unsigned_32);
							 | 
						||
| 
								 | 
							
								      pragma Inline (Put_32);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      --------------
							 | 
						||
| 
								 | 
							
								      -- Add_Data --
							 | 
						||
| 
								 | 
							
								      --------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      procedure Add_Data (Data : in Stream_Element_Array) is
							 | 
						||
| 
								 | 
							
								         Data_First : Stream_Element_Offset renames Filter.Offset;
							 | 
						||
| 
								 | 
							
								         Data_Last  : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								         Data_Len   : Stream_Element_Offset; --  -1
							 | 
						||
| 
								 | 
							
								         Out_Len    : Stream_Element_Offset; --  -1
							 | 
						||
| 
								 | 
							
								      begin
							 | 
						||
| 
								 | 
							
								         Out_First := Out_Last + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         if Data_First > Data'Last then
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Data_Len  := Data'Last     - Data_First;
							 | 
						||
| 
								 | 
							
								         Out_Len   := Out_Data'Last - Out_First;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         if Data_Len <= Out_Len then
							 | 
						||
| 
								 | 
							
								            Out_Last  := Out_First  + Data_Len;
							 | 
						||
| 
								 | 
							
								            Data_Last := Data'Last;
							 | 
						||
| 
								 | 
							
								         else
							 | 
						||
| 
								 | 
							
								            Out_Last  := Out_Data'Last;
							 | 
						||
| 
								 | 
							
								            Data_Last := Data_First + Out_Len;
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Data_First := Data_Last + 1;
							 | 
						||
| 
								 | 
							
								         Out_First  := Out_Last + 1;
							 | 
						||
| 
								 | 
							
								      end Add_Data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      ------------
							 | 
						||
| 
								 | 
							
								      -- Put_32 --
							 | 
						||
| 
								 | 
							
								      ------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      procedure Put_32
							 | 
						||
| 
								 | 
							
								        (Item : in out 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);
							 | 
						||
| 
								 | 
							
								         end loop;
							 | 
						||
| 
								 | 
							
								      end Put_32;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      Out_Last := Out_Data'First - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if not Filter.Stream_End then
							 | 
						||
| 
								 | 
							
								         Add_Data (Simple_GZip_Header);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         Translate_Auto
							 | 
						||
| 
								 | 
							
								           (Filter   => Filter,
							 | 
						||
| 
								 | 
							
								            In_Data  => In_Data,
							 | 
						||
| 
								 | 
							
								            In_Last  => In_Last,
							 | 
						||
| 
								 | 
							
								            Out_Data => Out_Data (Out_First .. Out_Data'Last),
							 | 
						||
| 
								 | 
							
								            Out_Last => Out_Last,
							 | 
						||
| 
								 | 
							
								            Flush    => Flush);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if Filter.Stream_End and then 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;
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         declare
							 | 
						||
| 
								 | 
							
								            Footer : Footer_Array;
							 | 
						||
| 
								 | 
							
								         begin
							 | 
						||
| 
								 | 
							
								            Put_32 (Footer, Filter.CRC);
							 | 
						||
| 
								 | 
							
								            Put_32 (Footer (Footer'First + 4 .. Footer'Last),
							 | 
						||
| 
								 | 
							
								                    Unsigned_32 (Total_In (Filter)));
							 | 
						||
| 
								 | 
							
								            Add_Data (Footer);
							 | 
						||
| 
								 | 
							
								         end;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								   end Translate_GZip;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -------------
							 | 
						||
| 
								 | 
							
								   -- Version --
							 | 
						||
| 
								 | 
							
								   -------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   function Version return String is
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      return Interfaces.C.Strings.Value (Thin.zlibVersion);
							 | 
						||
| 
								 | 
							
								   end Version;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								   -- Write --
							 | 
						||
| 
								 | 
							
								   -----------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   procedure Write
							 | 
						||
| 
								 | 
							
								     (Filter : in out Filter_Type;
							 | 
						||
| 
								 | 
							
								      Item   : in     Ada.Streams.Stream_Element_Array;
							 | 
						||
| 
								 | 
							
								      Flush  : in     Flush_Mode := No_Flush)
							 | 
						||
| 
								 | 
							
								   is
							 | 
						||
| 
								 | 
							
								      Buffer   : Stream_Element_Array (1 .. Buffer_Size);
							 | 
						||
| 
								 | 
							
								      In_Last  : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      Out_Last : Stream_Element_Offset;
							 | 
						||
| 
								 | 
							
								      In_First : Stream_Element_Offset := Item'First;
							 | 
						||
| 
								 | 
							
								   begin
							 | 
						||
| 
								 | 
							
								      if Item'Length = 0 and Flush = No_Flush then
							 | 
						||
| 
								 | 
							
								         return;
							 | 
						||
| 
								 | 
							
								      end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      loop
							 | 
						||
| 
								 | 
							
								         Translate
							 | 
						||
| 
								 | 
							
								           (Filter   => Filter,
							 | 
						||
| 
								 | 
							
								            In_Data  => Item (In_First .. Item'Last),
							 | 
						||
| 
								 | 
							
								            In_Last  => In_Last,
							 | 
						||
| 
								 | 
							
								            Out_Data => Buffer,
							 | 
						||
| 
								 | 
							
								            Out_Last => Out_Last,
							 | 
						||
| 
								 | 
							
								            Flush    => Flush);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         if Out_Last >= Buffer'First then
							 | 
						||
| 
								 | 
							
								            Write (Buffer (1 .. Out_Last));
							 | 
						||
| 
								 | 
							
								         end if;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         exit when In_Last = Item'Last or Stream_End (Filter);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         In_First := In_Last + 1;
							 | 
						||
| 
								 | 
							
								      end loop;
							 | 
						||
| 
								 | 
							
								   end Write;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								end ZLib;
							 |