annotate src/zlib-1.2.7/contrib/ada/zlib.adb @ 143:e95e00bdc3eb

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