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