annotate src/zlib-1.2.8/contrib/ada/zlib.adb @ 83:ae30d91d2ffe

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