1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2003-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(zlib). 22 23-export([open/0,close/1,set_controlling_process/2, 24 deflateInit/1,deflateInit/2,deflateInit/6, 25 deflateSetDictionary/2,deflateReset/1,deflateParams/3, 26 deflate/2,deflate/3,deflateEnd/1, 27 inflateInit/1,inflateInit/2,inflateInit/3, 28 inflateSetDictionary/2,inflateGetDictionary/1, inflateReset/1, 29 inflate/2,inflate/3,inflateEnd/1, 30 inflateChunk/2,inflateChunk/1, 31 safeInflate/2, 32 setBufSize/2,getBufSize/1, 33 crc32/1,crc32/2,crc32/3,adler32/2,adler32/3, 34 crc32_combine/4,adler32_combine/4, 35 compress/1,uncompress/1,zip/1,unzip/1, 36 gzip/1,gunzip/1]). 37 38-export([on_load/0]). 39 40-deprecated([{inflateChunk, 1, "use safeInflate/2 instead"}, 41 {inflateChunk, 2, "use safeInflate/2 instead"}, 42 {getBufSize, 1, "this function will be removed in a future release"}, 43 {setBufSize, 2, "this function will be removed in a future release"}, 44 {crc32, 1, "use erlang:crc32/1 on the uncompressed data instead"}, 45 {crc32, 2, "use erlang:crc32/1 instead"}, 46 {crc32, 3, "use erlang:crc32/2 instead"}, 47 {adler32, 2, "use erlang:adler32/1 instead"}, 48 {adler32, 3, "use erlang:adler32/2 instead"}, 49 {crc32_combine, 4, "use erlang:crc32_combine/3 instead"}, 50 {adler32_combine, 4, "use erlang:adler_combine/3 instead"}]). 51 52-export_type([zstream/0, zflush/0, zlevel/0, zwindowbits/0, zmemlevel/0, 53 zstrategy/0]). 54 55%% flush argument encoding 56-define(Z_NO_FLUSH, 0). 57-define(Z_SYNC_FLUSH, 2). 58-define(Z_FULL_FLUSH, 3). 59-define(Z_FINISH, 4). 60 61%% compression level 62-define(Z_NO_COMPRESSION, 0). 63-define(Z_BEST_SPEED, 1). 64-define(Z_BEST_COMPRESSION, 9). 65-define(Z_DEFAULT_COMPRESSION, (-1)). 66 67%% compression strategy 68-define(Z_FILTERED, 1). 69-define(Z_HUFFMAN_ONLY, 2). 70-define(Z_RLE, 3). 71-define(Z_DEFAULT_STRATEGY, 0). 72 73%% deflate compression method 74-define(Z_DEFLATED, 8). 75 76-define(MAX_WBITS, 15). 77 78-define(DEFAULT_MEMLEVEL, 8). 79-define(DEFAULT_WBITS, 15). 80 81-define(EOS_BEHAVIOR_ERROR, 0). 82-define(EOS_BEHAVIOR_RESET, 1). 83-define(EOS_BEHAVIOR_CUT, 2). 84 85%% Chunk sizes are hardcoded on account of them screwing with the 86%% predictability of the system. zlib is incapable of trapping so we need to 87%% ensure that it never operates on any significant amount of data. 88-define(DEFLATE_IN_CHUNKSIZE, 8 bsl 10). 89-define(DEFLATE_OUT_CHUNKSIZE, 8 bsl 10). 90-define(INFLATE_IN_CHUNKSIZE, 8 bsl 10). 91-define(INFLATE_OUT_CHUNKSIZE, 16 bsl 10). 92 93%%------------------------------------------------------------------------ 94 95%% Public data types. 96-type zstream() :: reference(). 97-type zflush() :: 'none' | 'sync' | 'full' | 'finish'. 98 99-type zlevel() :: 100 'none' | 'default' | 'best_compression' | 'best_speed' | 0..9. 101-type zstrategy() :: 'default' | 'filtered' | 'huffman_only' | 'rle'. 102 103-type zmemlevel() :: 1..9. 104-type zwindowbits() :: -15..-8 | 8..47. 105 106%% Private data types. 107 108-type zmethod() :: 'deflated'. 109 110-record(zlib_opts, { 111 stream :: zstream() | 'undefined', 112 method :: function(), 113 input_chunk_size :: pos_integer(), 114 output_chunk_size :: pos_integer(), 115 flush :: non_neg_integer() 116 }). 117 118%%------------------------------------------------------------------------ 119 120on_load() -> 121 case erlang:load_nif(atom_to_list(?MODULE), 0) of 122 ok -> ok 123 end. 124 125-spec open() -> zstream(). 126open() -> 127 open_nif(). 128open_nif() -> 129 erlang:nif_error(undef). 130 131-spec close(Z) -> 'ok' when 132 Z :: zstream(). 133close(Z) -> 134 close_nif(Z). 135close_nif(_Z) -> 136 erlang:nif_error(undef). 137 138-spec set_controlling_process(Z, Pid) -> 'ok' when 139 Z :: zstream(), 140 Pid :: pid(). 141set_controlling_process(Z, Pid) -> 142 set_controller_nif(Z, Pid). 143set_controller_nif(_Z, _Pid) -> 144 erlang:nif_error(undef). 145 146-spec deflateInit(Z) -> 'ok' when 147 Z :: zstream(). 148deflateInit(Z) -> 149 deflateInit(Z, default). 150 151-spec deflateInit(Z, Level) -> 'ok' when 152 Z :: zstream(), 153 Level :: zlevel(). 154deflateInit(Z, Level) -> 155 deflateInit(Z, Level, deflated, ?DEFAULT_WBITS, ?DEFAULT_MEMLEVEL, default). 156 157-spec deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> 'ok' when 158 Z :: zstream(), 159 Level :: zlevel(), 160 Method :: zmethod(), 161 WindowBits :: zwindowbits(), 162 MemLevel :: zmemlevel(), 163 Strategy :: zstrategy(). 164deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> 165 deflateInit_nif(Z, 166 arg_level(Level), 167 arg_method(Method), 168 arg_bitsz(WindowBits), 169 arg_mem(MemLevel), 170 arg_strategy(Strategy)). 171deflateInit_nif(_Z, _Level, _Method, _WindowBits, _MemLevel, _Strategy) -> 172 erlang:nif_error(undef). 173 174-spec deflateSetDictionary(Z, Dictionary) -> Adler32 when 175 Z :: zstream(), 176 Dictionary :: iodata(), 177 Adler32 :: non_neg_integer(). 178deflateSetDictionary(Z, Dictionary) -> 179 deflateSetDictionary_nif(Z, Dictionary). 180deflateSetDictionary_nif(_Z, _Dictionary) -> 181 erlang:nif_error(undef). 182 183-spec deflateReset(Z) -> 'ok' when 184 Z :: zstream(). 185deflateReset(Z) -> 186 deflateReset_nif(Z). 187deflateReset_nif(_Z) -> 188 erlang:nif_error(undef). 189 190-spec deflateParams(Z, Level, Strategy) -> ok when 191 Z :: zstream(), 192 Level :: zlevel(), 193 Strategy :: zstrategy(). 194deflateParams(Z, Level0, Strategy0) -> 195 Level = arg_level(Level0), 196 Strategy = arg_strategy(Strategy0), 197 Progress = deflate(Z, <<>>, sync), 198 case deflateParams_nif(Z, Level, Strategy) of 199 ok -> 200 save_progress(Z, deflate, Progress), 201 ok; 202 Other -> 203 Other 204 end. 205deflateParams_nif(_Z, _Level, _Strategy) -> 206 erlang:nif_error(undef). 207 208-spec deflate(Z, Data) -> Compressed when 209 Z :: zstream(), 210 Data :: iodata(), 211 Compressed :: iolist(). 212deflate(Z, Data) -> 213 deflate(Z, Data, none). 214 215-spec deflate(Z, Data, Flush) -> Compressed when 216 Z :: zstream(), 217 Data :: iodata(), 218 Flush :: zflush(), 219 Compressed :: iolist(). 220deflate(Z, Data, Flush) -> 221 Progress = restore_progress(Z, deflate), 222 enqueue_input(Z, Data), 223 append_iolist(Progress, dequeue_all_chunks(Z, deflate_opts(Flush))). 224 225deflate_opts(Flush) -> 226 #zlib_opts{ 227 method = fun deflate_nif/4, 228 input_chunk_size = ?DEFLATE_IN_CHUNKSIZE, 229 output_chunk_size = ?DEFLATE_OUT_CHUNKSIZE, 230 flush = arg_flush(Flush) 231 }. 232 233deflate_nif(_Z, _InputChSize, _OutputChSize, _Flush) -> 234 erlang:nif_error(undef). 235 236-spec deflateEnd(Z) -> 'ok' when 237 Z :: zstream(). 238deflateEnd(Z) -> 239 deflateEnd_nif(Z). 240deflateEnd_nif(_Z) -> 241 erlang:nif_error(undef). 242 243-spec inflateInit(Z) -> 'ok' when 244 Z :: zstream(). 245inflateInit(Z) -> 246 inflateInit(Z, ?DEFAULT_WBITS). 247 248-spec inflateInit(Z, WindowBits) -> 'ok' when 249 Z :: zstream(), 250 WindowBits :: zwindowbits(). 251inflateInit(Z, WindowBits) -> 252 inflateInit(Z, WindowBits, cut). 253 254-spec inflateInit(Z, WindowBits, EoSBehavior) -> 'ok' when 255 Z :: zstream(), 256 WindowBits :: zwindowbits(), 257 EoSBehavior :: error | reset | cut. 258inflateInit(Z, WindowBits, EoSBehavior) -> 259 inflateInit_nif(Z, arg_bitsz(WindowBits), arg_eos_behavior(EoSBehavior)). 260inflateInit_nif(_Z, _WindowBits, _EoSBehavior) -> 261 erlang:nif_error(undef). 262 263-spec inflateSetDictionary(Z, Dictionary) -> 'ok' when 264 Z :: zstream(), 265 Dictionary :: iodata(). 266inflateSetDictionary(Z, Dictionary) -> 267 inflateSetDictionary_nif(Z, Dictionary). 268inflateSetDictionary_nif(_Z, _Dictionary) -> 269 erlang:nif_error(undef). 270 271-spec inflateGetDictionary(Z) -> Dictionary when 272 Z :: zstream(), 273 Dictionary :: binary(). 274inflateGetDictionary(Z) -> 275 case inflateGetDictionary_nif(Z) of 276 Dictionary when is_binary(Dictionary) -> 277 Dictionary; 278 not_supported -> 279 erlang:error(enotsup) 280 end. 281inflateGetDictionary_nif(_Z) -> 282 erlang:nif_error(undef). 283 284-spec inflateReset(Z) -> 'ok' when 285 Z :: zstream(). 286inflateReset(Z) -> 287 inflateReset_nif(Z). 288inflateReset_nif(_Z) -> 289 erlang:nif_error(undef). 290 291-spec inflate(Z, Data) -> Decompressed when 292 Z :: zstream(), 293 Data :: iodata(), 294 Decompressed :: iolist(). 295inflate(Z, Data) -> 296 inflate(Z, Data, []). 297 298-spec inflate(Z, Data, Options) -> Decompressed when 299 Z :: zstream(), 300 Data :: iodata(), 301 Options :: list({exception_on_need_dict, boolean()}), 302 Decompressed :: iolist() | 303 {need_dictionary, 304 Adler32 :: non_neg_integer(), 305 Output :: iolist()}. 306inflate(Z, Data, Options) -> 307 enqueue_input(Z, Data), 308 Result = dequeue_all_chunks(Z, inflate_opts()), 309 case proplist_get_value(Options, exception_on_need_dict, true) of 310 true -> exception_on_need_dict(Z, Result); 311 false -> Result 312 end. 313 314inflate_nif(_Z, _InputChSize, _OutputChSize, _Flush) -> 315 erlang:nif_error(undef). 316 317inflate_opts() -> 318 #zlib_opts{ 319 method = fun inflate_nif/4, 320 input_chunk_size = ?INFLATE_IN_CHUNKSIZE, 321 output_chunk_size = ?INFLATE_OUT_CHUNKSIZE, 322 flush = arg_flush(none) 323 }. 324 325-spec inflateChunk(Z, Data) -> Decompressed | {more, Decompressed} when 326 Z :: zstream(), 327 Data :: iodata(), 328 Decompressed :: iolist(). 329inflateChunk(Z, Data) -> 330 enqueue_input(Z, Data), 331 inflateChunk(Z). 332 333-spec inflateChunk(Z) -> Decompressed | {more, Decompressed} when 334 Z :: zstream(), 335 Decompressed :: iolist(). 336inflateChunk(Z) -> 337 Opts0 = inflate_opts(), 338 Opts = Opts0#zlib_opts { output_chunk_size = getBufSize(Z) }, 339 340 Result0 = dequeue_next_chunk(Z, Opts), 341 Result1 = exception_on_need_dict(Z, Result0), 342 yield_inflateChunk(Z, Result1). 343 344yield_inflateChunk(_Z, {continue, Output}) -> 345 {more, lists:flatten(Output)}; 346yield_inflateChunk(_Z, {finished, Output}) -> 347 lists:flatten(Output). 348 349exception_on_need_dict(Z, {need_dictionary, Adler, Output}) -> 350 Progress = restore_progress(Z, inflate), 351 save_progress(Z, inflate, append_iolist(Progress, Output)), 352 erlang:error({need_dictionary, Adler}); 353exception_on_need_dict(Z, {Mark, Output}) -> 354 Progress = restore_progress(Z, inflate), 355 {Mark, append_iolist(Progress, Output)}; 356exception_on_need_dict(Z, Output) when is_list(Output); is_binary(Output) -> 357 Progress = restore_progress(Z, inflate), 358 append_iolist(Progress, Output). 359 360-spec safeInflate(Z, Data) -> Result when 361 Z :: zstream(), 362 Data :: iodata(), 363 Result :: {continue, Output :: iolist()} | 364 {finished, Output :: iolist()} | 365 {need_dictionary, 366 Adler32 :: non_neg_integer(), 367 Output :: iolist()}. 368safeInflate(Z, Data) -> 369 enqueue_input(Z, Data), 370 dequeue_next_chunk(Z, inflate_opts()). 371 372-spec inflateEnd(Z) -> 'ok' when 373 Z :: zstream(). 374inflateEnd(Z) -> 375 inflateEnd_nif(Z). 376inflateEnd_nif(_Z) -> 377 erlang:nif_error(undef). 378 379-spec setBufSize(Z, Size) -> 'ok' when 380 Z :: zstream(), 381 Size :: non_neg_integer(). 382setBufSize(Z, Size) when is_integer(Size), Size > 16, Size < (1 bsl 24) -> 383 setBufSize_nif(Z, Size); 384setBufSize(_Z, _Size) -> 385 erlang:error(badarg). 386setBufSize_nif(_Z, _Size) -> 387 erlang:nif_error(undef). 388 389-spec getBufSize(Z) -> non_neg_integer() when 390 Z :: zstream(). 391getBufSize(Z) -> 392 getBufSize_nif(Z). 393getBufSize_nif(_Z) -> 394 erlang:nif_error(undef). 395 396-spec crc32(Z) -> CRC when 397 Z :: zstream(), 398 CRC :: non_neg_integer(). 399crc32(Z) -> 400 crc32_nif(Z). 401crc32_nif(_Z) -> 402 erlang:nif_error(undef). 403 404-spec crc32(Z, Data) -> CRC when 405 Z :: zstream(), 406 Data :: iodata(), 407 CRC :: non_neg_integer(). 408crc32(Z, Data) when is_reference(Z) -> 409 erlang:crc32(Data); 410crc32(_Z, _Data) -> 411 erlang:error(badarg). 412 413-spec crc32(Z, PrevCRC, Data) -> CRC when 414 Z :: zstream(), 415 PrevCRC :: non_neg_integer(), 416 Data :: iodata(), 417 CRC :: non_neg_integer(). 418crc32(Z, CRC, Data) when is_reference(Z) -> 419 erlang:crc32(CRC, Data); 420crc32(_Z, _CRC, _Data) -> 421 erlang:error(badarg). 422 423-spec crc32_combine(Z, CRC1, CRC2, Size2) -> CRC when 424 Z :: zstream(), 425 CRC :: non_neg_integer(), 426 CRC1 :: non_neg_integer(), 427 CRC2 :: non_neg_integer(), 428 Size2 :: non_neg_integer(). 429crc32_combine(Z, CRC1, CRC2, Size2) when is_reference(Z) -> 430 erlang:crc32_combine(CRC1, CRC2, Size2); 431crc32_combine(_Z, _CRC1, _CRC2, _Size2) -> 432 erlang:error(badarg). 433 434-spec adler32(Z, Data) -> CheckSum when 435 Z :: zstream(), 436 Data :: iodata(), 437 CheckSum :: non_neg_integer(). 438adler32(Z, Data) when is_reference(Z) -> 439 erlang:adler32(Data); 440adler32(_Z, _Data) -> 441 erlang:error(badarg). 442 443-spec adler32(Z, PrevAdler, Data) -> CheckSum when 444 Z :: zstream(), 445 PrevAdler :: non_neg_integer(), 446 Data :: iodata(), 447 CheckSum :: non_neg_integer(). 448adler32(Z, Adler, Data) when is_reference(Z) -> 449 erlang:adler32(Adler, Data); 450adler32(_Z, _Adler, _Data) -> 451 erlang:error(badarg). 452 453-spec adler32_combine(Z, Adler1, Adler2, Size2) -> Adler when 454 Z :: zstream(), 455 Adler :: non_neg_integer(), 456 Adler1 :: non_neg_integer(), 457 Adler2 :: non_neg_integer(), 458 Size2 :: non_neg_integer(). 459adler32_combine(Z, Adler1, Adler2, Size2) when is_reference(Z) -> 460 erlang:adler32_combine(Adler1, Adler2, Size2); 461adler32_combine(_Z, _Adler1, _Adler2, _Size2) -> 462 erlang:error(badarg). 463 464%% compress/uncompress zlib with header 465-spec compress(Data) -> Compressed when 466 Data :: iodata(), 467 Compressed :: binary(). 468compress(Data) -> 469 Z = open(), 470 Bs = try 471 deflateInit(Z, default), 472 B = deflate(Z, Data, finish), 473 deflateEnd(Z), 474 B 475 after 476 close(Z) 477 end, 478 iolist_to_binary(Bs). 479 480-spec uncompress(Data) -> Decompressed when 481 Data :: iodata(), 482 Decompressed :: binary(). 483uncompress(Data) -> 484 try iolist_size(Data) of 485 Size -> 486 if 487 Size >= 8 -> 488 Z = open(), 489 Bs = try 490 inflateInit(Z), 491 B = inflate(Z, Data), 492 inflateEnd(Z), 493 B 494 after 495 close(Z) 496 end, 497 iolist_to_binary(Bs); 498 true -> 499 erlang:error(data_error) 500 end 501 catch 502 _:_ -> 503 erlang:error(badarg) 504 end. 505 506%% unzip/zip zlib without header (zip members) 507-spec zip(Data) -> Compressed when 508 Data :: iodata(), 509 Compressed :: binary(). 510zip(Data) -> 511 Z = open(), 512 Bs = try 513 deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), 514 B = deflate(Z, Data, finish), 515 deflateEnd(Z), 516 B 517 after 518 close(Z) 519 end, 520 iolist_to_binary(Bs). 521 522-spec unzip(Data) -> Decompressed when 523 Data :: iodata(), 524 Decompressed :: binary(). 525unzip(Data) -> 526 Z = open(), 527 Bs = try 528 inflateInit(Z, -?MAX_WBITS), 529 B = inflate(Z, Data), 530 inflateEnd(Z), 531 B 532 after 533 close(Z) 534 end, 535 iolist_to_binary(Bs). 536 537-spec gzip(Data) -> Compressed when 538 Data :: iodata(), 539 Compressed :: binary(). 540gzip(Data) -> 541 Z = open(), 542 Bs = try 543 deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), 544 B = deflate(Z, Data, finish), 545 deflateEnd(Z), 546 B 547 after 548 close(Z) 549 end, 550 iolist_to_binary(Bs). 551 552-spec gunzip(Data) -> Decompressed when 553 Data :: iodata(), 554 Decompressed :: binary(). 555gunzip(Data) -> 556 Z = open(), 557 Bs = try 558 inflateInit(Z, 16+?MAX_WBITS, reset), 559 B = inflate(Z, Data), 560 inflateEnd(Z), 561 B 562 after 563 close(Z) 564 end, 565 iolist_to_binary(Bs). 566 567-spec dequeue_all_chunks(Z, Opts) -> Result when 568 Z :: zstream(), 569 Opts :: #zlib_opts{}, 570 Result :: {need_dictionary, integer(), iolist()} | 571 iolist(). 572dequeue_all_chunks(Z, Opts) -> 573 dequeue_all_chunks_1(Z, Opts, []). 574dequeue_all_chunks_1(Z, Opts, Output) -> 575 case dequeue_next_chunk(Z, Opts) of 576 {need_dictionary, _, _} = NeedDict -> 577 NeedDict; 578 {continue, Chunk} -> 579 dequeue_all_chunks_1(Z, Opts, append_iolist(Output, Chunk)); 580 {finished, Chunk} -> 581 append_iolist(Output, Chunk) 582 end. 583 584-spec dequeue_next_chunk(Z, Opts) -> Result when 585 Z :: zstream(), 586 Opts :: #zlib_opts{}, 587 Result :: {need_dictionary, integer(), iolist()} | 588 {continue, iolist()} | 589 {finished, iolist()}. 590dequeue_next_chunk(Z, Opts) -> 591 Method = Opts#zlib_opts.method, 592 IChSz = Opts#zlib_opts.input_chunk_size, 593 OChSz = Opts#zlib_opts.output_chunk_size, 594 Flush = Opts#zlib_opts.flush, 595 Method(Z, IChSz, OChSz, Flush). 596 597-spec append_iolist(IO, D) -> iolist() when 598 IO :: iodata(), 599 D :: iodata(). 600append_iolist([], D) when is_list(D) -> D; 601append_iolist([], D) -> [D]; 602append_iolist(IO, []) -> IO; 603append_iolist(IO, [D]) -> [IO, D]; 604append_iolist(IO, D) -> [IO, D]. 605 606%% inflate/2 and friends are documented as throwing an error on Z_NEED_DICT 607%% rather than simply returning something to that effect, and deflateParams/3 608%% may flush behind the scenes. This requires us to stow away our current 609%% progress in the handle and resume from that point on our next call. 610%% 611%% Generally speaking this is either a refc binary or nothing at all, so it's 612%% pretty cheap. 613 614-spec save_progress(Z, Kind, Output) -> ok when 615 Z :: zstream(), 616 Kind :: inflate | deflate, 617 Output :: iolist(). 618save_progress(Z, Kind, Output) -> 619 ok = setStash_nif(Z, {Kind, Output}). 620 621-spec restore_progress(Z, Kind) -> iolist() when 622 Z :: zstream(), 623 Kind :: inflate | deflate. 624restore_progress(Z, Kind) -> 625 case getStash_nif(Z) of 626 {ok, {Kind, Output}} -> 627 ok = clearStash_nif(Z), 628 Output; 629 empty -> 630 [] 631 end. 632 633-spec clearStash_nif(Z) -> ok when 634 Z :: zstream(). 635clearStash_nif(_Z) -> 636 erlang:nif_error(undef). 637 638-spec setStash_nif(Z, Term) -> ok when 639 Z :: zstream(), 640 Term :: term(). 641setStash_nif(_Z, _Term) -> 642 erlang:nif_error(undef). 643 644-spec getStash_nif(Z) -> {ok, term()} | empty when 645 Z :: zstream(). 646getStash_nif(_Z) -> 647 erlang:nif_error(undef). 648 649%% The 'proplists' module isn't preloaded so we can't rely on its existence. 650proplist_get_value([], _Name, DefVal) -> DefVal; 651proplist_get_value([{Name, Value} | _Opts], Name, _DefVal) -> Value; 652proplist_get_value([_Head | Opts], Name, DefVal) -> 653 proplist_get_value(Opts, Name, DefVal). 654 655arg_flush(none) -> ?Z_NO_FLUSH; 656%% ?Z_PARTIAL_FLUSH is deprecated in zlib -- deliberately not included. 657arg_flush(sync) -> ?Z_SYNC_FLUSH; 658arg_flush(full) -> ?Z_FULL_FLUSH; 659arg_flush(finish) -> ?Z_FINISH; 660arg_flush(_) -> erlang:error(bad_flush_mode). 661 662arg_level(none) -> ?Z_NO_COMPRESSION; 663arg_level(best_speed) -> ?Z_BEST_SPEED; 664arg_level(best_compression) -> ?Z_BEST_COMPRESSION; 665arg_level(default) -> ?Z_DEFAULT_COMPRESSION; 666arg_level(Level) when is_integer(Level), Level >= 0, Level =< 9 -> Level; 667arg_level(_) -> erlang:error(bad_compression_level). 668 669arg_strategy(filtered) -> ?Z_FILTERED; 670arg_strategy(huffman_only) -> ?Z_HUFFMAN_ONLY; 671arg_strategy(rle) -> ?Z_RLE; 672arg_strategy(default) -> ?Z_DEFAULT_STRATEGY; 673arg_strategy(_) -> erlang:error(bad_compression_strategy). 674 675arg_method(deflated) -> ?Z_DEFLATED; 676arg_method(_) -> erlang:error(bad_compression_method). 677 678arg_eos_behavior(error) -> ?EOS_BEHAVIOR_ERROR; 679arg_eos_behavior(reset) -> ?EOS_BEHAVIOR_RESET; 680arg_eos_behavior(cut) -> ?EOS_BEHAVIOR_CUT; 681arg_eos_behavior(_) -> erlang:error(bad_eos_behavior). 682 683-spec arg_bitsz(zwindowbits()) -> zwindowbits(). 684arg_bitsz(Bits) when is_integer(Bits) andalso 685 ((8 =< Bits andalso Bits < 48) orelse 686 (-15 =< Bits andalso Bits =< -8)) -> 687 Bits; 688arg_bitsz(_) -> erlang:error(bad_windowbits). 689 690-spec arg_mem(zmemlevel()) -> zmemlevel(). 691arg_mem(Level) when is_integer(Level), 1 =< Level, Level =< 9 -> Level; 692arg_mem(_) -> erlang:error(bad_memlevel). 693 694-spec enqueue_input(Z, IOData) -> ok when 695 Z :: zstream(), 696 IOData :: iodata(). 697enqueue_input(Z, IOData) -> 698 enqueue_input_1(Z, erlang:iolist_to_iovec(IOData)). 699 700enqueue_input_1(_Z, []) -> 701 ok; 702enqueue_input_1(Z, IOVec) -> 703 case enqueue_nif(Z, IOVec) of 704 {continue, Remainder} -> enqueue_input_1(Z, Remainder); 705 ok -> ok 706 end. 707 708enqueue_nif(_Z, _IOVec) -> 709 erlang:nif_error(undef). 710