annotate src/zlib-1.2.8/contrib/ada/zlib.adb @ 169:223a55898ab9 tip default

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