1*44bedb31SLionel Sambuc---------------------------------------------------------------- 2*44bedb31SLionel Sambuc-- ZLib for Ada thick binding. -- 3*44bedb31SLionel Sambuc-- -- 4*44bedb31SLionel Sambuc-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- 5*44bedb31SLionel Sambuc-- -- 6*44bedb31SLionel Sambuc-- Open source license information is in the zlib.ads file. -- 7*44bedb31SLionel Sambuc---------------------------------------------------------------- 8*44bedb31SLionel Sambuc 9*44bedb31SLionel Sambuc-- Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp 10*44bedb31SLionel Sambuc 11*44bedb31SLionel Sambucwith Ada.Exceptions; 12*44bedb31SLionel Sambucwith Ada.Unchecked_Conversion; 13*44bedb31SLionel Sambucwith Ada.Unchecked_Deallocation; 14*44bedb31SLionel Sambuc 15*44bedb31SLionel Sambucwith Interfaces.C.Strings; 16*44bedb31SLionel Sambuc 17*44bedb31SLionel Sambucwith ZLib.Thin; 18*44bedb31SLionel Sambuc 19*44bedb31SLionel Sambucpackage body ZLib is 20*44bedb31SLionel Sambuc 21*44bedb31SLionel Sambuc use type Thin.Int; 22*44bedb31SLionel Sambuc 23*44bedb31SLionel Sambuc type Z_Stream is new Thin.Z_Stream; 24*44bedb31SLionel Sambuc 25*44bedb31SLionel Sambuc type Return_Code_Enum is 26*44bedb31SLionel Sambuc (OK, 27*44bedb31SLionel Sambuc STREAM_END, 28*44bedb31SLionel Sambuc NEED_DICT, 29*44bedb31SLionel Sambuc ERRNO, 30*44bedb31SLionel Sambuc STREAM_ERROR, 31*44bedb31SLionel Sambuc DATA_ERROR, 32*44bedb31SLionel Sambuc MEM_ERROR, 33*44bedb31SLionel Sambuc BUF_ERROR, 34*44bedb31SLionel Sambuc VERSION_ERROR); 35*44bedb31SLionel Sambuc 36*44bedb31SLionel Sambuc type Flate_Step_Function is access 37*44bedb31SLionel Sambuc function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; 38*44bedb31SLionel Sambuc pragma Convention (C, Flate_Step_Function); 39*44bedb31SLionel Sambuc 40*44bedb31SLionel Sambuc type Flate_End_Function is access 41*44bedb31SLionel Sambuc function (Ctrm : in Thin.Z_Streamp) return Thin.Int; 42*44bedb31SLionel Sambuc pragma Convention (C, Flate_End_Function); 43*44bedb31SLionel Sambuc 44*44bedb31SLionel Sambuc type Flate_Type is record 45*44bedb31SLionel Sambuc Step : Flate_Step_Function; 46*44bedb31SLionel Sambuc Done : Flate_End_Function; 47*44bedb31SLionel Sambuc end record; 48*44bedb31SLionel Sambuc 49*44bedb31SLionel Sambuc subtype Footer_Array is Stream_Element_Array (1 .. 8); 50*44bedb31SLionel Sambuc 51*44bedb31SLionel Sambuc Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) 52*44bedb31SLionel Sambuc := (16#1f#, 16#8b#, -- Magic header 53*44bedb31SLionel Sambuc 16#08#, -- Z_DEFLATED 54*44bedb31SLionel Sambuc 16#00#, -- Flags 55*44bedb31SLionel Sambuc 16#00#, 16#00#, 16#00#, 16#00#, -- Time 56*44bedb31SLionel Sambuc 16#00#, -- XFlags 57*44bedb31SLionel Sambuc 16#03# -- OS code 58*44bedb31SLionel Sambuc ); 59*44bedb31SLionel Sambuc -- The simplest gzip header is not for informational, but just for 60*44bedb31SLionel Sambuc -- gzip format compatibility. 61*44bedb31SLionel Sambuc -- Note that some code below is using assumption 62*44bedb31SLionel Sambuc -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make 63*44bedb31SLionel Sambuc -- Simple_GZip_Header'Last <= Footer_Array'Last. 64*44bedb31SLionel Sambuc 65*44bedb31SLionel Sambuc Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum 66*44bedb31SLionel Sambuc := (0 => OK, 67*44bedb31SLionel Sambuc 1 => STREAM_END, 68*44bedb31SLionel Sambuc 2 => NEED_DICT, 69*44bedb31SLionel Sambuc -1 => ERRNO, 70*44bedb31SLionel Sambuc -2 => STREAM_ERROR, 71*44bedb31SLionel Sambuc -3 => DATA_ERROR, 72*44bedb31SLionel Sambuc -4 => MEM_ERROR, 73*44bedb31SLionel Sambuc -5 => BUF_ERROR, 74*44bedb31SLionel Sambuc -6 => VERSION_ERROR); 75*44bedb31SLionel Sambuc 76*44bedb31SLionel Sambuc Flate : constant array (Boolean) of Flate_Type 77*44bedb31SLionel Sambuc := (True => (Step => Thin.Deflate'Access, 78*44bedb31SLionel Sambuc Done => Thin.DeflateEnd'Access), 79*44bedb31SLionel Sambuc False => (Step => Thin.Inflate'Access, 80*44bedb31SLionel Sambuc Done => Thin.InflateEnd'Access)); 81*44bedb31SLionel Sambuc 82*44bedb31SLionel Sambuc Flush_Finish : constant array (Boolean) of Flush_Mode 83*44bedb31SLionel Sambuc := (True => Finish, False => No_Flush); 84*44bedb31SLionel Sambuc 85*44bedb31SLionel Sambuc procedure Raise_Error (Stream : in Z_Stream); 86*44bedb31SLionel Sambuc pragma Inline (Raise_Error); 87*44bedb31SLionel Sambuc 88*44bedb31SLionel Sambuc procedure Raise_Error (Message : in String); 89*44bedb31SLionel Sambuc pragma Inline (Raise_Error); 90*44bedb31SLionel Sambuc 91*44bedb31SLionel Sambuc procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); 92*44bedb31SLionel Sambuc 93*44bedb31SLionel Sambuc procedure Free is new Ada.Unchecked_Deallocation 94*44bedb31SLionel Sambuc (Z_Stream, Z_Stream_Access); 95*44bedb31SLionel Sambuc 96*44bedb31SLionel Sambuc function To_Thin_Access is new Ada.Unchecked_Conversion 97*44bedb31SLionel Sambuc (Z_Stream_Access, Thin.Z_Streamp); 98*44bedb31SLionel Sambuc 99*44bedb31SLionel Sambuc procedure Translate_GZip 100*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 101*44bedb31SLionel Sambuc In_Data : in Ada.Streams.Stream_Element_Array; 102*44bedb31SLionel Sambuc In_Last : out Ada.Streams.Stream_Element_Offset; 103*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 104*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 105*44bedb31SLionel Sambuc Flush : in Flush_Mode); 106*44bedb31SLionel Sambuc -- Separate translate routine for make gzip header. 107*44bedb31SLionel Sambuc 108*44bedb31SLionel Sambuc procedure Translate_Auto 109*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 110*44bedb31SLionel Sambuc In_Data : in Ada.Streams.Stream_Element_Array; 111*44bedb31SLionel Sambuc In_Last : out Ada.Streams.Stream_Element_Offset; 112*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 113*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 114*44bedb31SLionel Sambuc Flush : in Flush_Mode); 115*44bedb31SLionel Sambuc -- translate routine without additional headers. 116*44bedb31SLionel Sambuc 117*44bedb31SLionel Sambuc ----------------- 118*44bedb31SLionel Sambuc -- Check_Error -- 119*44bedb31SLionel Sambuc ----------------- 120*44bedb31SLionel Sambuc 121*44bedb31SLionel Sambuc procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is 122*44bedb31SLionel Sambuc use type Thin.Int; 123*44bedb31SLionel Sambuc begin 124*44bedb31SLionel Sambuc if Code /= Thin.Z_OK then 125*44bedb31SLionel Sambuc Raise_Error 126*44bedb31SLionel Sambuc (Return_Code_Enum'Image (Return_Code (Code)) 127*44bedb31SLionel Sambuc & ": " & Last_Error_Message (Stream)); 128*44bedb31SLionel Sambuc end if; 129*44bedb31SLionel Sambuc end Check_Error; 130*44bedb31SLionel Sambuc 131*44bedb31SLionel Sambuc ----------- 132*44bedb31SLionel Sambuc -- Close -- 133*44bedb31SLionel Sambuc ----------- 134*44bedb31SLionel Sambuc 135*44bedb31SLionel Sambuc procedure Close 136*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 137*44bedb31SLionel Sambuc Ignore_Error : in Boolean := False) 138*44bedb31SLionel Sambuc is 139*44bedb31SLionel Sambuc Code : Thin.Int; 140*44bedb31SLionel Sambuc begin 141*44bedb31SLionel Sambuc if not Ignore_Error and then not Is_Open (Filter) then 142*44bedb31SLionel Sambuc raise Status_Error; 143*44bedb31SLionel Sambuc end if; 144*44bedb31SLionel Sambuc 145*44bedb31SLionel Sambuc Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); 146*44bedb31SLionel Sambuc 147*44bedb31SLionel Sambuc if Ignore_Error or else Code = Thin.Z_OK then 148*44bedb31SLionel Sambuc Free (Filter.Strm); 149*44bedb31SLionel Sambuc else 150*44bedb31SLionel Sambuc declare 151*44bedb31SLionel Sambuc Error_Message : constant String 152*44bedb31SLionel Sambuc := Last_Error_Message (Filter.Strm.all); 153*44bedb31SLionel Sambuc begin 154*44bedb31SLionel Sambuc Free (Filter.Strm); 155*44bedb31SLionel Sambuc Ada.Exceptions.Raise_Exception 156*44bedb31SLionel Sambuc (ZLib_Error'Identity, 157*44bedb31SLionel Sambuc Return_Code_Enum'Image (Return_Code (Code)) 158*44bedb31SLionel Sambuc & ": " & Error_Message); 159*44bedb31SLionel Sambuc end; 160*44bedb31SLionel Sambuc end if; 161*44bedb31SLionel Sambuc end Close; 162*44bedb31SLionel Sambuc 163*44bedb31SLionel Sambuc ----------- 164*44bedb31SLionel Sambuc -- CRC32 -- 165*44bedb31SLionel Sambuc ----------- 166*44bedb31SLionel Sambuc 167*44bedb31SLionel Sambuc function CRC32 168*44bedb31SLionel Sambuc (CRC : in Unsigned_32; 169*44bedb31SLionel Sambuc Data : in Ada.Streams.Stream_Element_Array) 170*44bedb31SLionel Sambuc return Unsigned_32 171*44bedb31SLionel Sambuc is 172*44bedb31SLionel Sambuc use Thin; 173*44bedb31SLionel Sambuc begin 174*44bedb31SLionel Sambuc return Unsigned_32 (crc32 (ULong (CRC), 175*44bedb31SLionel Sambuc Data'Address, 176*44bedb31SLionel Sambuc Data'Length)); 177*44bedb31SLionel Sambuc end CRC32; 178*44bedb31SLionel Sambuc 179*44bedb31SLionel Sambuc procedure CRC32 180*44bedb31SLionel Sambuc (CRC : in out Unsigned_32; 181*44bedb31SLionel Sambuc Data : in Ada.Streams.Stream_Element_Array) is 182*44bedb31SLionel Sambuc begin 183*44bedb31SLionel Sambuc CRC := CRC32 (CRC, Data); 184*44bedb31SLionel Sambuc end CRC32; 185*44bedb31SLionel Sambuc 186*44bedb31SLionel Sambuc ------------------ 187*44bedb31SLionel Sambuc -- Deflate_Init -- 188*44bedb31SLionel Sambuc ------------------ 189*44bedb31SLionel Sambuc 190*44bedb31SLionel Sambuc procedure Deflate_Init 191*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 192*44bedb31SLionel Sambuc Level : in Compression_Level := Default_Compression; 193*44bedb31SLionel Sambuc Strategy : in Strategy_Type := Default_Strategy; 194*44bedb31SLionel Sambuc Method : in Compression_Method := Deflated; 195*44bedb31SLionel Sambuc Window_Bits : in Window_Bits_Type := Default_Window_Bits; 196*44bedb31SLionel Sambuc Memory_Level : in Memory_Level_Type := Default_Memory_Level; 197*44bedb31SLionel Sambuc Header : in Header_Type := Default) 198*44bedb31SLionel Sambuc is 199*44bedb31SLionel Sambuc use type Thin.Int; 200*44bedb31SLionel Sambuc Win_Bits : Thin.Int := Thin.Int (Window_Bits); 201*44bedb31SLionel Sambuc begin 202*44bedb31SLionel Sambuc if Is_Open (Filter) then 203*44bedb31SLionel Sambuc raise Status_Error; 204*44bedb31SLionel Sambuc end if; 205*44bedb31SLionel Sambuc 206*44bedb31SLionel Sambuc -- We allow ZLib to make header only in case of default header type. 207*44bedb31SLionel Sambuc -- Otherwise we would either do header by ourselfs, or do not do 208*44bedb31SLionel Sambuc -- header at all. 209*44bedb31SLionel Sambuc 210*44bedb31SLionel Sambuc if Header = None or else Header = GZip then 211*44bedb31SLionel Sambuc Win_Bits := -Win_Bits; 212*44bedb31SLionel Sambuc end if; 213*44bedb31SLionel Sambuc 214*44bedb31SLionel Sambuc -- For the GZip CRC calculation and make headers. 215*44bedb31SLionel Sambuc 216*44bedb31SLionel Sambuc if Header = GZip then 217*44bedb31SLionel Sambuc Filter.CRC := 0; 218*44bedb31SLionel Sambuc Filter.Offset := Simple_GZip_Header'First; 219*44bedb31SLionel Sambuc else 220*44bedb31SLionel Sambuc Filter.Offset := Simple_GZip_Header'Last + 1; 221*44bedb31SLionel Sambuc end if; 222*44bedb31SLionel Sambuc 223*44bedb31SLionel Sambuc Filter.Strm := new Z_Stream; 224*44bedb31SLionel Sambuc Filter.Compression := True; 225*44bedb31SLionel Sambuc Filter.Stream_End := False; 226*44bedb31SLionel Sambuc Filter.Header := Header; 227*44bedb31SLionel Sambuc 228*44bedb31SLionel Sambuc if Thin.Deflate_Init 229*44bedb31SLionel Sambuc (To_Thin_Access (Filter.Strm), 230*44bedb31SLionel Sambuc Level => Thin.Int (Level), 231*44bedb31SLionel Sambuc method => Thin.Int (Method), 232*44bedb31SLionel Sambuc windowBits => Win_Bits, 233*44bedb31SLionel Sambuc memLevel => Thin.Int (Memory_Level), 234*44bedb31SLionel Sambuc strategy => Thin.Int (Strategy)) /= Thin.Z_OK 235*44bedb31SLionel Sambuc then 236*44bedb31SLionel Sambuc Raise_Error (Filter.Strm.all); 237*44bedb31SLionel Sambuc end if; 238*44bedb31SLionel Sambuc end Deflate_Init; 239*44bedb31SLionel Sambuc 240*44bedb31SLionel Sambuc ----------- 241*44bedb31SLionel Sambuc -- Flush -- 242*44bedb31SLionel Sambuc ----------- 243*44bedb31SLionel Sambuc 244*44bedb31SLionel Sambuc procedure Flush 245*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 246*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 247*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 248*44bedb31SLionel Sambuc Flush : in Flush_Mode) 249*44bedb31SLionel Sambuc is 250*44bedb31SLionel Sambuc No_Data : Stream_Element_Array := (1 .. 0 => 0); 251*44bedb31SLionel Sambuc Last : Stream_Element_Offset; 252*44bedb31SLionel Sambuc begin 253*44bedb31SLionel Sambuc Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); 254*44bedb31SLionel Sambuc end Flush; 255*44bedb31SLionel Sambuc 256*44bedb31SLionel Sambuc ----------------------- 257*44bedb31SLionel Sambuc -- Generic_Translate -- 258*44bedb31SLionel Sambuc ----------------------- 259*44bedb31SLionel Sambuc 260*44bedb31SLionel Sambuc procedure Generic_Translate 261*44bedb31SLionel Sambuc (Filter : in out ZLib.Filter_Type; 262*44bedb31SLionel Sambuc In_Buffer_Size : in Integer := Default_Buffer_Size; 263*44bedb31SLionel Sambuc Out_Buffer_Size : in Integer := Default_Buffer_Size) 264*44bedb31SLionel Sambuc is 265*44bedb31SLionel Sambuc In_Buffer : Stream_Element_Array 266*44bedb31SLionel Sambuc (1 .. Stream_Element_Offset (In_Buffer_Size)); 267*44bedb31SLionel Sambuc Out_Buffer : Stream_Element_Array 268*44bedb31SLionel Sambuc (1 .. Stream_Element_Offset (Out_Buffer_Size)); 269*44bedb31SLionel Sambuc Last : Stream_Element_Offset; 270*44bedb31SLionel Sambuc In_Last : Stream_Element_Offset; 271*44bedb31SLionel Sambuc In_First : Stream_Element_Offset; 272*44bedb31SLionel Sambuc Out_Last : Stream_Element_Offset; 273*44bedb31SLionel Sambuc begin 274*44bedb31SLionel Sambuc Main : loop 275*44bedb31SLionel Sambuc Data_In (In_Buffer, Last); 276*44bedb31SLionel Sambuc 277*44bedb31SLionel Sambuc In_First := In_Buffer'First; 278*44bedb31SLionel Sambuc 279*44bedb31SLionel Sambuc loop 280*44bedb31SLionel Sambuc Translate 281*44bedb31SLionel Sambuc (Filter => Filter, 282*44bedb31SLionel Sambuc In_Data => In_Buffer (In_First .. Last), 283*44bedb31SLionel Sambuc In_Last => In_Last, 284*44bedb31SLionel Sambuc Out_Data => Out_Buffer, 285*44bedb31SLionel Sambuc Out_Last => Out_Last, 286*44bedb31SLionel Sambuc Flush => Flush_Finish (Last < In_Buffer'First)); 287*44bedb31SLionel Sambuc 288*44bedb31SLionel Sambuc if Out_Buffer'First <= Out_Last then 289*44bedb31SLionel Sambuc Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); 290*44bedb31SLionel Sambuc end if; 291*44bedb31SLionel Sambuc 292*44bedb31SLionel Sambuc exit Main when Stream_End (Filter); 293*44bedb31SLionel Sambuc 294*44bedb31SLionel Sambuc -- The end of in buffer. 295*44bedb31SLionel Sambuc 296*44bedb31SLionel Sambuc exit when In_Last = Last; 297*44bedb31SLionel Sambuc 298*44bedb31SLionel Sambuc In_First := In_Last + 1; 299*44bedb31SLionel Sambuc end loop; 300*44bedb31SLionel Sambuc end loop Main; 301*44bedb31SLionel Sambuc 302*44bedb31SLionel Sambuc end Generic_Translate; 303*44bedb31SLionel Sambuc 304*44bedb31SLionel Sambuc ------------------ 305*44bedb31SLionel Sambuc -- Inflate_Init -- 306*44bedb31SLionel Sambuc ------------------ 307*44bedb31SLionel Sambuc 308*44bedb31SLionel Sambuc procedure Inflate_Init 309*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 310*44bedb31SLionel Sambuc Window_Bits : in Window_Bits_Type := Default_Window_Bits; 311*44bedb31SLionel Sambuc Header : in Header_Type := Default) 312*44bedb31SLionel Sambuc is 313*44bedb31SLionel Sambuc use type Thin.Int; 314*44bedb31SLionel Sambuc Win_Bits : Thin.Int := Thin.Int (Window_Bits); 315*44bedb31SLionel Sambuc 316*44bedb31SLionel Sambuc procedure Check_Version; 317*44bedb31SLionel Sambuc -- Check the latest header types compatibility. 318*44bedb31SLionel Sambuc 319*44bedb31SLionel Sambuc procedure Check_Version is 320*44bedb31SLionel Sambuc begin 321*44bedb31SLionel Sambuc if Version <= "1.1.4" then 322*44bedb31SLionel Sambuc Raise_Error 323*44bedb31SLionel Sambuc ("Inflate header type " & Header_Type'Image (Header) 324*44bedb31SLionel Sambuc & " incompatible with ZLib version " & Version); 325*44bedb31SLionel Sambuc end if; 326*44bedb31SLionel Sambuc end Check_Version; 327*44bedb31SLionel Sambuc 328*44bedb31SLionel Sambuc begin 329*44bedb31SLionel Sambuc if Is_Open (Filter) then 330*44bedb31SLionel Sambuc raise Status_Error; 331*44bedb31SLionel Sambuc end if; 332*44bedb31SLionel Sambuc 333*44bedb31SLionel Sambuc case Header is 334*44bedb31SLionel Sambuc when None => 335*44bedb31SLionel Sambuc Check_Version; 336*44bedb31SLionel Sambuc 337*44bedb31SLionel Sambuc -- Inflate data without headers determined 338*44bedb31SLionel Sambuc -- by negative Win_Bits. 339*44bedb31SLionel Sambuc 340*44bedb31SLionel Sambuc Win_Bits := -Win_Bits; 341*44bedb31SLionel Sambuc when GZip => 342*44bedb31SLionel Sambuc Check_Version; 343*44bedb31SLionel Sambuc 344*44bedb31SLionel Sambuc -- Inflate gzip data defined by flag 16. 345*44bedb31SLionel Sambuc 346*44bedb31SLionel Sambuc Win_Bits := Win_Bits + 16; 347*44bedb31SLionel Sambuc when Auto => 348*44bedb31SLionel Sambuc Check_Version; 349*44bedb31SLionel Sambuc 350*44bedb31SLionel Sambuc -- Inflate with automatic detection 351*44bedb31SLionel Sambuc -- of gzip or native header defined by flag 32. 352*44bedb31SLionel Sambuc 353*44bedb31SLionel Sambuc Win_Bits := Win_Bits + 32; 354*44bedb31SLionel Sambuc when Default => null; 355*44bedb31SLionel Sambuc end case; 356*44bedb31SLionel Sambuc 357*44bedb31SLionel Sambuc Filter.Strm := new Z_Stream; 358*44bedb31SLionel Sambuc Filter.Compression := False; 359*44bedb31SLionel Sambuc Filter.Stream_End := False; 360*44bedb31SLionel Sambuc Filter.Header := Header; 361*44bedb31SLionel Sambuc 362*44bedb31SLionel Sambuc if Thin.Inflate_Init 363*44bedb31SLionel Sambuc (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK 364*44bedb31SLionel Sambuc then 365*44bedb31SLionel Sambuc Raise_Error (Filter.Strm.all); 366*44bedb31SLionel Sambuc end if; 367*44bedb31SLionel Sambuc end Inflate_Init; 368*44bedb31SLionel Sambuc 369*44bedb31SLionel Sambuc ------------- 370*44bedb31SLionel Sambuc -- Is_Open -- 371*44bedb31SLionel Sambuc ------------- 372*44bedb31SLionel Sambuc 373*44bedb31SLionel Sambuc function Is_Open (Filter : in Filter_Type) return Boolean is 374*44bedb31SLionel Sambuc begin 375*44bedb31SLionel Sambuc return Filter.Strm /= null; 376*44bedb31SLionel Sambuc end Is_Open; 377*44bedb31SLionel Sambuc 378*44bedb31SLionel Sambuc ----------------- 379*44bedb31SLionel Sambuc -- Raise_Error -- 380*44bedb31SLionel Sambuc ----------------- 381*44bedb31SLionel Sambuc 382*44bedb31SLionel Sambuc procedure Raise_Error (Message : in String) is 383*44bedb31SLionel Sambuc begin 384*44bedb31SLionel Sambuc Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); 385*44bedb31SLionel Sambuc end Raise_Error; 386*44bedb31SLionel Sambuc 387*44bedb31SLionel Sambuc procedure Raise_Error (Stream : in Z_Stream) is 388*44bedb31SLionel Sambuc begin 389*44bedb31SLionel Sambuc Raise_Error (Last_Error_Message (Stream)); 390*44bedb31SLionel Sambuc end Raise_Error; 391*44bedb31SLionel Sambuc 392*44bedb31SLionel Sambuc ---------- 393*44bedb31SLionel Sambuc -- Read -- 394*44bedb31SLionel Sambuc ---------- 395*44bedb31SLionel Sambuc 396*44bedb31SLionel Sambuc procedure Read 397*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 398*44bedb31SLionel Sambuc Item : out Ada.Streams.Stream_Element_Array; 399*44bedb31SLionel Sambuc Last : out Ada.Streams.Stream_Element_Offset; 400*44bedb31SLionel Sambuc Flush : in Flush_Mode := No_Flush) 401*44bedb31SLionel Sambuc is 402*44bedb31SLionel Sambuc In_Last : Stream_Element_Offset; 403*44bedb31SLionel Sambuc Item_First : Ada.Streams.Stream_Element_Offset := Item'First; 404*44bedb31SLionel Sambuc V_Flush : Flush_Mode := Flush; 405*44bedb31SLionel Sambuc 406*44bedb31SLionel Sambuc begin 407*44bedb31SLionel Sambuc pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); 408*44bedb31SLionel Sambuc pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); 409*44bedb31SLionel Sambuc 410*44bedb31SLionel Sambuc loop 411*44bedb31SLionel Sambuc if Rest_Last = Buffer'First - 1 then 412*44bedb31SLionel Sambuc V_Flush := Finish; 413*44bedb31SLionel Sambuc 414*44bedb31SLionel Sambuc elsif Rest_First > Rest_Last then 415*44bedb31SLionel Sambuc Read (Buffer, Rest_Last); 416*44bedb31SLionel Sambuc Rest_First := Buffer'First; 417*44bedb31SLionel Sambuc 418*44bedb31SLionel Sambuc if Rest_Last < Buffer'First then 419*44bedb31SLionel Sambuc V_Flush := Finish; 420*44bedb31SLionel Sambuc end if; 421*44bedb31SLionel Sambuc end if; 422*44bedb31SLionel Sambuc 423*44bedb31SLionel Sambuc Translate 424*44bedb31SLionel Sambuc (Filter => Filter, 425*44bedb31SLionel Sambuc In_Data => Buffer (Rest_First .. Rest_Last), 426*44bedb31SLionel Sambuc In_Last => In_Last, 427*44bedb31SLionel Sambuc Out_Data => Item (Item_First .. Item'Last), 428*44bedb31SLionel Sambuc Out_Last => Last, 429*44bedb31SLionel Sambuc Flush => V_Flush); 430*44bedb31SLionel Sambuc 431*44bedb31SLionel Sambuc Rest_First := In_Last + 1; 432*44bedb31SLionel Sambuc 433*44bedb31SLionel Sambuc exit when Stream_End (Filter) 434*44bedb31SLionel Sambuc or else Last = Item'Last 435*44bedb31SLionel Sambuc or else (Last >= Item'First and then Allow_Read_Some); 436*44bedb31SLionel Sambuc 437*44bedb31SLionel Sambuc Item_First := Last + 1; 438*44bedb31SLionel Sambuc end loop; 439*44bedb31SLionel Sambuc end Read; 440*44bedb31SLionel Sambuc 441*44bedb31SLionel Sambuc ---------------- 442*44bedb31SLionel Sambuc -- Stream_End -- 443*44bedb31SLionel Sambuc ---------------- 444*44bedb31SLionel Sambuc 445*44bedb31SLionel Sambuc function Stream_End (Filter : in Filter_Type) return Boolean is 446*44bedb31SLionel Sambuc begin 447*44bedb31SLionel Sambuc if Filter.Header = GZip and Filter.Compression then 448*44bedb31SLionel Sambuc return Filter.Stream_End 449*44bedb31SLionel Sambuc and then Filter.Offset = Footer_Array'Last + 1; 450*44bedb31SLionel Sambuc else 451*44bedb31SLionel Sambuc return Filter.Stream_End; 452*44bedb31SLionel Sambuc end if; 453*44bedb31SLionel Sambuc end Stream_End; 454*44bedb31SLionel Sambuc 455*44bedb31SLionel Sambuc -------------- 456*44bedb31SLionel Sambuc -- Total_In -- 457*44bedb31SLionel Sambuc -------------- 458*44bedb31SLionel Sambuc 459*44bedb31SLionel Sambuc function Total_In (Filter : in Filter_Type) return Count is 460*44bedb31SLionel Sambuc begin 461*44bedb31SLionel Sambuc return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); 462*44bedb31SLionel Sambuc end Total_In; 463*44bedb31SLionel Sambuc 464*44bedb31SLionel Sambuc --------------- 465*44bedb31SLionel Sambuc -- Total_Out -- 466*44bedb31SLionel Sambuc --------------- 467*44bedb31SLionel Sambuc 468*44bedb31SLionel Sambuc function Total_Out (Filter : in Filter_Type) return Count is 469*44bedb31SLionel Sambuc begin 470*44bedb31SLionel Sambuc return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); 471*44bedb31SLionel Sambuc end Total_Out; 472*44bedb31SLionel Sambuc 473*44bedb31SLionel Sambuc --------------- 474*44bedb31SLionel Sambuc -- Translate -- 475*44bedb31SLionel Sambuc --------------- 476*44bedb31SLionel Sambuc 477*44bedb31SLionel Sambuc procedure Translate 478*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 479*44bedb31SLionel Sambuc In_Data : in Ada.Streams.Stream_Element_Array; 480*44bedb31SLionel Sambuc In_Last : out Ada.Streams.Stream_Element_Offset; 481*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 482*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 483*44bedb31SLionel Sambuc Flush : in Flush_Mode) is 484*44bedb31SLionel Sambuc begin 485*44bedb31SLionel Sambuc if Filter.Header = GZip and then Filter.Compression then 486*44bedb31SLionel Sambuc Translate_GZip 487*44bedb31SLionel Sambuc (Filter => Filter, 488*44bedb31SLionel Sambuc In_Data => In_Data, 489*44bedb31SLionel Sambuc In_Last => In_Last, 490*44bedb31SLionel Sambuc Out_Data => Out_Data, 491*44bedb31SLionel Sambuc Out_Last => Out_Last, 492*44bedb31SLionel Sambuc Flush => Flush); 493*44bedb31SLionel Sambuc else 494*44bedb31SLionel Sambuc Translate_Auto 495*44bedb31SLionel Sambuc (Filter => Filter, 496*44bedb31SLionel Sambuc In_Data => In_Data, 497*44bedb31SLionel Sambuc In_Last => In_Last, 498*44bedb31SLionel Sambuc Out_Data => Out_Data, 499*44bedb31SLionel Sambuc Out_Last => Out_Last, 500*44bedb31SLionel Sambuc Flush => Flush); 501*44bedb31SLionel Sambuc end if; 502*44bedb31SLionel Sambuc end Translate; 503*44bedb31SLionel Sambuc 504*44bedb31SLionel Sambuc -------------------- 505*44bedb31SLionel Sambuc -- Translate_Auto -- 506*44bedb31SLionel Sambuc -------------------- 507*44bedb31SLionel Sambuc 508*44bedb31SLionel Sambuc procedure Translate_Auto 509*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 510*44bedb31SLionel Sambuc In_Data : in Ada.Streams.Stream_Element_Array; 511*44bedb31SLionel Sambuc In_Last : out Ada.Streams.Stream_Element_Offset; 512*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 513*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 514*44bedb31SLionel Sambuc Flush : in Flush_Mode) 515*44bedb31SLionel Sambuc is 516*44bedb31SLionel Sambuc use type Thin.Int; 517*44bedb31SLionel Sambuc Code : Thin.Int; 518*44bedb31SLionel Sambuc 519*44bedb31SLionel Sambuc begin 520*44bedb31SLionel Sambuc if not Is_Open (Filter) then 521*44bedb31SLionel Sambuc raise Status_Error; 522*44bedb31SLionel Sambuc end if; 523*44bedb31SLionel Sambuc 524*44bedb31SLionel Sambuc if Out_Data'Length = 0 and then In_Data'Length = 0 then 525*44bedb31SLionel Sambuc raise Constraint_Error; 526*44bedb31SLionel Sambuc end if; 527*44bedb31SLionel Sambuc 528*44bedb31SLionel Sambuc Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); 529*44bedb31SLionel Sambuc Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); 530*44bedb31SLionel Sambuc 531*44bedb31SLionel Sambuc Code := Flate (Filter.Compression).Step 532*44bedb31SLionel Sambuc (To_Thin_Access (Filter.Strm), 533*44bedb31SLionel Sambuc Thin.Int (Flush)); 534*44bedb31SLionel Sambuc 535*44bedb31SLionel Sambuc if Code = Thin.Z_STREAM_END then 536*44bedb31SLionel Sambuc Filter.Stream_End := True; 537*44bedb31SLionel Sambuc else 538*44bedb31SLionel Sambuc Check_Error (Filter.Strm.all, Code); 539*44bedb31SLionel Sambuc end if; 540*44bedb31SLionel Sambuc 541*44bedb31SLionel Sambuc In_Last := In_Data'Last 542*44bedb31SLionel Sambuc - Stream_Element_Offset (Avail_In (Filter.Strm.all)); 543*44bedb31SLionel Sambuc Out_Last := Out_Data'Last 544*44bedb31SLionel Sambuc - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); 545*44bedb31SLionel Sambuc end Translate_Auto; 546*44bedb31SLionel Sambuc 547*44bedb31SLionel Sambuc -------------------- 548*44bedb31SLionel Sambuc -- Translate_GZip -- 549*44bedb31SLionel Sambuc -------------------- 550*44bedb31SLionel Sambuc 551*44bedb31SLionel Sambuc procedure Translate_GZip 552*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 553*44bedb31SLionel Sambuc In_Data : in Ada.Streams.Stream_Element_Array; 554*44bedb31SLionel Sambuc In_Last : out Ada.Streams.Stream_Element_Offset; 555*44bedb31SLionel Sambuc Out_Data : out Ada.Streams.Stream_Element_Array; 556*44bedb31SLionel Sambuc Out_Last : out Ada.Streams.Stream_Element_Offset; 557*44bedb31SLionel Sambuc Flush : in Flush_Mode) 558*44bedb31SLionel Sambuc is 559*44bedb31SLionel Sambuc Out_First : Stream_Element_Offset; 560*44bedb31SLionel Sambuc 561*44bedb31SLionel Sambuc procedure Add_Data (Data : in Stream_Element_Array); 562*44bedb31SLionel Sambuc -- Add data to stream from the Filter.Offset till necessary, 563*44bedb31SLionel Sambuc -- used for add gzip headr/footer. 564*44bedb31SLionel Sambuc 565*44bedb31SLionel Sambuc procedure Put_32 566*44bedb31SLionel Sambuc (Item : in out Stream_Element_Array; 567*44bedb31SLionel Sambuc Data : in Unsigned_32); 568*44bedb31SLionel Sambuc pragma Inline (Put_32); 569*44bedb31SLionel Sambuc 570*44bedb31SLionel Sambuc -------------- 571*44bedb31SLionel Sambuc -- Add_Data -- 572*44bedb31SLionel Sambuc -------------- 573*44bedb31SLionel Sambuc 574*44bedb31SLionel Sambuc procedure Add_Data (Data : in Stream_Element_Array) is 575*44bedb31SLionel Sambuc Data_First : Stream_Element_Offset renames Filter.Offset; 576*44bedb31SLionel Sambuc Data_Last : Stream_Element_Offset; 577*44bedb31SLionel Sambuc Data_Len : Stream_Element_Offset; -- -1 578*44bedb31SLionel Sambuc Out_Len : Stream_Element_Offset; -- -1 579*44bedb31SLionel Sambuc begin 580*44bedb31SLionel Sambuc Out_First := Out_Last + 1; 581*44bedb31SLionel Sambuc 582*44bedb31SLionel Sambuc if Data_First > Data'Last then 583*44bedb31SLionel Sambuc return; 584*44bedb31SLionel Sambuc end if; 585*44bedb31SLionel Sambuc 586*44bedb31SLionel Sambuc Data_Len := Data'Last - Data_First; 587*44bedb31SLionel Sambuc Out_Len := Out_Data'Last - Out_First; 588*44bedb31SLionel Sambuc 589*44bedb31SLionel Sambuc if Data_Len <= Out_Len then 590*44bedb31SLionel Sambuc Out_Last := Out_First + Data_Len; 591*44bedb31SLionel Sambuc Data_Last := Data'Last; 592*44bedb31SLionel Sambuc else 593*44bedb31SLionel Sambuc Out_Last := Out_Data'Last; 594*44bedb31SLionel Sambuc Data_Last := Data_First + Out_Len; 595*44bedb31SLionel Sambuc end if; 596*44bedb31SLionel Sambuc 597*44bedb31SLionel Sambuc Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); 598*44bedb31SLionel Sambuc 599*44bedb31SLionel Sambuc Data_First := Data_Last + 1; 600*44bedb31SLionel Sambuc Out_First := Out_Last + 1; 601*44bedb31SLionel Sambuc end Add_Data; 602*44bedb31SLionel Sambuc 603*44bedb31SLionel Sambuc ------------ 604*44bedb31SLionel Sambuc -- Put_32 -- 605*44bedb31SLionel Sambuc ------------ 606*44bedb31SLionel Sambuc 607*44bedb31SLionel Sambuc procedure Put_32 608*44bedb31SLionel Sambuc (Item : in out Stream_Element_Array; 609*44bedb31SLionel Sambuc Data : in Unsigned_32) 610*44bedb31SLionel Sambuc is 611*44bedb31SLionel Sambuc D : Unsigned_32 := Data; 612*44bedb31SLionel Sambuc begin 613*44bedb31SLionel Sambuc for J in Item'First .. Item'First + 3 loop 614*44bedb31SLionel Sambuc Item (J) := Stream_Element (D and 16#FF#); 615*44bedb31SLionel Sambuc D := Shift_Right (D, 8); 616*44bedb31SLionel Sambuc end loop; 617*44bedb31SLionel Sambuc end Put_32; 618*44bedb31SLionel Sambuc 619*44bedb31SLionel Sambuc begin 620*44bedb31SLionel Sambuc Out_Last := Out_Data'First - 1; 621*44bedb31SLionel Sambuc 622*44bedb31SLionel Sambuc if not Filter.Stream_End then 623*44bedb31SLionel Sambuc Add_Data (Simple_GZip_Header); 624*44bedb31SLionel Sambuc 625*44bedb31SLionel Sambuc Translate_Auto 626*44bedb31SLionel Sambuc (Filter => Filter, 627*44bedb31SLionel Sambuc In_Data => In_Data, 628*44bedb31SLionel Sambuc In_Last => In_Last, 629*44bedb31SLionel Sambuc Out_Data => Out_Data (Out_First .. Out_Data'Last), 630*44bedb31SLionel Sambuc Out_Last => Out_Last, 631*44bedb31SLionel Sambuc Flush => Flush); 632*44bedb31SLionel Sambuc 633*44bedb31SLionel Sambuc CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); 634*44bedb31SLionel Sambuc end if; 635*44bedb31SLionel Sambuc 636*44bedb31SLionel Sambuc if Filter.Stream_End and then Out_Last <= Out_Data'Last then 637*44bedb31SLionel Sambuc -- This detection method would work only when 638*44bedb31SLionel Sambuc -- Simple_GZip_Header'Last > Footer_Array'Last 639*44bedb31SLionel Sambuc 640*44bedb31SLionel Sambuc if Filter.Offset = Simple_GZip_Header'Last + 1 then 641*44bedb31SLionel Sambuc Filter.Offset := Footer_Array'First; 642*44bedb31SLionel Sambuc end if; 643*44bedb31SLionel Sambuc 644*44bedb31SLionel Sambuc declare 645*44bedb31SLionel Sambuc Footer : Footer_Array; 646*44bedb31SLionel Sambuc begin 647*44bedb31SLionel Sambuc Put_32 (Footer, Filter.CRC); 648*44bedb31SLionel Sambuc Put_32 (Footer (Footer'First + 4 .. Footer'Last), 649*44bedb31SLionel Sambuc Unsigned_32 (Total_In (Filter))); 650*44bedb31SLionel Sambuc Add_Data (Footer); 651*44bedb31SLionel Sambuc end; 652*44bedb31SLionel Sambuc end if; 653*44bedb31SLionel Sambuc end Translate_GZip; 654*44bedb31SLionel Sambuc 655*44bedb31SLionel Sambuc ------------- 656*44bedb31SLionel Sambuc -- Version -- 657*44bedb31SLionel Sambuc ------------- 658*44bedb31SLionel Sambuc 659*44bedb31SLionel Sambuc function Version return String is 660*44bedb31SLionel Sambuc begin 661*44bedb31SLionel Sambuc return Interfaces.C.Strings.Value (Thin.zlibVersion); 662*44bedb31SLionel Sambuc end Version; 663*44bedb31SLionel Sambuc 664*44bedb31SLionel Sambuc ----------- 665*44bedb31SLionel Sambuc -- Write -- 666*44bedb31SLionel Sambuc ----------- 667*44bedb31SLionel Sambuc 668*44bedb31SLionel Sambuc procedure Write 669*44bedb31SLionel Sambuc (Filter : in out Filter_Type; 670*44bedb31SLionel Sambuc Item : in Ada.Streams.Stream_Element_Array; 671*44bedb31SLionel Sambuc Flush : in Flush_Mode := No_Flush) 672*44bedb31SLionel Sambuc is 673*44bedb31SLionel Sambuc Buffer : Stream_Element_Array (1 .. Buffer_Size); 674*44bedb31SLionel Sambuc In_Last : Stream_Element_Offset; 675*44bedb31SLionel Sambuc Out_Last : Stream_Element_Offset; 676*44bedb31SLionel Sambuc In_First : Stream_Element_Offset := Item'First; 677*44bedb31SLionel Sambuc begin 678*44bedb31SLionel Sambuc if Item'Length = 0 and Flush = No_Flush then 679*44bedb31SLionel Sambuc return; 680*44bedb31SLionel Sambuc end if; 681*44bedb31SLionel Sambuc 682*44bedb31SLionel Sambuc loop 683*44bedb31SLionel Sambuc Translate 684*44bedb31SLionel Sambuc (Filter => Filter, 685*44bedb31SLionel Sambuc In_Data => Item (In_First .. Item'Last), 686*44bedb31SLionel Sambuc In_Last => In_Last, 687*44bedb31SLionel Sambuc Out_Data => Buffer, 688*44bedb31SLionel Sambuc Out_Last => Out_Last, 689*44bedb31SLionel Sambuc Flush => Flush); 690*44bedb31SLionel Sambuc 691*44bedb31SLionel Sambuc if Out_Last >= Buffer'First then 692*44bedb31SLionel Sambuc Write (Buffer (1 .. Out_Last)); 693*44bedb31SLionel Sambuc end if; 694*44bedb31SLionel Sambuc 695*44bedb31SLionel Sambuc exit when In_Last = Item'Last or Stream_End (Filter); 696*44bedb31SLionel Sambuc 697*44bedb31SLionel Sambuc In_First := In_Last + 1; 698*44bedb31SLionel Sambuc end loop; 699*44bedb31SLionel Sambuc end Write; 700*44bedb31SLionel Sambuc 701*44bedb31SLionel Sambucend ZLib; 702