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