annotate src/zlib-1.2.7/contrib/ada/zlib.adb @ 23:619f715526df sv_v2.1

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