Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
zlib.c
Go to the documentation of this file.
1/*
2 * zlib.c - An interface for zlib.
3 *
4 * Copyright (C) UENO Katsuhiro 2000-2003
5 *
6 * $Id$
7 */
8
9#include <ruby.h>
10#include <zlib.h>
11#include <time.h>
12#include <ruby/io.h>
13#include <ruby/thread.h>
14
15#ifdef HAVE_VALGRIND_MEMCHECK_H
16# include <valgrind/memcheck.h>
17# ifndef VALGRIND_MAKE_MEM_DEFINED
18# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
19# endif
20# ifndef VALGRIND_MAKE_MEM_UNDEFINED
21# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
22# endif
23#else
24# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
25# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
26#endif
27
28#define RUBY_ZLIB_VERSION "1.1.0"
29
30#ifndef RB_PASS_CALLED_KEYWORDS
31# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
32#endif
33
34#ifndef GZIP_SUPPORT
35#define GZIP_SUPPORT 1
36#endif
37
38/* from zutil.h */
39#ifndef DEF_MEM_LEVEL
40#if MAX_MEM_LEVEL >= 8
41#define DEF_MEM_LEVEL 8
42#else
43#define DEF_MEM_LEVEL MAX_MEM_LEVEL
44#endif
45#endif
46
47#if SIZEOF_LONG > SIZEOF_INT
48static inline uInt
49max_uint(long n)
50{
51 if (n > UINT_MAX) n = UINT_MAX;
52 return (uInt)n;
53}
54#define MAX_UINT(n) max_uint(n)
55#else
56#define MAX_UINT(n) (uInt)(n)
57#endif
58
59static ID id_dictionaries;
60
61/*--------- Prototypes --------*/
62
63static NORETURN(void raise_zlib_error(int, const char*));
64static VALUE rb_zlib_version(VALUE);
65static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
66static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
67static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
68static VALUE rb_zlib_crc_table(VALUE);
69static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
70static void zlib_mem_free(voidpf, voidpf);
71static void finalizer_warn(const char*);
72
73struct zstream;
74struct zstream_funcs;
75struct zstream_run_args;
76static void zstream_init(struct zstream*, const struct zstream_funcs*);
77static void zstream_expand_buffer(struct zstream*);
78static void zstream_expand_buffer_into(struct zstream*, unsigned long);
79static int zstream_expand_buffer_non_stream(struct zstream *z);
80static void zstream_append_buffer(struct zstream*, const Bytef*, long);
81static VALUE zstream_detach_buffer(struct zstream*);
82static VALUE zstream_shift_buffer(struct zstream*, long);
83static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
84static void zstream_buffer_ungetbyte(struct zstream*, int);
85static void zstream_append_input(struct zstream*, const Bytef*, long);
86static void zstream_discard_input(struct zstream*, long);
87static void zstream_reset_input(struct zstream*);
88static void zstream_passthrough_input(struct zstream*);
89static VALUE zstream_detach_input(struct zstream*);
90static void zstream_reset(struct zstream*);
91static VALUE zstream_end(struct zstream*);
92static VALUE zstream_ensure_end(VALUE v);
93static void zstream_run(struct zstream*, Bytef*, long, int);
94static VALUE zstream_sync(struct zstream*, Bytef*, long);
95static void zstream_mark(void*);
96static void zstream_free(void*);
97static VALUE zstream_new(VALUE, const struct zstream_funcs*);
98static struct zstream *get_zstream(VALUE);
99static void zstream_finalize(struct zstream*);
100
101static VALUE rb_zstream_end(VALUE);
102static VALUE rb_zstream_reset(VALUE);
103static VALUE rb_zstream_finish(VALUE);
104static VALUE rb_zstream_flush_next_in(VALUE);
105static VALUE rb_zstream_flush_next_out(VALUE);
106static VALUE rb_zstream_avail_out(VALUE);
107static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
108static VALUE rb_zstream_avail_in(VALUE);
109static VALUE rb_zstream_total_in(VALUE);
110static VALUE rb_zstream_total_out(VALUE);
111static VALUE rb_zstream_data_type(VALUE);
112static VALUE rb_zstream_adler(VALUE);
113static VALUE rb_zstream_finished_p(VALUE);
114static VALUE rb_zstream_closed_p(VALUE);
115
116static VALUE rb_deflate_s_allocate(VALUE);
117static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
118static VALUE rb_deflate_init_copy(VALUE, VALUE);
119static VALUE deflate_run(VALUE);
120static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
121static void do_deflate(struct zstream*, VALUE, int);
122static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
123static VALUE rb_deflate_addstr(VALUE, VALUE);
124static VALUE rb_deflate_flush(int, VALUE*, VALUE);
125static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
126static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
127
128static VALUE inflate_run(VALUE);
129static VALUE rb_inflate_s_allocate(VALUE);
130static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
131static VALUE rb_inflate_s_inflate(VALUE, VALUE);
132static void do_inflate(struct zstream*, VALUE);
133static VALUE rb_inflate_inflate(VALUE, VALUE);
134static VALUE rb_inflate_addstr(VALUE, VALUE);
135static VALUE rb_inflate_sync(VALUE, VALUE);
136static VALUE rb_inflate_sync_point_p(VALUE);
137static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
138
139#if GZIP_SUPPORT
140struct gzfile;
141static void gzfile_mark(void*);
142static void gzfile_free(void*);
143static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
144static void gzfile_reset(struct gzfile*);
145static void gzfile_close(struct gzfile*, int);
146static void gzfile_write_raw(struct gzfile*);
147static VALUE gzfile_read_raw_partial(VALUE);
148static VALUE gzfile_read_raw_rescue(VALUE,VALUE);
149static VALUE gzfile_read_raw(struct gzfile*, VALUE outbuf);
150static int gzfile_read_raw_ensure(struct gzfile*, long, VALUE outbuf);
151static char *gzfile_read_raw_until_zero(struct gzfile*, long);
152static unsigned int gzfile_get16(const unsigned char*);
153static unsigned long gzfile_get32(const unsigned char*);
154static void gzfile_set32(unsigned long n, unsigned char*);
155static void gzfile_make_header(struct gzfile*);
156static void gzfile_make_footer(struct gzfile*);
157static void gzfile_read_header(struct gzfile*, VALUE outbuf);
158static void gzfile_check_footer(struct gzfile*, VALUE outbuf);
159static void gzfile_write(struct gzfile*, Bytef*, long);
160static long gzfile_read_more(struct gzfile*, VALUE outbuf);
161static void gzfile_calc_crc(struct gzfile*, VALUE);
162static VALUE gzfile_read(struct gzfile*, long);
163static VALUE gzfile_read_all(struct gzfile*);
164static void gzfile_ungets(struct gzfile*, const Bytef*, long);
165static void gzfile_ungetbyte(struct gzfile*, int);
166static VALUE gzfile_writer_end_run(VALUE);
167static void gzfile_writer_end(struct gzfile*);
168static VALUE gzfile_reader_end_run(VALUE);
169static void gzfile_reader_end(struct gzfile*);
170static void gzfile_reader_rewind(struct gzfile*);
171static VALUE gzfile_reader_get_unused(struct gzfile*);
172static struct gzfile *get_gzfile(VALUE);
173static VALUE gzfile_ensure_close(VALUE);
174static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
175static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
176NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
177static VALUE gzfile_error_inspect(VALUE);
178
179static VALUE rb_gzfile_to_io(VALUE);
180static VALUE rb_gzfile_crc(VALUE);
181static VALUE rb_gzfile_mtime(VALUE);
182static VALUE rb_gzfile_level(VALUE);
183static VALUE rb_gzfile_os_code(VALUE);
184static VALUE rb_gzfile_orig_name(VALUE);
185static VALUE rb_gzfile_comment(VALUE);
186static VALUE rb_gzfile_lineno(VALUE);
187static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
188static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
189static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
190static VALUE rb_gzfile_set_comment(VALUE, VALUE);
191static VALUE rb_gzfile_close(VALUE);
192static VALUE rb_gzfile_finish(VALUE);
193static VALUE rb_gzfile_closed_p(VALUE);
194static VALUE rb_gzfile_eof_p(VALUE);
195static VALUE rb_gzfile_sync(VALUE);
196static VALUE rb_gzfile_set_sync(VALUE, VALUE);
197static VALUE rb_gzfile_total_in(VALUE);
198static VALUE rb_gzfile_total_out(VALUE);
199static VALUE rb_gzfile_path(VALUE);
200
201static VALUE rb_gzwriter_s_allocate(VALUE);
202static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
203static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
204static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
205static VALUE rb_gzwriter_write(int, VALUE*, VALUE);
206static VALUE rb_gzwriter_putc(VALUE, VALUE);
207
208static VALUE rb_gzreader_s_allocate(VALUE);
209static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
210static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
211static VALUE rb_gzreader_rewind(VALUE);
212static VALUE rb_gzreader_unused(VALUE);
213static VALUE rb_gzreader_read(int, VALUE*, VALUE);
214static VALUE rb_gzreader_getc(VALUE);
215static VALUE rb_gzreader_readchar(VALUE);
216static VALUE rb_gzreader_each_byte(VALUE);
217static VALUE rb_gzreader_ungetc(VALUE, VALUE);
218static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
219static void gzreader_skip_linebreaks(struct gzfile*);
220static VALUE gzreader_gets(int, VALUE*, VALUE);
221static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
222static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
223static VALUE rb_gzreader_each(int, VALUE*, VALUE);
224static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
225#endif /* GZIP_SUPPORT */
226
227/*
228 * Document-module: Zlib
229 *
230 * This module provides access to the {zlib library}[http://zlib.net]. Zlib is
231 * designed to be a portable, free, general-purpose, legally unencumbered --
232 * that is, not covered by any patents -- lossless data-compression library
233 * for use on virtually any computer hardware and operating system.
234 *
235 * The zlib compression library provides in-memory compression and
236 * decompression functions, including integrity checks of the uncompressed
237 * data.
238 *
239 * The zlib compressed data format is described in RFC 1950, which is a
240 * wrapper around a deflate stream which is described in RFC 1951.
241 *
242 * The library also supports reading and writing files in gzip (.gz) format
243 * with an interface similar to that of IO. The gzip format is described in
244 * RFC 1952 which is also a wrapper around a deflate stream.
245 *
246 * The zlib format was designed to be compact and fast for use in memory and on
247 * communications channels. The gzip format was designed for single-file
248 * compression on file systems, has a larger header than zlib to maintain
249 * directory information, and uses a different, slower check method than zlib.
250 *
251 * See your system's zlib.h for further information about zlib
252 *
253 * == Sample usage
254 *
255 * Using the wrapper to compress strings with default parameters is quite
256 * simple:
257 *
258 * require "zlib"
259 *
260 * data_to_compress = File.read("don_quixote.txt")
261 *
262 * puts "Input size: #{data_to_compress.size}"
263 * #=> Input size: 2347740
264 *
265 * data_compressed = Zlib::Deflate.deflate(data_to_compress)
266 *
267 * puts "Compressed size: #{data_compressed.size}"
268 * #=> Compressed size: 887238
269 *
270 * uncompressed_data = Zlib::Inflate.inflate(data_compressed)
271 *
272 * puts "Uncompressed data is: #{uncompressed_data}"
273 * #=> Uncompressed data is: The Project Gutenberg EBook of Don Quixote...
274 *
275 * == Class tree
276 *
277 * - Zlib::Deflate
278 * - Zlib::Inflate
279 * - Zlib::ZStream
280 * - Zlib::Error
281 * - Zlib::StreamEnd
282 * - Zlib::NeedDict
283 * - Zlib::DataError
284 * - Zlib::StreamError
285 * - Zlib::MemError
286 * - Zlib::BufError
287 * - Zlib::VersionError
288 * - Zlib::InProgressError
289 *
290 * (if you have GZIP_SUPPORT)
291 * - Zlib::GzipReader
292 * - Zlib::GzipWriter
293 * - Zlib::GzipFile
294 * - Zlib::GzipFile::Error
295 * - Zlib::GzipFile::LengthError
296 * - Zlib::GzipFile::CRCError
297 * - Zlib::GzipFile::NoFooter
298 *
299 */
300void Init_zlib(void);
301
302/*--------- Exceptions --------*/
303
304static VALUE cZError, cStreamEnd, cNeedDict;
305static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError, cInProgressError;
306
307static void
308raise_zlib_error(int err, const char *msg)
309{
310 VALUE exc;
311
312 if (!msg) {
313 msg = zError(err);
314 }
315
316 switch(err) {
317 case Z_STREAM_END:
318 exc = rb_exc_new2(cStreamEnd, msg);
319 break;
320 case Z_NEED_DICT:
321 exc = rb_exc_new2(cNeedDict, msg);
322 break;
323 case Z_STREAM_ERROR:
324 exc = rb_exc_new2(cStreamError, msg);
325 break;
326 case Z_DATA_ERROR:
327 exc = rb_exc_new2(cDataError, msg);
328 break;
329 case Z_BUF_ERROR:
330 exc = rb_exc_new2(cBufError, msg);
331 break;
332 case Z_VERSION_ERROR:
333 exc = rb_exc_new2(cVersionError, msg);
334 break;
335 case Z_MEM_ERROR:
336 exc = rb_exc_new2(cMemError, msg);
337 break;
338 case Z_ERRNO:
339 rb_sys_fail(msg);
340 /* no return */
341 default:
342 exc = rb_exc_new_str(cZError,
343 rb_sprintf("unknown zlib error %d: %s", err, msg));
344 }
345
347}
348
349
350/*--- Warning (in finalizer) ---*/
351
352static void
353finalizer_warn(const char *msg)
354{
355 fprintf(stderr, "zlib(finalizer): %s\n", msg);
356}
357
358
359/*-------- module Zlib --------*/
360
361/*
362 * Document-method: Zlib.zlib_version
363 *
364 * Returns the string which represents the version of zlib library.
365 */
366static VALUE
367rb_zlib_version(VALUE klass)
368{
369 return rb_str_new2(zlibVersion());
370}
371
372#if SIZEOF_LONG > SIZEOF_INT
373static uLong
374checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
375{
376 if (len > UINT_MAX) {
377 do {
378 sum = func(sum, ptr, UINT_MAX);
379 ptr += UINT_MAX;
380 len -= UINT_MAX;
381 } while (len >= UINT_MAX);
382 }
383 if (len > 0) sum = func(sum, ptr, (uInt)len);
384 return sum;
385}
386#else
387#define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
388#endif
389
390static VALUE
391do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
392{
393 VALUE str, vsum;
394 unsigned long sum;
395
396 rb_scan_args(argc, argv, "02", &str, &vsum);
397
398 if (!NIL_P(vsum)) {
399 sum = NUM2ULONG(vsum);
400 }
401 else if (NIL_P(str)) {
402 sum = 0;
403 }
404 else {
405 sum = func(0, Z_NULL, 0);
406 }
407
408 if (NIL_P(str)) {
409 sum = func(sum, Z_NULL, 0);
410 }
411 else {
413 sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
414 }
415 return rb_uint2inum(sum);
416}
417
418/*
419 * Document-method: Zlib.adler32
420 *
421 * call-seq: Zlib.adler32(string, adler)
422 *
423 * Calculates Adler-32 checksum for +string+, and returns updated value of
424 * +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
425 * +adler+ is omitted, it assumes that the initial value is given to +adler+.
426 *
427 * Example usage:
428 *
429 * require "zlib"
430 *
431 * data = "foo"
432 * puts "Adler32 checksum: #{Zlib.adler32(data).to_s(16)}"
433 * #=> Adler32 checksum: 2820145
434 *
435 */
436static VALUE
437rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
438{
439 return do_checksum(argc, argv, adler32);
440}
441
442#ifdef HAVE_ADLER32_COMBINE
443/*
444 * Document-method: Zlib.adler32_combine
445 *
446 * call-seq: Zlib.adler32_combine(adler1, adler2, len2)
447 *
448 * Combine two Adler-32 check values in to one. +alder1+ is the first Adler-32
449 * value, +adler2+ is the second Adler-32 value. +len2+ is the length of the
450 * string used to generate +adler2+.
451 *
452 */
453static VALUE
454rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
455{
456 return ULONG2NUM(
457 adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
458}
459#else
460#define rb_zlib_adler32_combine rb_f_notimplement
461#endif
462
463/*
464 * Document-method: Zlib.crc32
465 *
466 * call-seq: Zlib.crc32(string, crc)
467 *
468 * Calculates CRC checksum for +string+, and returns updated value of +crc+. If
469 * +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
470 * assumes that the initial value is given to +crc+.
471 *
472 * FIXME: expression.
473 */
474static VALUE
475rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
476{
477 return do_checksum(argc, argv, crc32);
478}
479
480#ifdef HAVE_CRC32_COMBINE
481/*
482 * Document-method: Zlib.crc32_combine
483 *
484 * call-seq: Zlib.crc32_combine(crc1, crc2, len2)
485 *
486 * Combine two CRC-32 check values in to one. +crc1+ is the first CRC-32
487 * value, +crc2+ is the second CRC-32 value. +len2+ is the length of the
488 * string used to generate +crc2+.
489 *
490 */
491static VALUE
493{
494 return ULONG2NUM(
495 crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
496}
497#else
498#define rb_zlib_crc32_combine rb_f_notimplement
499#endif
500
501/*
502 * Document-method: Zlib.crc_table
503 *
504 * Returns the table for calculating CRC checksum as an array.
505 */
506static VALUE
507rb_zlib_crc_table(VALUE obj)
508{
509#if !defined(HAVE_TYPE_Z_CRC_T)
510 /* z_crc_t is defined since zlib-1.2.7. */
511 typedef unsigned long z_crc_t;
512#endif
513 const z_crc_t *crctbl;
514 VALUE dst;
515 int i;
516
517 crctbl = get_crc_table();
518 dst = rb_ary_new2(256);
519
520 for (i = 0; i < 256; i++) {
521 rb_ary_push(dst, rb_uint2inum(crctbl[i]));
522 }
523 return dst;
524}
525
526
527
528/*-------- zstream - internal APIs --------*/
529
530struct zstream {
531 unsigned long flags;
535 z_stream stream;
536 const struct zstream_funcs {
537 int (*reset)(z_streamp);
538 int (*end)(z_streamp);
539 int (*run)(z_streamp, int);
541};
542
543#define ZSTREAM_FLAG_READY (1 << 0)
544#define ZSTREAM_FLAG_IN_STREAM (1 << 1)
545#define ZSTREAM_FLAG_FINISHED (1 << 2)
546#define ZSTREAM_FLAG_CLOSING (1 << 3)
547#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for
548 gzip*/
549#define ZSTREAM_IN_PROGRESS (1 << 5)
550#define ZSTREAM_FLAG_UNUSED (1 << 6)
552#define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
553#define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
554#define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
555#define ZSTREAM_IS_CLOSING(z) ((z)->flags & ZSTREAM_FLAG_CLOSING)
556#define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
557#define ZSTREAM_BUF_FILLED(z) (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf))
559#define ZSTREAM_EXPAND_BUFFER_OK 0
560
561/* I think that more better value should be found,
562 but I gave up finding it. B) */
563#define ZSTREAM_INITIAL_BUFSIZE 1024
564/* Allow a quick return when the thread is interrupted */
565#define ZSTREAM_AVAIL_OUT_STEP_MAX 16384
566#define ZSTREAM_AVAIL_OUT_STEP_MIN 2048
567
568static const struct zstream_funcs deflate_funcs = {
569 deflateReset, deflateEnd, deflate,
570};
571
572static const struct zstream_funcs inflate_funcs = {
573 inflateReset, inflateEnd, inflate,
574};
577 struct zstream *const z;
578 Bytef *src;
579 long len;
580 int flush; /* stream flush value for inflate() or deflate() */
581 int interrupt; /* stop processing the stream and return to ruby */
582 int jump_state; /* for buffer expansion block break or exception */
583 int stream_output; /* for streaming zlib processing */
584};
585
586static voidpf
587zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
588{
589 voidpf p = xmalloc2(items, size);
590 /* zlib FAQ: Valgrind (or some similar memory access checker) says that
591 deflate is performing a conditional jump that depends on an
592 uninitialized value. Isn't that a bug?
593 http://www.zlib.net/zlib_faq.html#faq36 */
595 return p;
596}
597
598static void
599zlib_mem_free(voidpf opaque, voidpf address)
600{
601 xfree(address);
602}
603
604static void
605zstream_init(struct zstream *z, const struct zstream_funcs *func)
606{
607 z->flags = 0;
608 z->buf = Qnil;
609 z->input = Qnil;
610 z->mutex = rb_mutex_new();
611 z->stream.zalloc = zlib_mem_alloc;
612 z->stream.zfree = zlib_mem_free;
613 z->stream.opaque = Z_NULL;
614 z->stream.msg = Z_NULL;
615 z->stream.next_in = Z_NULL;
616 z->stream.avail_in = 0;
617 z->stream.next_out = Z_NULL;
618 z->stream.avail_out = 0;
619 z->func = func;
620}
622#define zstream_init_deflate(z) zstream_init((z), &deflate_funcs)
623#define zstream_init_inflate(z) zstream_init((z), &inflate_funcs)
624
625static void
626zstream_expand_buffer(struct zstream *z)
627{
628 if (NIL_P(z->buf)) {
629 zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
630 return;
631 }
632
633 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
634 long buf_filled = ZSTREAM_BUF_FILLED(z);
635 if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
636 int state = 0;
637
639
641 rb_protect(rb_yield, z->buf, &state);
643
644 z->buf = Qnil;
645 zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
646
647 if (state)
648 rb_jump_tag(state);
649
650 return;
651 }
652 else {
653 zstream_expand_buffer_into(z,
654 ZSTREAM_AVAIL_OUT_STEP_MAX - buf_filled);
655 }
656 }
657 else {
658 zstream_expand_buffer_non_stream(z);
659 }
660}
661
662static void
663zstream_expand_buffer_into(struct zstream *z, unsigned long size)
664{
665 if (NIL_P(z->buf)) {
666 /* I uses rb_str_new here not rb_str_buf_new because
667 rb_str_buf_new makes a zero-length string. */
668 z->buf = rb_str_buf_new(size);
669 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
670 z->stream.avail_out = MAX_UINT(size);
671 rb_obj_hide(z->buf);
672 }
673 else if (z->stream.avail_out != size) {
675 z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
676 z->stream.avail_out = MAX_UINT(size);
677 }
678}
679
680static void *
681zstream_expand_buffer_protect(void *ptr)
682{
683 struct zstream *z = (struct zstream *)ptr;
684 int state = 0;
685
686 rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
687
688 return (void *)(VALUE)state;
689}
690
691static int
692zstream_expand_buffer_non_stream(struct zstream *z)
693{
694 long inc, len = ZSTREAM_BUF_FILLED(z);
695
697 z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
698 }
699 else {
700 inc = len / 2;
701 if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
703 }
704
705 rb_str_modify_expand(z->buf, inc);
706 z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
708 }
709 z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
710
712}
713
714static void
715zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
716{
717 if (NIL_P(z->buf)) {
718 z->buf = rb_str_buf_new(len);
719 rb_str_buf_cat(z->buf, (const char*)src, len);
720 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
721 z->stream.avail_out = 0;
722 rb_obj_hide(z->buf);
723 return;
724 }
725
726 if ((long)rb_str_capacity(z->buf) < ZSTREAM_BUF_FILLED(z) + len) {
728 z->stream.avail_out = 0;
729 }
730 else {
731 if (z->stream.avail_out >= (uInt)len) {
732 z->stream.avail_out -= (uInt)len;
733 }
734 else {
735 z->stream.avail_out = 0;
736 }
737 }
738 rb_str_cat(z->buf, (const char *)src, len);
739 z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
740}
742#define zstream_append_buffer2(z,v) \
743 zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
744
745static VALUE
746zstream_detach_buffer(struct zstream *z)
747{
748 VALUE dst;
749
750 if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
752 /* prevent tiny yields mid-stream, save for next
753 * zstream_expand_buffer() or stream end */
754 return Qnil;
755 }
756
757 if (NIL_P(z->buf)) {
758 dst = rb_str_new(0, 0);
759 }
760 else {
761 dst = z->buf;
763 }
764
765 z->buf = Qnil;
766 z->stream.next_out = 0;
767 z->stream.avail_out = 0;
768
769 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
770 rb_yield(dst);
771 dst = Qnil;
772 }
773
774 return dst;
775}
776
777static VALUE
778zstream_shift_buffer(struct zstream *z, long len)
779{
780 VALUE dst;
781 char *bufptr;
782 long buflen = ZSTREAM_BUF_FILLED(z);
783
784 if (buflen <= len) {
785 return zstream_detach_buffer(z);
786 }
787
788 bufptr = RSTRING_PTR(z->buf);
789 dst = rb_str_new(bufptr, len);
790 buflen -= len;
791 memmove(bufptr, bufptr + len, buflen);
792 rb_str_set_len(z->buf, buflen);
793 z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
794 buflen = (long)rb_str_capacity(z->buf) - ZSTREAM_BUF_FILLED(z);
795 if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
797 }
798 z->stream.avail_out = (uInt)buflen;
799
800 return dst;
801}
802
803static void
804zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
805{
806 char *bufptr;
807 long filled;
808
809 if (NIL_P(z->buf) || (long)rb_str_capacity(z->buf) <= ZSTREAM_BUF_FILLED(z)) {
810 zstream_expand_buffer_into(z, len);
811 }
812
813 RSTRING_GETMEM(z->buf, bufptr, filled);
814 memmove(bufptr + len, bufptr, filled);
815 memmove(bufptr, b, len);
816 rb_str_set_len(z->buf, filled + len);
817 if (z->stream.avail_out > 0) {
818 if (len > z->stream.avail_out) len = z->stream.avail_out;
819 z->stream.next_out+=len;
820 z->stream.avail_out-=(uInt)len;
821 }
822}
823
824static void
825zstream_buffer_ungetbyte(struct zstream *z, int c)
826{
827 Bytef cc = (Bytef)c;
828 zstream_buffer_ungets(z, &cc, 1);
829}
830
831static void
832zstream_append_input(struct zstream *z, const Bytef *src, long len)
833{
834 if (len <= 0) return;
835
836 if (NIL_P(z->input)) {
838 rb_str_buf_cat(z->input, (const char*)src, len);
839 rb_obj_hide(z->input);
840 }
841 else {
842 rb_str_buf_cat(z->input, (const char*)src, len);
843 }
844}
846#define zstream_append_input2(z,v)\
847 RB_GC_GUARD(v),\
848 zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
849
850static void
851zstream_discard_input(struct zstream *z, long len)
852{
853 if (NIL_P(z->input)) {
854 }
855 else if (RBASIC_CLASS(z->input) == 0) {
856 /* hidden, we created z->input and have complete control */
857 char *ptr;
858 long oldlen, newlen;
859
860 RSTRING_GETMEM(z->input, ptr, oldlen);
861 newlen = oldlen - len;
862 if (newlen > 0) {
863 memmove(ptr, ptr + len, newlen);
864 }
865 if (newlen < 0) {
866 newlen = 0;
867 }
868 rb_str_resize(z->input, newlen);
869 if (newlen == 0) {
871 z->input = Qnil;
872 }
873 else {
874 rb_str_set_len(z->input, newlen);
875 }
876 }
877 else { /* do not mangle user-provided data */
878 if (RSTRING_LEN(z->input) <= len) {
879 z->input = Qnil;
880 }
881 else {
882 z->input = rb_str_substr(z->input, len,
883 RSTRING_LEN(z->input) - len);
884 }
885 }
886}
887
888static void
889zstream_reset_input(struct zstream *z)
890{
891 if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) {
892 rb_str_resize(z->input, 0);
893 }
894 else {
895 z->input = Qnil;
896 }
897}
898
899static void
900zstream_passthrough_input(struct zstream *z)
901{
902 if (!NIL_P(z->input)) {
904 z->input = Qnil;
905 }
906}
907
908static VALUE
909zstream_detach_input(struct zstream *z)
910{
911 VALUE dst;
912
913 if (NIL_P(z->input)) {
914 dst = rb_str_new(0, 0);
915 }
916 else {
917 dst = z->input;
919 }
920 z->input = Qnil;
921 return dst;
922}
923
924static void
925zstream_reset(struct zstream *z)
926{
927 int err;
928
929 err = z->func->reset(&z->stream);
930 if (err != Z_OK) {
931 raise_zlib_error(err, z->stream.msg);
932 }
934 z->buf = Qnil;
935 z->stream.next_out = 0;
936 z->stream.avail_out = 0;
937 zstream_reset_input(z);
938}
939
940static VALUE
941zstream_end(struct zstream *z)
942{
943 int err;
944
945 if (!ZSTREAM_IS_READY(z)) {
946 rb_warning("attempt to close uninitialized zstream; ignored.");
947 return Qnil;
948 }
949 if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
950 rb_warning("attempt to close unfinished zstream; reset forced.");
951 zstream_reset(z);
952 }
953
954 zstream_reset_input(z);
955 err = z->func->end(&z->stream);
956 if (err != Z_OK) {
957 raise_zlib_error(err, z->stream.msg);
958 }
959 z->flags = 0;
960 return Qnil;
961}
962
963static VALUE
964zstream_ensure_end(VALUE v)
965{
966 return zstream_end((struct zstream *)v);
967}
968
969static void *
970zstream_run_func(void *ptr)
971{
972 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
973 int err, state, flush = args->flush;
974 struct zstream *z = args->z;
975 uInt n;
976
977 err = Z_OK;
978 while (!args->interrupt) {
979 n = z->stream.avail_out;
980 err = z->func->run(&z->stream, flush);
981 rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
982
983 if (err == Z_STREAM_END) {
984 z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
986 break;
987 }
988
989 if (err != Z_OK && err != Z_BUF_ERROR)
990 break;
991
992 if (z->stream.avail_out > 0) {
994 break;
995 }
996
997 if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
998 /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
999 /* but deflate() could be called with avail_in == 0 (there's hidden buffer
1000 in zstream->state) */
1002 break;
1003 }
1004
1005 if (args->stream_output) {
1006 state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
1007 (void *)z);
1008 }
1009 else {
1010 state = zstream_expand_buffer_non_stream(z);
1011 }
1012
1013 if (state) {
1014 err = Z_OK; /* buffer expanded but stream processing was stopped */
1015 args->jump_state = state;
1016 break;
1017 }
1018 }
1019
1020 return (void *)(VALUE)err;
1021}
1022
1023/*
1024 * There is no safe way to interrupt z->run->func().
1025 * async-signal-safe
1026 */
1027static void
1028zstream_unblock_func(void *ptr)
1029{
1030 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
1031
1032 args->interrupt = 1;
1033}
1034
1035static VALUE
1036zstream_run_try(VALUE value_arg)
1037{
1038 struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
1039 struct zstream *z = args->z;
1040 Bytef *src = args->src;
1041 long len = args->len;
1042 int flush = args->flush;
1043
1044 int err;
1045 VALUE old_input = Qnil;
1046
1047 if (NIL_P(z->input) && len == 0) {
1048 z->stream.next_in = (Bytef*)"";
1049 z->stream.avail_in = 0;
1050 }
1051 else {
1052 zstream_append_input(z, src, len);
1053 /* keep reference to `z->input' so as not to be garbage collected
1054 after zstream_reset_input() and prevent `z->stream.next_in'
1055 from dangling. */
1056 old_input = zstream_detach_input(z);
1057 rb_obj_hide(old_input); /* for GVL release and later recycle */
1058 z->stream.next_in = (Bytef*)RSTRING_PTR(old_input);
1059 z->stream.avail_in = MAX_UINT(RSTRING_LEN(old_input));
1060 }
1061
1062 if (z->stream.avail_out == 0) {
1063 zstream_expand_buffer(z);
1064 }
1065
1066loop:
1067#ifndef RB_NOGVL_UBF_ASYNC_SAFE
1068 err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args,
1069 zstream_unblock_func, (void *)args);
1070#else
1071 err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
1072 zstream_unblock_func, (void *)args,
1074#endif
1075
1076 /* retry if no exception is thrown */
1077 if (err == Z_OK && args->interrupt) {
1078 args->interrupt = 0;
1079 goto loop;
1080 }
1081
1082 if (flush != Z_FINISH && err == Z_BUF_ERROR
1083 && z->stream.avail_out > 0) {
1085 }
1086
1087 zstream_reset_input(z);
1088
1089 if (err != Z_OK && err != Z_STREAM_END) {
1090 if (z->stream.avail_in > 0) {
1091 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1092 }
1093 if (err == Z_NEED_DICT) {
1094 VALUE self = (VALUE)z->stream.opaque;
1095 if (self) {
1096 VALUE dicts = rb_ivar_get(self, id_dictionaries);
1097 VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
1098 if (!NIL_P(dict)) {
1099 rb_inflate_set_dictionary(self, dict);
1100 goto loop;
1101 }
1102 }
1103 }
1104 raise_zlib_error(err, z->stream.msg);
1105 }
1106
1107 if (z->stream.avail_in > 0) {
1108 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1109 }
1110 if (!NIL_P(old_input)) {
1111 rb_str_resize(old_input, 0);
1112 rb_gc_force_recycle(old_input);
1113 }
1114
1115 if (args->jump_state)
1116 rb_jump_tag(args->jump_state);
1117 return Qnil;
1118}
1119
1120static VALUE
1121zstream_run_ensure(VALUE value_arg)
1122{
1123 struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
1124
1125 /* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
1126 args->z->flags &= ~ZSTREAM_IN_PROGRESS;
1127
1128 return Qnil;
1129}
1130
1131static VALUE
1132zstream_run_synchronized(VALUE value_arg)
1133{
1134 struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
1135
1136 /* Cannot start zstream while it is in progress. */
1137 if (args->z->flags & ZSTREAM_IN_PROGRESS) {
1138 rb_raise(cInProgressError, "zlib stream is in progress");
1139 }
1140 args->z->flags |= ZSTREAM_IN_PROGRESS;
1141
1142 rb_ensure(zstream_run_try, value_arg, zstream_run_ensure, value_arg);
1143
1144 return Qnil;
1145}
1146
1147static void
1148zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1149{
1150 struct zstream_run_args args = {
1151 .z = z,
1152 .src = src,
1153 .len = len,
1154 .flush = flush,
1155 .interrupt = 0,
1156 .jump_state = 0,
1157 .stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(),
1158 };
1159 rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
1160}
1161static VALUE
1162zstream_sync(struct zstream *z, Bytef *src, long len)
1163{
1164 /* VALUE rest; */
1165 int err;
1166
1167 if (!NIL_P(z->input)) {
1168 z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
1169 z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
1170 err = inflateSync(&z->stream);
1171 if (err == Z_OK) {
1172 zstream_discard_input(z,
1173 RSTRING_LEN(z->input) - z->stream.avail_in);
1174 zstream_append_input(z, src, len);
1175 return Qtrue;
1176 }
1177 zstream_reset_input(z);
1178 if (err != Z_DATA_ERROR) {
1179 /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1180 raise_zlib_error(err, z->stream.msg);
1181 }
1182 }
1183
1184 if (len <= 0) return Qfalse;
1185
1186 z->stream.next_in = src;
1187 z->stream.avail_in = MAX_UINT(len);
1188 err = inflateSync(&z->stream);
1189 if (err == Z_OK) {
1190 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1191 return Qtrue;
1192 }
1193 if (err != Z_DATA_ERROR) {
1194 /* rest = rb_str_new((char*)z->stream.next_in, z->stream.avail_in); */
1195 raise_zlib_error(err, z->stream.msg);
1196 }
1197 return Qfalse;
1198}
1199
1200static void
1201zstream_mark(void *p)
1202{
1203 struct zstream *z = p;
1204 rb_gc_mark(z->buf);
1205 rb_gc_mark(z->input);
1206 rb_gc_mark(z->mutex);
1207}
1208
1209static void
1210zstream_finalize(struct zstream *z)
1211{
1212 int err = z->func->end(&z->stream);
1213 if (err == Z_STREAM_ERROR)
1214 finalizer_warn("the stream state was inconsistent.");
1215 if (err == Z_DATA_ERROR)
1216 finalizer_warn("the stream was freed prematurely.");
1217}
1218
1219static void
1220zstream_free(void *p)
1221{
1222 struct zstream *z = p;
1223
1224 if (ZSTREAM_IS_READY(z)) {
1225 zstream_finalize(z);
1226 }
1227 xfree(z);
1228}
1229
1230static size_t
1231zstream_memsize(const void *p)
1232{
1233 /* n.b. this does not track memory managed via zalloc/zfree callbacks */
1234 return sizeof(struct zstream);
1235}
1236
1237static const rb_data_type_t zstream_data_type = {
1238 "zstream",
1239 { zstream_mark, zstream_free, zstream_memsize, },
1241};
1242
1243static VALUE
1244zstream_new(VALUE klass, const struct zstream_funcs *funcs)
1245{
1246 VALUE obj;
1247 struct zstream *z;
1248
1249 obj = TypedData_Make_Struct(klass, struct zstream, &zstream_data_type, z);
1250 zstream_init(z, funcs);
1251 z->stream.opaque = (voidpf)obj;
1252 return obj;
1253}
1255#define zstream_deflate_new(klass) zstream_new((klass), &deflate_funcs)
1256#define zstream_inflate_new(klass) zstream_new((klass), &inflate_funcs)
1257
1258static struct zstream *
1259get_zstream(VALUE obj)
1260{
1261 struct zstream *z;
1262
1263 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1264 if (!ZSTREAM_IS_READY(z)) {
1265 rb_raise(cZError, "stream is not ready");
1266 }
1267 return z;
1268}
1269
1270
1271/* ------------------------------------------------------------------------- */
1272
1273/*
1274 * Document-class: Zlib::ZStream
1275 *
1276 * Zlib::ZStream is the abstract class for the stream which handles the
1277 * compressed data. The operations are defined in the subclasses:
1278 * Zlib::Deflate for compression, and Zlib::Inflate for decompression.
1279 *
1280 * An instance of Zlib::ZStream has one stream (struct zstream in the source)
1281 * and two variable-length buffers which associated to the input (next_in) of
1282 * the stream and the output (next_out) of the stream. In this document,
1283 * "input buffer" means the buffer for input, and "output buffer" means the
1284 * buffer for output.
1285 *
1286 * Data input into an instance of Zlib::ZStream are temporally stored into
1287 * the end of input buffer, and then data in input buffer are processed from
1288 * the beginning of the buffer until no more output from the stream is
1289 * produced (i.e. until avail_out > 0 after processing). During processing,
1290 * output buffer is allocated and expanded automatically to hold all output
1291 * data.
1292 *
1293 * Some particular instance methods consume the data in output buffer and
1294 * return them as a String.
1295 *
1296 * Here is an ascii art for describing above:
1297 *
1298 * +================ an instance of Zlib::ZStream ================+
1299 * || ||
1300 * || +--------+ +-------+ +--------+ ||
1301 * || +--| output |<---------|zstream|<---------| input |<--+ ||
1302 * || | | buffer | next_out+-------+next_in | buffer | | ||
1303 * || | +--------+ +--------+ | ||
1304 * || | | ||
1305 * +===|======================================================|===+
1306 * | |
1307 * v |
1308 * "output data" "input data"
1309 *
1310 * If an error occurs during processing input buffer, an exception which is a
1311 * subclass of Zlib::Error is raised. At that time, both input and output
1312 * buffer keep their conditions at the time when the error occurs.
1313 *
1314 * == Method Catalogue
1315 *
1316 * Many of the methods in this class are fairly low-level and unlikely to be
1317 * of interest to users. In fact, users are unlikely to use this class
1318 * directly; rather they will be interested in Zlib::Inflate and
1319 * Zlib::Deflate.
1320 *
1321 * The higher level methods are listed below.
1322 *
1323 * - #total_in
1324 * - #total_out
1325 * - #data_type
1326 * - #adler
1327 * - #reset
1328 * - #finish
1329 * - #finished?
1330 * - #close
1331 * - #closed?
1332 */
1333
1334/*
1335 * Closes the stream. All operations on the closed stream will raise an
1336 * exception.
1337 */
1338static VALUE
1339rb_zstream_end(VALUE obj)
1340{
1341 zstream_end(get_zstream(obj));
1342 return Qnil;
1343}
1344
1345/*
1346 * Resets and initializes the stream. All data in both input and output buffer
1347 * are discarded.
1348 */
1349static VALUE
1350rb_zstream_reset(VALUE obj)
1351{
1352 zstream_reset(get_zstream(obj));
1353 return Qnil;
1354}
1355
1356/*
1357 * call-seq:
1358 * finish -> String
1359 * finish { |chunk| ... } -> nil
1360 *
1361 * Finishes the stream and flushes output buffer. If a block is given each
1362 * chunk is yielded to the block until the input buffer has been flushed to
1363 * the output buffer.
1364 */
1365static VALUE
1366rb_zstream_finish(VALUE obj)
1367{
1368 struct zstream *z = get_zstream(obj);
1369
1370 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1371
1372 return zstream_detach_buffer(z);
1373}
1374
1375/*
1376 * call-seq:
1377 * flush_next_in -> input
1378 *
1379 */
1380static VALUE
1381rb_zstream_flush_next_in(VALUE obj)
1382{
1383 struct zstream *z;
1384 VALUE dst;
1385
1386 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1387 dst = zstream_detach_input(z);
1388 return dst;
1389}
1390
1391/*
1392 * call-seq:
1393 * flush_next_out -> String
1394 * flush_next_out { |chunk| ... } -> nil
1395 *
1396 * Flushes output buffer and returns all data in that buffer. If a block is
1397 * given each chunk is yielded to the block until the current output buffer
1398 * has been flushed.
1399 */
1400static VALUE
1401rb_zstream_flush_next_out(VALUE obj)
1402{
1403 struct zstream *z;
1404
1405 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1406
1407 return zstream_detach_buffer(z);
1408}
1409
1410/*
1411 * Returns number of bytes of free spaces in output buffer. Because the free
1412 * space is allocated automatically, this method returns 0 normally.
1413 */
1414static VALUE
1415rb_zstream_avail_out(VALUE obj)
1416{
1417 struct zstream *z;
1418 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1419 return rb_uint2inum(z->stream.avail_out);
1420}
1421
1422/*
1423 * Allocates +size+ bytes of free space in the output buffer. If there are more
1424 * than +size+ bytes already in the buffer, the buffer is truncated. Because
1425 * free space is allocated automatically, you usually don't need to use this
1426 * method.
1427 */
1428static VALUE
1429rb_zstream_set_avail_out(VALUE obj, VALUE size)
1430{
1431 struct zstream *z = get_zstream(obj);
1432
1433 zstream_expand_buffer_into(z, FIX2INT(size));
1434 return size;
1435}
1436
1437/*
1438 * Returns bytes of data in the input buffer. Normally, returns 0.
1439 */
1440static VALUE
1441rb_zstream_avail_in(VALUE obj)
1442{
1443 struct zstream *z;
1444 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1445 return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
1446}
1447
1448/*
1449 * Returns the total bytes of the input data to the stream. FIXME
1450 */
1451static VALUE
1452rb_zstream_total_in(VALUE obj)
1453{
1454 return rb_uint2inum(get_zstream(obj)->stream.total_in);
1455}
1456
1457/*
1458 * Returns the total bytes of the output data from the stream. FIXME
1459 */
1460static VALUE
1461rb_zstream_total_out(VALUE obj)
1462{
1463 return rb_uint2inum(get_zstream(obj)->stream.total_out);
1464}
1465
1466/*
1467 * Guesses the type of the data which have been inputed into the stream. The
1468 * returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
1469 * <tt>UNKNOWN</tt>.
1470 */
1471static VALUE
1472rb_zstream_data_type(VALUE obj)
1473{
1474 return INT2FIX(get_zstream(obj)->stream.data_type);
1475}
1476
1477/*
1478 * Returns the adler-32 checksum.
1479 */
1480static VALUE
1481rb_zstream_adler(VALUE obj)
1482{
1483 return rb_uint2inum(get_zstream(obj)->stream.adler);
1484}
1485
1486/*
1487 * Returns true if the stream is finished.
1488 */
1489static VALUE
1490rb_zstream_finished_p(VALUE obj)
1491{
1492 return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
1493}
1494
1495/*
1496 * Returns true if the stream is closed.
1497 */
1498static VALUE
1499rb_zstream_closed_p(VALUE obj)
1500{
1501 struct zstream *z;
1502 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1503 return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
1504}
1505
1506
1507/* ------------------------------------------------------------------------- */
1508
1509/*
1510 * Document-class: Zlib::Deflate
1511 *
1512 * Zlib::Deflate is the class for compressing data. See Zlib::ZStream for more
1513 * information.
1514 */
1516#define FIXNUMARG(val, ifnil) \
1517 (NIL_P((val)) ? (ifnil) \
1518 : (FIX2INT((val))))
1520#define ARG_LEVEL(val) FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
1521#define ARG_WBITS(val) FIXNUMARG((val), MAX_WBITS)
1522#define ARG_MEMLEVEL(val) FIXNUMARG((val), DEF_MEM_LEVEL)
1523#define ARG_STRATEGY(val) FIXNUMARG((val), Z_DEFAULT_STRATEGY)
1524#define ARG_FLUSH(val) FIXNUMARG((val), Z_NO_FLUSH)
1525
1526
1527static VALUE
1528rb_deflate_s_allocate(VALUE klass)
1529{
1530 return zstream_deflate_new(klass);
1531}
1532
1533/*
1534 * Document-method: Zlib::Deflate.new
1535 *
1536 * call-seq:
1537 * Zlib::Deflate.new(level=DEFAULT_COMPRESSION, window_bits=MAX_WBITS, mem_level=DEF_MEM_LEVEL, strategy=DEFAULT_STRATEGY)
1538 *
1539 * Creates a new deflate stream for compression. If a given argument is nil,
1540 * the default value of that argument is used.
1541 *
1542 * The +level+ sets the compression level for the deflate stream between 0 (no
1543 * compression) and 9 (best compression). The following constants have been
1544 * defined to make code more readable:
1545 *
1546 * * Zlib::DEFAULT_COMPRESSION
1547 * * Zlib::NO_COMPRESSION
1548 * * Zlib::BEST_SPEED
1549 * * Zlib::BEST_COMPRESSION
1550 *
1551 * See http://www.zlib.net/manual.html#Constants for further information.
1552 *
1553 * The +window_bits+ sets the size of the history buffer and should be between
1554 * 8 and 15. Larger values of this parameter result in better compression at
1555 * the expense of memory usage.
1556 *
1557 * The +mem_level+ specifies how much memory should be allocated for the
1558 * internal compression state. 1 uses minimum memory but is slow and reduces
1559 * compression ratio while 9 uses maximum memory for optimal speed. The
1560 * default value is 8. Two constants are defined:
1561 *
1562 * * Zlib::DEF_MEM_LEVEL
1563 * * Zlib::MAX_MEM_LEVEL
1564 *
1565 * The +strategy+ sets the deflate compression strategy. The following
1566 * strategies are available:
1567 *
1568 * Zlib::DEFAULT_STRATEGY:: For normal data
1569 * Zlib::FILTERED:: For data produced by a filter or predictor
1570 * Zlib::FIXED:: Prevents dynamic Huffman codes
1571 * Zlib::HUFFMAN_ONLY:: Prevents string matching
1572 * Zlib::RLE:: Designed for better compression of PNG image data
1573 *
1574 * See the constants for further description.
1575 *
1576 * == Examples
1577 *
1578 * === Basic
1579 *
1580 * open "compressed.file", "w+" do |io|
1581 * io << Zlib::Deflate.new.deflate(File.read("big.file"))
1582 * end
1583 *
1584 * === Custom compression
1585 *
1586 * open "compressed.file", "w+" do |compressed_io|
1587 * deflate = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
1588 * Zlib::MAX_WBITS,
1589 * Zlib::MAX_MEM_LEVEL,
1590 * Zlib::HUFFMAN_ONLY)
1591 *
1592 * begin
1593 * open "big.file" do |big_io|
1594 * until big_io.eof? do
1595 * compressed_io << zd.deflate(big_io.read(16384))
1596 * end
1597 * end
1598 * ensure
1599 * deflate.close
1600 * end
1601 * end
1602 *
1603 * While this example will work, for best optimization review the flags for
1604 * your specific time, memory usage and output space requirements.
1605 */
1606static VALUE
1607rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
1608{
1609 struct zstream *z;
1610 VALUE level, wbits, memlevel, strategy;
1611 int err;
1612
1613 rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
1614 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1615
1616 err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
1617 ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
1618 ARG_STRATEGY(strategy));
1619 if (err != Z_OK) {
1620 raise_zlib_error(err, z->stream.msg);
1621 }
1622 ZSTREAM_READY(z);
1623
1624 return obj;
1625}
1626
1627/*
1628 * Document-method: Zlib::Deflate#initialize_copy
1629 *
1630 * Duplicates the deflate stream.
1631 */
1632static VALUE
1633rb_deflate_init_copy(VALUE self, VALUE orig)
1634{
1635 struct zstream *z1, *z2;
1636 int err;
1637
1638 TypedData_Get_Struct(self, struct zstream, &zstream_data_type, z1);
1639 z2 = get_zstream(orig);
1640
1641 if (z1 == z2) return self;
1642 err = deflateCopy(&z1->stream, &z2->stream);
1643 if (err != Z_OK) {
1644 raise_zlib_error(err, 0);
1645 }
1646 z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
1647 z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf);
1648 z1->flags = z2->flags;
1649
1650 return self;
1651}
1652
1653static VALUE
1654deflate_run(VALUE args)
1655{
1656 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1657 VALUE src = ((VALUE*)args)[1];
1658
1659 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_FINISH);
1660 return zstream_detach_buffer(z);
1661}
1662
1663/*
1664 * Document-method: Zlib::Deflate.deflate
1665 *
1666 * call-seq:
1667 * Zlib.deflate(string[, level])
1668 * Zlib::Deflate.deflate(string[, level])
1669 *
1670 * Compresses the given +string+. Valid values of level are
1671 * Zlib::NO_COMPRESSION, Zlib::BEST_SPEED, Zlib::BEST_COMPRESSION,
1672 * Zlib::DEFAULT_COMPRESSION, or an integer from 0 to 9.
1673 *
1674 * This method is almost equivalent to the following code:
1675 *
1676 * def deflate(string, level)
1677 * z = Zlib::Deflate.new(level)
1678 * dst = z.deflate(string, Zlib::FINISH)
1679 * z.close
1680 * dst
1681 * end
1682 *
1683 * See also Zlib.inflate
1684 *
1685 */
1686static VALUE
1687rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
1688{
1689 struct zstream z;
1690 VALUE src, level, dst, args[2];
1691 int err, lev;
1692
1693 rb_scan_args(argc, argv, "11", &src, &level);
1694
1695 lev = ARG_LEVEL(level);
1698 err = deflateInit(&z.stream, lev);
1699 if (err != Z_OK) {
1700 raise_zlib_error(err, z.stream.msg);
1701 }
1702 ZSTREAM_READY(&z);
1703
1704 args[0] = (VALUE)&z;
1705 args[1] = src;
1706 dst = rb_ensure(deflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
1707
1708 return dst;
1709}
1710
1711static void
1712do_deflate(struct zstream *z, VALUE src, int flush)
1713{
1714 if (NIL_P(src)) {
1715 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
1716 return;
1717 }
1719 if (flush != Z_NO_FLUSH || RSTRING_LEN(src) > 0) { /* prevent BUF_ERROR */
1720 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), flush);
1721 }
1722}
1723
1724/*
1725 * Document-method: Zlib::Deflate#deflate
1726 *
1727 * call-seq:
1728 * z.deflate(string, flush = Zlib::NO_FLUSH) -> String
1729 * z.deflate(string, flush = Zlib::NO_FLUSH) { |chunk| ... } -> nil
1730 *
1731 * Inputs +string+ into the deflate stream and returns the output from the
1732 * stream. On calling this method, both the input and the output buffers of
1733 * the stream are flushed. If +string+ is nil, this method finishes the
1734 * stream, just like Zlib::ZStream#finish.
1735 *
1736 * If a block is given consecutive deflated chunks from the +string+ are
1737 * yielded to the block and +nil+ is returned.
1738 *
1739 * The +flush+ parameter specifies the flush mode. The following constants
1740 * may be used:
1741 *
1742 * Zlib::NO_FLUSH:: The default
1743 * Zlib::SYNC_FLUSH:: Flushes the output to a byte boundary
1744 * Zlib::FULL_FLUSH:: SYNC_FLUSH + resets the compression state
1745 * Zlib::FINISH:: Pending input is processed, pending output is flushed.
1746 *
1747 * See the constants for further description.
1748 *
1749 */
1750static VALUE
1751rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1752{
1753 struct zstream *z = get_zstream(obj);
1754 VALUE src, flush;
1755
1756 rb_scan_args(argc, argv, "11", &src, &flush);
1757 do_deflate(z, src, ARG_FLUSH(flush));
1758
1759 return zstream_detach_buffer(z);
1760}
1761
1762/*
1763 * Document-method: Zlib::Deflate#<<
1764 *
1765 * call-seq: << string
1766 *
1767 * Inputs +string+ into the deflate stream just like Zlib::Deflate#deflate, but
1768 * returns the Zlib::Deflate object itself. The output from the stream is
1769 * preserved in output buffer.
1770 */
1771static VALUE
1772rb_deflate_addstr(VALUE obj, VALUE src)
1773{
1774 do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
1775 return obj;
1776}
1777
1778/*
1779 * Document-method: Zlib::Deflate#flush
1780 *
1781 * call-seq:
1782 * flush(flush = Zlib::SYNC_FLUSH) -> String
1783 * flush(flush = Zlib::SYNC_FLUSH) { |chunk| ... } -> nil
1784 *
1785 * This method is equivalent to <tt>deflate('', flush)</tt>. This method is
1786 * just provided to improve the readability of your Ruby program. If a block
1787 * is given chunks of deflate output are yielded to the block until the buffer
1788 * is flushed.
1789 *
1790 * See Zlib::Deflate#deflate for detail on the +flush+ constants NO_FLUSH,
1791 * SYNC_FLUSH, FULL_FLUSH and FINISH.
1792 */
1793static VALUE
1794rb_deflate_flush(int argc, VALUE *argv, VALUE obj)
1795{
1796 struct zstream *z = get_zstream(obj);
1797 VALUE v_flush;
1798 int flush;
1799
1800 rb_scan_args(argc, argv, "01", &v_flush);
1801 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
1802 if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
1803 zstream_run(z, (Bytef*)"", 0, flush);
1804 }
1805
1806 return zstream_detach_buffer(z);
1807}
1808
1809/*
1810 * Document-method: Zlib::Deflate.params
1811 *
1812 * call-seq: params(level, strategy)
1813 *
1814 * Changes the parameters of the deflate stream to allow changes between
1815 * different types of data that require different types of compression. Any
1816 * unprocessed data is flushed before changing the params.
1817 *
1818 * See Zlib::Deflate.new for a description of +level+ and +strategy+.
1819 *
1820 */
1821static VALUE
1822rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
1823{
1824 struct zstream *z = get_zstream(obj);
1825 int level, strategy;
1826 int err;
1827 uInt n;
1828 long filled;
1829
1830 level = ARG_LEVEL(v_level);
1831 strategy = ARG_STRATEGY(v_strategy);
1832
1833 n = z->stream.avail_out;
1834 err = deflateParams(&z->stream, level, strategy);
1835 filled = n - z->stream.avail_out;
1836 while (err == Z_BUF_ERROR) {
1837 rb_warning("deflateParams() returned Z_BUF_ERROR");
1838 zstream_expand_buffer(z);
1839 rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
1840 n = z->stream.avail_out;
1841 err = deflateParams(&z->stream, level, strategy);
1842 filled = n - z->stream.avail_out;
1843 }
1844 if (err != Z_OK) {
1845 raise_zlib_error(err, z->stream.msg);
1846 }
1847 rb_str_set_len(z->buf, RSTRING_LEN(z->buf) + filled);
1848
1849 return Qnil;
1850}
1851
1852/*
1853 * Document-method: Zlib::Deflate.set_dictionary
1854 *
1855 * call-seq: set_dictionary(string)
1856 *
1857 * Sets the preset dictionary and returns +string+. This method is available
1858 * just only after Zlib::Deflate.new or Zlib::ZStream#reset method was called.
1859 * See zlib.h for details.
1860 *
1861 * Can raise errors of Z_STREAM_ERROR if a parameter is invalid (such as
1862 * NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if
1863 * the given dictionary doesn't match the expected one (incorrect adler32 value)
1864 *
1865 */
1866static VALUE
1867rb_deflate_set_dictionary(VALUE obj, VALUE dic)
1868{
1869 struct zstream *z = get_zstream(obj);
1870 VALUE src = dic;
1871 int err;
1872
1874 err = deflateSetDictionary(&z->stream,
1875 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
1876 if (err != Z_OK) {
1877 raise_zlib_error(err, z->stream.msg);
1878 }
1879
1880 return dic;
1881}
1882
1883
1884/* ------------------------------------------------------------------------- */
1885
1886/*
1887 * Document-class: Zlib::Inflate
1888 *
1889 * Zlib:Inflate is the class for decompressing compressed data. Unlike
1890 * Zlib::Deflate, an instance of this class is not able to duplicate (clone,
1891 * dup) itself.
1892 */
1893
1894static VALUE
1895rb_inflate_s_allocate(VALUE klass)
1896{
1897 VALUE inflate = zstream_inflate_new(klass);
1898 rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
1899 return inflate;
1900}
1901
1902/*
1903 * Document-method: Zlib::Inflate.new
1904 *
1905 * call-seq:
1906 * Zlib::Inflate.new(window_bits = Zlib::MAX_WBITS)
1907 *
1908 * Creates a new inflate stream for decompression. +window_bits+ sets the
1909 * size of the history buffer and can have the following values:
1910 *
1911 * 0::
1912 * Have inflate use the window size from the zlib header of the compressed
1913 * stream.
1914 *
1915 * (8..15)::
1916 * Overrides the window size of the inflate header in the compressed stream.
1917 * The window size must be greater than or equal to the window size of the
1918 * compressed stream.
1919 *
1920 * Greater than 15::
1921 * Add 32 to window_bits to enable zlib and gzip decoding with automatic
1922 * header detection, or add 16 to decode only the gzip format (a
1923 * Zlib::DataError will be raised for a non-gzip stream).
1924 *
1925 * (-8..-15)::
1926 * Enables raw deflate mode which will not generate a check value, and will
1927 * not look for any check values for comparison at the end of the stream.
1928 *
1929 * This is for use with other formats that use the deflate compressed data
1930 * format such as zip which provide their own check values.
1931 *
1932 * == Example
1933 *
1934 * open "compressed.file" do |compressed_io|
1935 * zi = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
1936 *
1937 * begin
1938 * open "uncompressed.file", "w+" do |uncompressed_io|
1939 * uncompressed_io << zi.inflate(compressed_io.read)
1940 * end
1941 * ensure
1942 * zi.close
1943 * end
1944 * end
1945 *
1946 */
1947static VALUE
1948rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
1949{
1950 struct zstream *z;
1951 VALUE wbits;
1952 int err;
1953
1954 rb_scan_args(argc, argv, "01", &wbits);
1955 TypedData_Get_Struct(obj, struct zstream, &zstream_data_type, z);
1956
1957 err = inflateInit2(&z->stream, ARG_WBITS(wbits));
1958 if (err != Z_OK) {
1959 raise_zlib_error(err, z->stream.msg);
1960 }
1961 ZSTREAM_READY(z);
1962
1963 return obj;
1964}
1965
1966static VALUE
1967inflate_run(VALUE args)
1968{
1969 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
1970 VALUE src = ((VALUE*)args)[1];
1971
1972 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
1973 zstream_run(z, (Bytef*)"", 0, Z_FINISH); /* for checking errors */
1974 return zstream_detach_buffer(z);
1975}
1976
1977/*
1978 * Document-method: Zlib::inflate
1979 *
1980 * call-seq:
1981 * Zlib.inflate(string)
1982 * Zlib::Inflate.inflate(string)
1983 *
1984 * Decompresses +string+. Raises a Zlib::NeedDict exception if a preset
1985 * dictionary is needed for decompression.
1986 *
1987 * This method is almost equivalent to the following code:
1988 *
1989 * def inflate(string)
1990 * zstream = Zlib::Inflate.new
1991 * buf = zstream.inflate(string)
1992 * zstream.finish
1993 * zstream.close
1994 * buf
1995 * end
1996 *
1997 * See also Zlib.deflate
1998 *
1999 */
2000static VALUE
2001rb_inflate_s_inflate(VALUE obj, VALUE src)
2002{
2003 struct zstream z;
2004 VALUE dst, args[2];
2005 int err;
2006
2009 err = inflateInit(&z.stream);
2010 if (err != Z_OK) {
2011 raise_zlib_error(err, z.stream.msg);
2012 }
2013 ZSTREAM_READY(&z);
2014
2015 args[0] = (VALUE)&z;
2016 args[1] = src;
2017 dst = rb_ensure(inflate_run, (VALUE)args, zstream_ensure_end, (VALUE)&z);
2018
2019 return dst;
2020}
2021
2022static void
2023do_inflate(struct zstream *z, VALUE src)
2024{
2025 if (NIL_P(src)) {
2026 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
2027 return;
2028 }
2030 if (RSTRING_LEN(src) > 0 || z->stream.avail_in > 0) { /* prevent Z_BUF_ERROR */
2031 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
2032 }
2033}
2034
2035/* Document-method: Zlib::Inflate#add_dictionary
2036 *
2037 * call-seq: add_dictionary(string)
2038 *
2039 * Provide the inflate stream with a dictionary that may be required in the
2040 * future. Multiple dictionaries may be provided. The inflate stream will
2041 * automatically choose the correct user-provided dictionary based on the
2042 * stream's required dictionary.
2043 */
2044static VALUE
2045rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
2046{
2047 VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
2048 VALUE checksum = do_checksum(1, &dictionary, adler32);
2049
2050 rb_hash_aset(dictionaries, checksum, dictionary);
2051
2052 return obj;
2053}
2054
2055/*
2056 * Document-method: Zlib::Inflate#inflate
2057 *
2058 * call-seq:
2059 * inflate(deflate_string) -> String
2060 * inflate(deflate_string) { |chunk| ... } -> nil
2061 *
2062 * Inputs +deflate_string+ into the inflate stream and returns the output from
2063 * the stream. Calling this method, both the input and the output buffer of
2064 * the stream are flushed. If string is +nil+, this method finishes the
2065 * stream, just like Zlib::ZStream#finish.
2066 *
2067 * If a block is given consecutive inflated chunks from the +deflate_string+
2068 * are yielded to the block and +nil+ is returned.
2069 *
2070 * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
2071 * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
2072 * call this method again with an empty string to flush the stream:
2073 *
2074 * inflater = Zlib::Inflate.new
2075 *
2076 * begin
2077 * out = inflater.inflate compressed
2078 * rescue Zlib::NeedDict
2079 * # ensure the dictionary matches the stream's required dictionary
2080 * raise unless inflater.adler == Zlib.adler32(dictionary)
2081 *
2082 * inflater.set_dictionary dictionary
2083 * inflater.inflate ''
2084 * end
2085 *
2086 * # ...
2087 *
2088 * inflater.close
2089 *
2090 * See also Zlib::Inflate.new
2091 */
2092static VALUE
2093rb_inflate_inflate(VALUE obj, VALUE src)
2094{
2095 struct zstream *z = get_zstream(obj);
2096 VALUE dst;
2097
2098 if (ZSTREAM_IS_FINISHED(z)) {
2099 if (NIL_P(src)) {
2100 dst = zstream_detach_buffer(z);
2101 }
2102 else {
2105 dst = rb_str_new(0, 0);
2106 }
2107 }
2108 else {
2109 do_inflate(z, src);
2110 dst = zstream_detach_buffer(z);
2111 if (ZSTREAM_IS_FINISHED(z)) {
2112 zstream_passthrough_input(z);
2113 }
2114 }
2115
2116 return dst;
2117}
2118
2119/*
2120 * call-seq: << string
2121 *
2122 * Inputs +string+ into the inflate stream just like Zlib::Inflate#inflate, but
2123 * returns the Zlib::Inflate object itself. The output from the stream is
2124 * preserved in output buffer.
2125 */
2126static VALUE
2127rb_inflate_addstr(VALUE obj, VALUE src)
2128{
2129 struct zstream *z = get_zstream(obj);
2130
2131 if (ZSTREAM_IS_FINISHED(z)) {
2132 if (!NIL_P(src)) {
2135 }
2136 }
2137 else {
2138 do_inflate(z, src);
2139 if (ZSTREAM_IS_FINISHED(z)) {
2140 zstream_passthrough_input(z);
2141 }
2142 }
2143
2144 return obj;
2145}
2146
2147/*
2148 * call-seq: sync(string)
2149 *
2150 * Inputs +string+ into the end of input buffer and skips data until a full
2151 * flush point can be found. If the point is found in the buffer, this method
2152 * flushes the buffer and returns false. Otherwise it returns +true+ and the
2153 * following data of full flush point is preserved in the buffer.
2154 */
2155static VALUE
2156rb_inflate_sync(VALUE obj, VALUE src)
2157{
2158 struct zstream *z = get_zstream(obj);
2159
2161 return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
2162}
2163
2164/*
2165 * Quoted verbatim from original documentation:
2166 *
2167 * What is this?
2168 *
2169 * <tt>:)</tt>
2170 */
2171static VALUE
2172rb_inflate_sync_point_p(VALUE obj)
2173{
2174 struct zstream *z = get_zstream(obj);
2175 int err;
2176
2177 err = inflateSyncPoint(&z->stream);
2178 if (err == 1) {
2179 return Qtrue;
2180 }
2181 if (err != Z_OK) {
2182 raise_zlib_error(err, z->stream.msg);
2183 }
2184 return Qfalse;
2185}
2186
2187/*
2188 * Document-method: Zlib::Inflate#set_dictionary
2189 *
2190 * Sets the preset dictionary and returns +string+. This method is available just
2191 * only after a Zlib::NeedDict exception was raised. See zlib.h for details.
2192 *
2193 */
2194static VALUE
2195rb_inflate_set_dictionary(VALUE obj, VALUE dic)
2196{
2197 struct zstream *z = get_zstream(obj);
2198 VALUE src = dic;
2199 int err;
2200
2202 err = inflateSetDictionary(&z->stream,
2203 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
2204 if (err != Z_OK) {
2205 raise_zlib_error(err, z->stream.msg);
2206 }
2207
2208 return dic;
2209}
2210
2211
2212
2213#if GZIP_SUPPORT
2214
2215/* NOTE: Features for gzip files of Ruby/zlib are written from scratch
2216 * and using undocumented feature of zlib, negative wbits.
2217 * I don't think gzFile APIs of zlib are good for Ruby.
2218 */
2219
2220/*------- .gz file header --------*/
2222#define GZ_MAGIC1 0x1f
2223#define GZ_MAGIC2 0x8b
2224#define GZ_METHOD_DEFLATE 8
2225#define GZ_FLAG_MULTIPART 0x2
2226#define GZ_FLAG_EXTRA 0x4
2227#define GZ_FLAG_ORIG_NAME 0x8
2228#define GZ_FLAG_COMMENT 0x10
2229#define GZ_FLAG_ENCRYPT 0x20
2230#define GZ_FLAG_UNKNOWN_MASK 0xc0
2232#define GZ_EXTRAFLAG_FAST 0x4
2233#define GZ_EXTRAFLAG_SLOW 0x2
2234
2235/* from zutil.h */
2236#define OS_MSDOS 0x00
2237#define OS_AMIGA 0x01
2238#define OS_VMS 0x02
2239#define OS_UNIX 0x03
2240#define OS_ATARI 0x05
2241#define OS_OS2 0x06
2242#define OS_MACOS 0x07
2243#define OS_TOPS20 0x0a
2244#define OS_WIN32 0x0b
2246#define OS_VMCMS 0x04
2247#define OS_ZSYSTEM 0x08
2248#define OS_CPM 0x09
2249#define OS_QDOS 0x0c
2250#define OS_RISCOS 0x0d
2251#define OS_UNKNOWN 0xff
2252
2253#ifndef OS_CODE
2254#define OS_CODE OS_UNIX
2255#endif
2256
2257static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
2258static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
2259
2260
2261
2262/*-------- gzfile internal APIs --------*/
2264struct gzfile {
2265 struct zstream z;
2268 int os_code; /* for header */
2269 time_t mtime; /* for header */
2270 VALUE orig_name; /* for header; must be a String */
2271 VALUE comment; /* for header; must be a String */
2272 unsigned long crc;
2276 void (*end)(struct gzfile *);
2281 VALUE path;
2283#define GZFILE_CBUF_CAPA 10
2285#define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
2286#define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
2287#define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
2288#define GZFILE_FLAG_MTIME_IS_SET (ZSTREAM_FLAG_UNUSED << 3)
2290#define GZFILE_IS_FINISHED(gz) \
2291 (ZSTREAM_IS_FINISHED(&(gz)->z) && ZSTREAM_BUF_FILLED(&(gz)->z) == 0)
2293#define GZFILE_READ_SIZE 2048
2296 VALUE io;
2297 union {
2298 const VALUE argv[2]; /* for rb_funcallv */
2299 struct {
2303 } as;
2304};
2305
2306static void
2307gzfile_mark(void *p)
2308{
2309 struct gzfile *gz = p;
2310
2311 rb_gc_mark(gz->io);
2312 rb_gc_mark(gz->orig_name);
2313 rb_gc_mark(gz->comment);
2314 zstream_mark(&gz->z);
2315 rb_gc_mark(gz->ecopts);
2316 rb_gc_mark(gz->path);
2317}
2318
2319static void
2320gzfile_free(void *p)
2321{
2322 struct gzfile *gz = p;
2323 struct zstream *z = &gz->z;
2324
2325 if (ZSTREAM_IS_READY(z)) {
2326 if (z->func == &deflate_funcs) {
2327 finalizer_warn("Zlib::GzipWriter object must be closed explicitly.");
2328 }
2329 zstream_finalize(z);
2330 }
2331 xfree(gz);
2332}
2333
2334static size_t
2335gzfile_memsize(const void *p)
2336{
2337 return sizeof(struct gzfile);
2338}
2339
2340static const rb_data_type_t gzfile_data_type = {
2341 "gzfile",
2342 { gzfile_mark, gzfile_free, gzfile_memsize, },
2344};
2345
2346static void
2347gzfile_init(struct gzfile *gz, const struct zstream_funcs *funcs, void (*endfunc)(struct gzfile *))
2348{
2349 zstream_init(&gz->z, funcs);
2351 gz->io = Qnil;
2352 gz->level = 0;
2353 gz->mtime = 0;
2354 gz->os_code = OS_CODE;
2355 gz->orig_name = Qnil;
2356 gz->comment = Qnil;
2357 gz->crc = crc32(0, Z_NULL, 0);
2358 gz->lineno = 0;
2359 gz->ungetc = 0;
2360 gz->end = endfunc;
2362 gz->enc2 = 0;
2363 gz->ec = NULL;
2364 gz->ecflags = 0;
2365 gz->ecopts = Qnil;
2366 gz->path = Qnil;
2367}
2368
2369static VALUE
2370gzfile_new(VALUE klass, const struct zstream_funcs *funcs, void (*endfunc)(struct gzfile *))
2371{
2372 VALUE obj;
2373 struct gzfile *gz;
2374
2375 obj = TypedData_Make_Struct(klass, struct gzfile, &gzfile_data_type, gz);
2376 gzfile_init(gz, funcs, endfunc);
2377 return obj;
2378}
2380#define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
2381#define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
2382
2383static void
2384gzfile_reset(struct gzfile *gz)
2385{
2386 zstream_reset(&gz->z);
2388 gz->crc = crc32(0, Z_NULL, 0);
2389 gz->lineno = 0;
2390 gz->ungetc = 0;
2391 if (gz->ec) {
2392 rb_econv_close(gz->ec);
2393 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
2394 gz->ecflags, gz->ecopts);
2395 }
2396}
2397
2398static void
2399gzfile_close(struct gzfile *gz, int closeflag)
2400{
2401 VALUE io = gz->io;
2402
2403 gz->end(gz);
2404 gz->io = Qnil;
2405 gz->orig_name = Qnil;
2406 gz->comment = Qnil;
2407 if (closeflag && rb_respond_to(io, id_close)) {
2408 rb_funcall(io, id_close, 0);
2409 }
2410}
2411
2412static void
2413gzfile_write_raw(struct gzfile *gz)
2414{
2415 VALUE str;
2416
2417 if (ZSTREAM_BUF_FILLED(&gz->z) > 0) {
2418 str = zstream_detach_buffer(&gz->z);
2419 rb_funcall(gz->io, id_write, 1, str);
2420 if ((gz->z.flags & GZFILE_FLAG_SYNC)
2421 && rb_respond_to(gz->io, id_flush))
2422 rb_funcall(gz->io, id_flush, 0);
2423 }
2424}
2425
2426static VALUE
2427gzfile_read_raw_partial(VALUE arg)
2428{
2429 struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2430 VALUE str;
2431 int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2432
2433 str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
2435 return str;
2436}
2437
2438static VALUE
2439gzfile_read_raw_rescue(VALUE arg, VALUE _)
2440{
2441 struct read_raw_arg *ra = (struct read_raw_arg *)arg;
2442 VALUE str = Qnil;
2444 int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
2445 str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
2446 if (!NIL_P(str)) {
2448 }
2449 }
2450 return str; /* return nil when EOFError */
2451}
2452
2453static VALUE
2454gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
2455{
2456 struct read_raw_arg ra;
2457
2458 ra.io = gz->io;
2460 ra.as.in.buf = outbuf;
2461
2462 return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
2463 gzfile_read_raw_rescue, (VALUE)&ra,
2465}
2466
2467static int
2468gzfile_read_raw_ensure(struct gzfile *gz, long size, VALUE outbuf)
2469{
2470 VALUE str;
2471
2472 if (gz->io == Qundef) { /* Zlib.gunzip */
2473 if (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size)
2474 rb_raise(cGzError, "unexpected end of string");
2475 }
2476 while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
2477 str = gzfile_read_raw(gz, outbuf);
2478 if (NIL_P(str)) return 0;
2480 }
2481 return 1;
2482}
2483
2484static char *
2485gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
2486{
2487 VALUE str;
2488 char *p;
2489
2490 for (;;) {
2491 p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
2492 RSTRING_LEN(gz->z.input) - offset);
2493 if (p) break;
2494 str = gzfile_read_raw(gz, Qnil);
2495 if (NIL_P(str)) {
2496 rb_raise(cGzError, "unexpected end of file");
2497 }
2498 offset = RSTRING_LEN(gz->z.input);
2500 }
2501 return p;
2502}
2503
2504static unsigned int
2505gzfile_get16(const unsigned char *src)
2506{
2507 unsigned int n;
2508 n = *(src++) & 0xff;
2509 n |= (*(src++) & 0xff) << 8;
2510 return n;
2511}
2512
2513static unsigned long
2514gzfile_get32(const unsigned char *src)
2515{
2516 unsigned long n;
2517 n = *(src++) & 0xff;
2518 n |= (*(src++) & 0xff) << 8;
2519 n |= (*(src++) & 0xff) << 16;
2520 n |= (*(src++) & 0xffU) << 24;
2521 return n;
2522}
2523
2524static void
2525gzfile_set32(unsigned long n, unsigned char *dst)
2526{
2527 *(dst++) = n & 0xff;
2528 *(dst++) = (n >> 8) & 0xff;
2529 *(dst++) = (n >> 16) & 0xff;
2530 *dst = (n >> 24) & 0xff;
2531}
2532
2533static void
2534gzfile_raise(struct gzfile *gz, VALUE klass, const char *message)
2535{
2536 VALUE exc = rb_exc_new2(klass, message);
2537 if (!NIL_P(gz->z.input)) {
2538 rb_ivar_set(exc, id_input, rb_str_resurrect(gz->z.input));
2539 }
2541}
2542
2543/*
2544 * Document-method: Zlib::GzipFile::Error#inspect
2545 *
2546 * Constructs a String of the GzipFile Error
2547 */
2548static VALUE
2549gzfile_error_inspect(VALUE error)
2550{
2551 VALUE str = rb_call_super(0, 0);
2552 VALUE input = rb_attr_get(error, id_input);
2553
2554 if (!NIL_P(input)) {
2556 rb_str_cat2(str, ", input=");
2558 rb_str_cat2(str, ">");
2559 }
2560 return str;
2561}
2562
2563static void
2564gzfile_make_header(struct gzfile *gz)
2565{
2566 Bytef buf[10]; /* the size of gzip header */
2567 unsigned char flags = 0, extraflags = 0;
2568
2569 if (!NIL_P(gz->orig_name)) {
2570 flags |= GZ_FLAG_ORIG_NAME;
2571 }
2572 if (!NIL_P(gz->comment)) {
2573 flags |= GZ_FLAG_COMMENT;
2574 }
2575 if (!(gz->z.flags & GZFILE_FLAG_MTIME_IS_SET)) {
2576 gz->mtime = time(0);
2577 }
2578
2579 if (gz->level == Z_BEST_SPEED) {
2580 extraflags |= GZ_EXTRAFLAG_FAST;
2581 }
2582 else if (gz->level == Z_BEST_COMPRESSION) {
2583 extraflags |= GZ_EXTRAFLAG_SLOW;
2584 }
2585
2586 buf[0] = GZ_MAGIC1;
2587 buf[1] = GZ_MAGIC2;
2589 buf[3] = flags;
2590 gzfile_set32((unsigned long)gz->mtime, &buf[4]);
2591 buf[8] = extraflags;
2592 buf[9] = gz->os_code;
2593 zstream_append_buffer(&gz->z, buf, (long)sizeof(buf));
2594
2595 if (!NIL_P(gz->orig_name)) {
2597 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2598 }
2599 if (!NIL_P(gz->comment)) {
2600 zstream_append_buffer2(&gz->z, gz->comment);
2601 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
2602 }
2603
2605}
2606
2607static void
2608gzfile_make_footer(struct gzfile *gz)
2609{
2610 Bytef buf[8]; /* 8 is the size of gzip footer */
2611
2612 gzfile_set32(gz->crc, buf);
2613 gzfile_set32(gz->z.stream.total_in, &buf[4]);
2614 zstream_append_buffer(&gz->z, buf, (long)sizeof(buf));
2616}
2617
2618static void
2619gzfile_read_header(struct gzfile *gz, VALUE outbuf)
2620{
2621 const unsigned char *head;
2622 long len;
2623 char flags, *p;
2624
2625 /* 10 is the size of gzip header */
2626 if (!gzfile_read_raw_ensure(gz, 10, outbuf)) {
2627 gzfile_raise(gz, cGzError, "not in gzip format");
2628 }
2629
2630 head = (unsigned char*)RSTRING_PTR(gz->z.input);
2631
2632 if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
2633 gzfile_raise(gz, cGzError, "not in gzip format");
2634 }
2635 if (head[2] != GZ_METHOD_DEFLATE) {
2636 rb_raise(cGzError, "unsupported compression method %d", head[2]);
2637 }
2638
2639 flags = head[3];
2640 if (flags & GZ_FLAG_MULTIPART) {
2641 rb_raise(cGzError, "multi-part gzip file is not supported");
2642 }
2643 else if (flags & GZ_FLAG_ENCRYPT) {
2644 rb_raise(cGzError, "encrypted gzip file is not supported");
2645 }
2646 else if (flags & GZ_FLAG_UNKNOWN_MASK) {
2647 rb_raise(cGzError, "unknown flags 0x%02x", flags);
2648 }
2649
2650 if (head[8] & GZ_EXTRAFLAG_FAST) {
2651 gz->level = Z_BEST_SPEED;
2652 }
2653 else if (head[8] & GZ_EXTRAFLAG_SLOW) {
2654 gz->level = Z_BEST_COMPRESSION;
2655 }
2656 else {
2657 gz->level = Z_DEFAULT_COMPRESSION;
2658 }
2659
2660 gz->mtime = gzfile_get32(&head[4]);
2661 gz->os_code = head[9];
2662 zstream_discard_input(&gz->z, 10);
2663
2664 if (flags & GZ_FLAG_EXTRA) {
2665 if (!gzfile_read_raw_ensure(gz, 2, outbuf)) {
2666 rb_raise(cGzError, "unexpected end of file");
2667 }
2668 len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
2669 if (!gzfile_read_raw_ensure(gz, 2 + len, outbuf)) {
2670 rb_raise(cGzError, "unexpected end of file");
2671 }
2672 zstream_discard_input(&gz->z, 2 + len);
2673 }
2674 if (flags & GZ_FLAG_ORIG_NAME) {
2675 if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2676 rb_raise(cGzError, "unexpected end of file");
2677 }
2678 p = gzfile_read_raw_until_zero(gz, 0);
2679 len = p - RSTRING_PTR(gz->z.input);
2681 zstream_discard_input(&gz->z, len + 1);
2682 }
2683 if (flags & GZ_FLAG_COMMENT) {
2684 if (!gzfile_read_raw_ensure(gz, 1, outbuf)) {
2685 rb_raise(cGzError, "unexpected end of file");
2686 }
2687 p = gzfile_read_raw_until_zero(gz, 0);
2688 len = p - RSTRING_PTR(gz->z.input);
2689 gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
2690 zstream_discard_input(&gz->z, len + 1);
2691 }
2692
2693 if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) {
2694 zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
2695 }
2696}
2697
2698static void
2699gzfile_check_footer(struct gzfile *gz, VALUE outbuf)
2700{
2701 unsigned long crc, length;
2702
2704
2705 /* 8 is the size of gzip footer */
2706 if (!gzfile_read_raw_ensure(gz, 8, outbuf)) {
2707 gzfile_raise(gz, cNoFooter, "footer is not found");
2708 }
2709
2710 crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input));
2711 length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4);
2712
2713 gz->z.stream.total_in += 8; /* to rewind correctly */
2714 zstream_discard_input(&gz->z, 8);
2715
2716 if (gz->crc != crc) {
2717 rb_raise(cCRCError, "invalid compressed data -- crc error");
2718 }
2719 if ((uint32_t)gz->z.stream.total_out != length) {
2720 rb_raise(cLengthError, "invalid compressed data -- length error");
2721 }
2722}
2723
2724static void
2725gzfile_write(struct gzfile *gz, Bytef *str, long len)
2726{
2727 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2728 gzfile_make_header(gz);
2729 }
2730
2731 if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
2732 gz->crc = checksum_long(crc32, gz->crc, str, len);
2733 zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
2734 ? Z_SYNC_FLUSH : Z_NO_FLUSH);
2735 }
2736 gzfile_write_raw(gz);
2737}
2738
2739static long
2740gzfile_read_more(struct gzfile *gz, VALUE outbuf)
2741{
2742 VALUE str;
2743
2744 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2745 str = gzfile_read_raw(gz, outbuf);
2746 if (NIL_P(str)) {
2747 if (!ZSTREAM_IS_FINISHED(&gz->z)) {
2748 rb_raise(cGzError, "unexpected end of file");
2749 }
2750 break;
2751 }
2752 if (RSTRING_LEN(str) > 0) { /* prevent Z_BUF_ERROR */
2753 zstream_run(&gz->z, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str),
2754 Z_SYNC_FLUSH);
2756 }
2757 if (ZSTREAM_BUF_FILLED(&gz->z) > 0) break;
2758 }
2759 return ZSTREAM_BUF_FILLED(&gz->z);
2760}
2761
2762static void
2763gzfile_calc_crc(struct gzfile *gz, VALUE str)
2764{
2765 if (RSTRING_LEN(str) <= gz->ungetc) {
2766 gz->ungetc -= RSTRING_LEN(str);
2767 }
2768 else {
2769 gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
2770 RSTRING_LEN(str) - gz->ungetc);
2771 gz->ungetc = 0;
2772 }
2773}
2774
2775static VALUE
2776gzfile_newstr(struct gzfile *gz, VALUE str)
2777{
2778 if (!gz->enc2) {
2779 rb_enc_associate(str, gz->enc);
2780 return str;
2781 }
2782 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2784 rb_enc_associate(str, gz->enc);
2785 return str;
2786 }
2787 return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
2788 gz->ecflags, gz->ecopts);
2789}
2790
2791static long
2792gzfile_fill(struct gzfile *gz, long len)
2793{
2794 if (len < 0)
2795 rb_raise(rb_eArgError, "negative length %ld given", len);
2796 if (len == 0)
2797 return 0;
2798 while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2799 gzfile_read_more(gz, Qnil);
2800 }
2801 if (GZFILE_IS_FINISHED(gz)) {
2802 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2803 gzfile_check_footer(gz, Qnil);
2804 }
2805 return -1;
2806 }
2807 return len < ZSTREAM_BUF_FILLED(&gz->z) ? len : ZSTREAM_BUF_FILLED(&gz->z);
2808}
2809
2810static VALUE
2811gzfile_read(struct gzfile *gz, long len)
2812{
2813 VALUE dst;
2814
2815 len = gzfile_fill(gz, len);
2816 if (len == 0) return rb_str_new(0, 0);
2817 if (len < 0) return Qnil;
2818 dst = zstream_shift_buffer(&gz->z, len);
2819 if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
2820 return dst;
2821}
2822
2823static VALUE
2824gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
2825{
2826 VALUE dst;
2827
2828 if (len < 0)
2829 rb_raise(rb_eArgError, "negative length %ld given", len);
2830
2831 if (len == 0) {
2832 if (NIL_P(outbuf))
2833 return rb_str_new(0, 0);
2834 else {
2835 rb_str_resize(outbuf, 0);
2836 return outbuf;
2837 }
2838 }
2839 while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
2840 gzfile_read_more(gz, outbuf);
2841 }
2842 if (GZFILE_IS_FINISHED(gz)) {
2843 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2844 gzfile_check_footer(gz, outbuf);
2845 }
2846 if (!NIL_P(outbuf))
2847 rb_str_resize(outbuf, 0);
2848 rb_raise(rb_eEOFError, "end of file reached");
2849 }
2850
2851 dst = zstream_shift_buffer(&gz->z, len);
2852 gzfile_calc_crc(gz, dst);
2853
2854 if (!NIL_P(outbuf)) {
2855 rb_str_resize(outbuf, RSTRING_LEN(dst));
2856 memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
2857 rb_str_resize(dst, 0);
2859 dst = outbuf;
2860 }
2861 return dst;
2862}
2863
2864static VALUE
2865gzfile_read_all(struct gzfile *gz)
2866{
2867 VALUE dst;
2868
2869 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
2870 gzfile_read_more(gz, Qnil);
2871 }
2872 if (GZFILE_IS_FINISHED(gz)) {
2873 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2874 gzfile_check_footer(gz, Qnil);
2875 }
2876 return rb_str_new(0, 0);
2877 }
2878
2879 dst = zstream_detach_buffer(&gz->z);
2880 if (NIL_P(dst)) return dst;
2881 gzfile_calc_crc(gz, dst);
2882 return gzfile_newstr(gz, dst);
2883}
2884
2885static VALUE
2886gzfile_getc(struct gzfile *gz)
2887{
2888 VALUE buf, dst = 0;
2889 int len;
2890
2891 len = rb_enc_mbmaxlen(gz->enc);
2892 while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
2893 gzfile_read_more(gz, Qnil);
2894 }
2895 if (GZFILE_IS_FINISHED(gz)) {
2896 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2897 gzfile_check_footer(gz, Qnil);
2898 }
2899 return Qnil;
2900 }
2901
2902 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
2903 const unsigned char *ss, *sp, *se;
2904 unsigned char *ds, *dp, *de;
2905 VALUE cbuf = rb_enc_str_new(0, GZFILE_CBUF_CAPA, gz->enc);
2906
2907 ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
2908 se = sp + ZSTREAM_BUF_FILLED(&gz->z);
2909 ds = dp = (unsigned char *)RSTRING_PTR(cbuf);
2910 de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
2913 dst = zstream_shift_buffer(&gz->z, sp - ss);
2914 gzfile_calc_crc(gz, dst);
2915 rb_str_resize(cbuf, dp - ds);
2916 return cbuf;
2917 }
2918 else {
2919 buf = gz->z.buf;
2921 dst = gzfile_read(gz, len);
2922 if (NIL_P(dst)) return dst;
2923 return gzfile_newstr(gz, dst);
2924 }
2925}
2926
2927static void
2928gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
2929{
2930 zstream_buffer_ungets(&gz->z, b, len);
2931 gz->ungetc+=len;
2932}
2933
2934static void
2935gzfile_ungetbyte(struct gzfile *gz, int c)
2936{
2937 zstream_buffer_ungetbyte(&gz->z, c);
2938 gz->ungetc++;
2939}
2940
2941static VALUE
2942gzfile_writer_end_run(VALUE arg)
2943{
2944 struct gzfile *gz = (struct gzfile *)arg;
2945
2946 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
2947 gzfile_make_header(gz);
2948 }
2949
2950 zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
2951 gzfile_make_footer(gz);
2952 gzfile_write_raw(gz);
2953
2954 return Qnil;
2955}
2956
2957static void
2958gzfile_writer_end(struct gzfile *gz)
2959{
2960 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2962
2963 rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2964}
2965
2966static VALUE
2967gzfile_reader_end_run(VALUE arg)
2968{
2969 struct gzfile *gz = (struct gzfile *)arg;
2970
2971 if (GZFILE_IS_FINISHED(gz)
2972 && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
2973 gzfile_check_footer(gz, Qnil);
2974 }
2975
2976 return Qnil;
2977}
2978
2979static void
2980gzfile_reader_end(struct gzfile *gz)
2981{
2982 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
2984
2985 rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_ensure_end, (VALUE)&gz->z);
2986}
2987
2988static void
2989gzfile_reader_rewind(struct gzfile *gz)
2990{
2991 long n;
2992
2993 n = gz->z.stream.total_in;
2994 if (!NIL_P(gz->z.input)) {
2995 n += RSTRING_LEN(gz->z.input);
2996 }
2997
2998 rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
2999 gzfile_reset(gz);
3000}
3001
3002static VALUE
3003gzfile_reader_get_unused(struct gzfile *gz)
3004{
3005 VALUE str;
3006
3007 if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
3008 if (!GZFILE_IS_FINISHED(gz)) return Qnil;
3009 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
3010 gzfile_check_footer(gz, Qnil);
3011 }
3012 if (NIL_P(gz->z.input)) return Qnil;
3013
3014 str = rb_str_resurrect(gz->z.input);
3015 return str;
3016}
3017
3018static struct gzfile *
3019get_gzfile(VALUE obj)
3020{
3021 struct gzfile *gz;
3022
3023 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3024 if (!ZSTREAM_IS_READY(&gz->z)) {
3025 rb_raise(cGzError, "closed gzip stream");
3026 }
3027 return gz;
3028}
3029
3030
3031/* ------------------------------------------------------------------------- */
3032
3033/*
3034 * Document-class: Zlib::GzipFile
3035 *
3036 * Zlib::GzipFile is an abstract class for handling a gzip formatted
3037 * compressed file. The operations are defined in the subclasses,
3038 * Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
3039 *
3040 * GzipReader should be used by associating an IO, or IO-like, object.
3041 *
3042 * == Method Catalogue
3043 *
3044 * - ::wrap
3045 * - ::open (Zlib::GzipReader::open and Zlib::GzipWriter::open)
3046 * - #close
3047 * - #closed?
3048 * - #comment
3049 * - comment= (Zlib::GzipWriter#comment=)
3050 * - #crc
3051 * - eof? (Zlib::GzipReader#eof?)
3052 * - #finish
3053 * - #level
3054 * - lineno (Zlib::GzipReader#lineno)
3055 * - lineno= (Zlib::GzipReader#lineno=)
3056 * - #mtime
3057 * - mtime= (Zlib::GzipWriter#mtime=)
3058 * - #orig_name
3059 * - orig_name (Zlib::GzipWriter#orig_name=)
3060 * - #os_code
3061 * - path (when the underlying IO supports #path)
3062 * - #sync
3063 * - #sync=
3064 * - #to_io
3065 *
3066 * (due to internal structure, documentation may appear under Zlib::GzipReader
3067 * or Zlib::GzipWriter)
3068 */
3069
3071typedef struct {
3072 int argc;
3074 VALUE klass;
3076
3077static VALUE
3078new_wrap(VALUE tmp)
3079{
3081 return rb_class_new_instance_kw(arg->argc, arg->argv, arg->klass, RB_PASS_CALLED_KEYWORDS);
3082}
3083
3084static VALUE
3085gzfile_ensure_close(VALUE obj)
3086{
3087 struct gzfile *gz;
3088
3089 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3090 if (ZSTREAM_IS_READY(&gz->z)) {
3091 gzfile_close(gz, 1);
3092 }
3093 return Qnil;
3094}
3095
3096static VALUE
3097gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
3098{
3099 VALUE obj;
3100
3101 if (close_io_on_error) {
3102 int state = 0;
3104 arg.argc = argc;
3105 arg.argv = argv;
3106 arg.klass = klass;
3107 obj = rb_protect(new_wrap, (VALUE)&arg, &state);
3108 if (state) {
3109 rb_io_close(argv[0]);
3110 rb_jump_tag(state);
3111 }
3112 }
3113 else {
3115 }
3116
3117 if (rb_block_given_p()) {
3118 return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
3119 }
3120 else {
3121 return obj;
3122 }
3123}
3124
3125/*
3126 * Document-method: Zlib::GzipFile.wrap
3127 *
3128 * call-seq:
3129 * Zlib::GzipReader.wrap(io, ...) { |gz| ... }
3130 * Zlib::GzipWriter.wrap(io, ...) { |gz| ... }
3131 *
3132 * Creates a GzipReader or GzipWriter associated with +io+, passing in any
3133 * necessary extra options, and executes the block with the newly created
3134 * object just like File.open.
3135 *
3136 * The GzipFile object will be closed automatically after executing the block.
3137 * If you want to keep the associated IO object open, you may call
3138 * Zlib::GzipFile#finish method in the block.
3139 */
3140static VALUE
3141rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
3142{
3143 return gzfile_wrap(argc, argv, klass, 0);
3144}
3145
3146/*
3147 * Document-method: Zlib::GzipFile.open
3148 *
3149 * See Zlib::GzipReader#open and Zlib::GzipWriter#open.
3150 */
3151static VALUE
3152gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
3153{
3154 VALUE io, filename;
3155
3157 filename = argv[0];
3158 io = rb_file_open_str(filename, mode);
3159 argv[0] = io;
3160 return gzfile_wrap(argc, argv, klass, 1);
3161}
3162
3163/*
3164 * Document-method: Zlib::GzipFile#to_io
3165 *
3166 * Same as IO.
3167 */
3168static VALUE
3169rb_gzfile_to_io(VALUE obj)
3170{
3171 return get_gzfile(obj)->io;
3172}
3173
3174/*
3175 * Document-method: Zlib::GzipFile#crc
3176 *
3177 * Returns CRC value of the uncompressed data.
3178 */
3179static VALUE
3180rb_gzfile_crc(VALUE obj)
3181{
3182 return rb_uint2inum(get_gzfile(obj)->crc);
3183}
3184
3185/*
3186 * Document-method: Zlib::GzipFile#mtime
3187 *
3188 * Returns last modification time recorded in the gzip file header.
3189 */
3190static VALUE
3191rb_gzfile_mtime(VALUE obj)
3192{
3193 return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
3194}
3195
3196/*
3197 * Document-method: Zlib::GzipFile#level
3198 *
3199 * Returns compression level.
3200 */
3201static VALUE
3202rb_gzfile_level(VALUE obj)
3203{
3204 return INT2FIX(get_gzfile(obj)->level);
3205}
3206
3207/*
3208 * Document-method: Zlib::GzipFile#os_code
3209 *
3210 * Returns OS code number recorded in the gzip file header.
3211 */
3212static VALUE
3213rb_gzfile_os_code(VALUE obj)
3214{
3215 return INT2FIX(get_gzfile(obj)->os_code);
3216}
3217
3218/*
3219 * Document-method: Zlib::GzipFile#orig_name
3220 *
3221 * Returns original filename recorded in the gzip file header, or +nil+ if
3222 * original filename is not present.
3223 */
3224static VALUE
3225rb_gzfile_orig_name(VALUE obj)
3226{
3227 VALUE str = get_gzfile(obj)->orig_name;
3228 if (!NIL_P(str)) {
3229 str = rb_str_dup(str);
3230 }
3231 return str;
3232}
3233
3234/*
3235 * Document-method: Zlib::GzipFile#comment
3236 *
3237 * Returns comments recorded in the gzip file header, or nil if the comments
3238 * is not present.
3239 */
3240static VALUE
3241rb_gzfile_comment(VALUE obj)
3242{
3243 VALUE str = get_gzfile(obj)->comment;
3244 if (!NIL_P(str)) {
3245 str = rb_str_dup(str);
3246 }
3247 return str;
3248}
3249
3250/*
3251 * Document-method: Zlib::GzipFile#lineno
3252 *
3253 * The line number of the last row read from this file.
3254 */
3255static VALUE
3256rb_gzfile_lineno(VALUE obj)
3257{
3258 return INT2NUM(get_gzfile(obj)->lineno);
3259}
3260
3261/*
3262 * Document-method: Zlib::GzipReader#lineno=
3263 *
3264 * Specify line number of the last row read from this file.
3265 */
3266static VALUE
3267rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
3268{
3269 struct gzfile *gz = get_gzfile(obj);
3270 gz->lineno = NUM2INT(lineno);
3271 return lineno;
3272}
3273
3274/*
3275 * Document-method: Zlib::GzipWriter#mtime=
3276 *
3277 * Specify the modification time (+mtime+) in the gzip header.
3278 * Using an Integer.
3279 *
3280 * Setting the mtime in the gzip header does not effect the
3281 * mtime of the file generated. Different utilities that
3282 * expand the gzipped files may use the mtime
3283 * header. For example the gunzip utility can use the `-N`
3284 * flag which will set the resultant file's mtime to the
3285 * value in the header. By default many tools will set
3286 * the mtime of the expanded file to the mtime of the
3287 * gzipped file, not the mtime in the header.
3288 *
3289 * If you do not set an mtime, the default value will be the time
3290 * when compression started. Setting a value of 0 indicates
3291 * no time stamp is available.
3292 */
3293static VALUE
3294rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
3295{
3296 struct gzfile *gz = get_gzfile(obj);
3297 VALUE val;
3298
3300 rb_raise(cGzError, "header is already written");
3301 }
3302
3303 val = rb_Integer(mtime);
3304 gz->mtime = NUM2UINT(val);
3306
3307 return mtime;
3308}
3309
3310/*
3311 * Document-method: Zlib::GzipFile#orig_name=
3312 *
3313 * Specify the original name (+str+) in the gzip header.
3314 */
3315static VALUE
3316rb_gzfile_set_orig_name(VALUE obj, VALUE str)
3317{
3318 struct gzfile *gz = get_gzfile(obj);
3319 VALUE s;
3320 char *p;
3321
3323 rb_raise(cGzError, "header is already written");
3324 }
3326 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3327 if (p) {
3328 rb_str_resize(s, p - RSTRING_PTR(s));
3329 }
3330 gz->orig_name = s;
3331 return str;
3332}
3333
3334/*
3335 * Document-method: Zlib::GzipFile#comment=
3336 *
3337 * Specify the comment (+str+) in the gzip header.
3338 */
3339static VALUE
3340rb_gzfile_set_comment(VALUE obj, VALUE str)
3341{
3342 struct gzfile *gz = get_gzfile(obj);
3343 VALUE s;
3344 char *p;
3345
3347 rb_raise(cGzError, "header is already written");
3348 }
3350 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
3351 if (p) {
3352 rb_str_resize(s, p - RSTRING_PTR(s));
3353 }
3354 gz->comment = s;
3355 return str;
3356}
3357
3358/*
3359 * Document-method: Zlib::GzipFile#close
3360 *
3361 * Closes the GzipFile object. This method calls close method of the
3362 * associated IO object. Returns the associated IO object.
3363 */
3364static VALUE
3365rb_gzfile_close(VALUE obj)
3366{
3367 struct gzfile *gz;
3368 VALUE io;
3369
3370 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3371 if (!ZSTREAM_IS_READY(&gz->z)) {
3372 return Qnil;
3373 }
3374 io = gz->io;
3375 gzfile_close(gz, 1);
3376 return io;
3377}
3378
3379/*
3380 * Document-method: Zlib::GzipFile#finish
3381 *
3382 * Closes the GzipFile object. Unlike Zlib::GzipFile#close, this method never
3383 * calls the close method of the associated IO object. Returns the associated IO
3384 * object.
3385 */
3386static VALUE
3387rb_gzfile_finish(VALUE obj)
3388{
3389 struct gzfile *gz = get_gzfile(obj);
3390 VALUE io;
3391
3392 io = gz->io;
3393 gzfile_close(gz, 0);
3394 return io;
3395}
3396
3397/*
3398 * Document-method: Zlib::GzipFile#closed?
3399 *
3400 * Same as IO#closed?
3401 *
3402 */
3403static VALUE
3404rb_gzfile_closed_p(VALUE obj)
3405{
3406 struct gzfile *gz;
3407 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3408 return NIL_P(gz->io) ? Qtrue : Qfalse;
3409}
3410
3411/*
3412 * Document-method: Zlib::GzipFile#eof?
3413 *
3414 * Returns +true+ or +false+ whether the stream has reached the end.
3415 */
3416static VALUE
3417rb_gzfile_eof_p(VALUE obj)
3418{
3419 struct gzfile *gz = get_gzfile(obj);
3420 return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
3421}
3422
3423/*
3424 * Document-method: Zlib::GzipFile#sync
3425 *
3426 * Same as IO#sync
3427 *
3428 */
3429static VALUE
3430rb_gzfile_sync(VALUE obj)
3431{
3432 return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
3433}
3434
3435/*
3436 * Document-method: Zlib::GzipFile#sync=
3437 *
3438 * call-seq: sync = flag
3439 *
3440 * Same as IO. If flag is +true+, the associated IO object must respond to the
3441 * +flush+ method. While +sync+ mode is +true+, the compression ratio
3442 * decreases sharply.
3443 */
3444static VALUE
3445rb_gzfile_set_sync(VALUE obj, VALUE mode)
3446{
3447 struct gzfile *gz = get_gzfile(obj);
3448
3449 if (RTEST(mode)) {
3450 gz->z.flags |= GZFILE_FLAG_SYNC;
3451 }
3452 else {
3453 gz->z.flags &= ~GZFILE_FLAG_SYNC;
3454 }
3455 return mode;
3456}
3457
3458/*
3459 * Document-method: Zlib::GzipFile#total_in
3460 *
3461 * Total number of input bytes read so far.
3462 */
3463static VALUE
3464rb_gzfile_total_in(VALUE obj)
3465{
3466 return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
3467}
3468
3469/*
3470 * Document-method: Zlib::GzipFile#total_out
3471 *
3472 * Total number of output bytes output so far.
3473 */
3474static VALUE
3475rb_gzfile_total_out(VALUE obj)
3476{
3477 struct gzfile *gz = get_gzfile(obj);
3478 uLong total_out = gz->z.stream.total_out;
3479 long buf_filled = ZSTREAM_BUF_FILLED(&gz->z);
3480
3481 if (total_out >= (uLong)buf_filled) {
3482 return rb_uint2inum(total_out - buf_filled);
3483 } else {
3484 return LONG2FIX(-(buf_filled - (long)total_out));
3485 }
3486}
3487
3488/*
3489 * Document-method: Zlib::GzipFile#path
3490 *
3491 * call-seq: path
3492 *
3493 * Returns the path string of the associated IO-like object. This
3494 * method is only defined when the IO-like object responds to #path().
3495 */
3496static VALUE
3497rb_gzfile_path(VALUE obj)
3498{
3499 struct gzfile *gz;
3500 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3501 return gz->path;
3502}
3503
3504static void
3505rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
3506{
3507 if (!NIL_P(opts)) {
3508 rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
3509 }
3510 if (gz->enc2) {
3511 gz->ecflags = rb_econv_prepare_opts(opts, &opts);
3512 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
3513 gz->ecflags, opts);
3514 gz->ecopts = opts;
3515 }
3516}
3517
3518/* ------------------------------------------------------------------------- */
3519
3520/*
3521 * Document-class: Zlib::GzipWriter
3522 *
3523 * Zlib::GzipWriter is a class for writing gzipped files. GzipWriter should
3524 * be used with an instance of IO, or IO-like, object.
3525 *
3526 * Following two example generate the same result.
3527 *
3528 * Zlib::GzipWriter.open('hoge.gz') do |gz|
3529 * gz.write 'jugemu jugemu gokou no surikire...'
3530 * end
3531 *
3532 * File.open('hoge.gz', 'w') do |f|
3533 * gz = Zlib::GzipWriter.new(f)
3534 * gz.write 'jugemu jugemu gokou no surikire...'
3535 * gz.close
3536 * end
3537 *
3538 * To make like gzip(1) does, run following:
3539 *
3540 * orig = 'hoge.txt'
3541 * Zlib::GzipWriter.open('hoge.gz') do |gz|
3542 * gz.mtime = File.mtime(orig)
3543 * gz.orig_name = orig
3544 * gz.write IO.binread(orig)
3545 * end
3546 *
3547 * NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close
3548 * GzipWriter objects by Zlib::GzipWriter#close etc. Otherwise, GzipWriter
3549 * will be not able to write the gzip footer and will generate a broken gzip
3550 * file.
3551 */
3552
3553static VALUE
3554rb_gzwriter_s_allocate(VALUE klass)
3555{
3556 return gzfile_writer_new(klass);
3557}
3558
3559/*
3560 * call-seq: Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... }
3561 *
3562 * Opens a file specified by +filename+ for writing gzip compressed data, and
3563 * returns a GzipWriter object associated with that file. Further details of
3564 * this method are found in Zlib::GzipWriter.new and Zlib::GzipFile.wrap.
3565 */
3566static VALUE
3567rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
3568{
3569 return gzfile_s_open(argc, argv, klass, "wb");
3570}
3571
3572/*
3573 * call-seq:
3574 * Zlib::GzipWriter.new(io, level = nil, strategy = nil, options = {})
3575 *
3576 * Creates a GzipWriter object associated with +io+. +level+ and +strategy+
3577 * should be the same as the arguments of Zlib::Deflate.new. The GzipWriter
3578 * object writes gzipped data to +io+. +io+ must respond to the
3579 * +write+ method that behaves the same as IO#write.
3580 *
3581 * The +options+ hash may be used to set the encoding of the data.
3582 * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3583 * IO::new.
3584 */
3585static VALUE
3586rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
3587{
3588 struct gzfile *gz;
3589 VALUE io, level, strategy, opt = Qnil;
3590 int err;
3591
3592 if (argc > 1) {
3593 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
3594 if (!NIL_P(opt)) argc--;
3595 }
3596
3597 rb_scan_args(argc, argv, "12", &io, &level, &strategy);
3598 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3599
3600 /* this is undocumented feature of zlib */
3601 gz->level = ARG_LEVEL(level);
3602 err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
3603 -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
3604 if (err != Z_OK) {
3605 raise_zlib_error(err, gz->z.stream.msg);
3606 }
3607 gz->io = io;
3608 ZSTREAM_READY(&gz->z);
3609 rb_gzfile_ecopts(gz, opt);
3610
3611 if (rb_respond_to(io, id_path)) {
3612 gz->path = rb_funcall(gz->io, id_path, 0);
3613 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3614 }
3615
3616 return obj;
3617}
3618
3619/*
3620 * call-seq: flush(flush=nil)
3621 *
3622 * Flushes all the internal buffers of the GzipWriter object. The meaning of
3623 * +flush+ is same as in Zlib::Deflate#deflate. <tt>Zlib::SYNC_FLUSH</tt> is used if
3624 * +flush+ is omitted. It is no use giving flush <tt>Zlib::NO_FLUSH</tt>.
3625 */
3626static VALUE
3627rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
3628{
3629 struct gzfile *gz = get_gzfile(obj);
3630 VALUE v_flush;
3631 int flush;
3632
3633 rb_scan_args(argc, argv, "01", &v_flush);
3634
3635 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
3636 if (flush != Z_NO_FLUSH) { /* prevent Z_BUF_ERROR */
3637 zstream_run(&gz->z, (Bytef*)"", 0, flush);
3638 }
3639
3640 gzfile_write_raw(gz);
3641 if (rb_respond_to(gz->io, id_flush)) {
3642 rb_funcall(gz->io, id_flush, 0);
3643 }
3644 return obj;
3645}
3646
3647/*
3648 * Same as IO.
3649 */
3650static VALUE
3651rb_gzwriter_write(int argc, VALUE *argv, VALUE obj)
3652{
3653 struct gzfile *gz = get_gzfile(obj);
3654 size_t total = 0;
3655
3656 while (argc-- > 0) {
3657 VALUE str = *argv++;
3658 if (!RB_TYPE_P(str, T_STRING))
3660 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
3662 }
3663 gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
3664 total += RSTRING_LEN(str);
3666 }
3667 return SIZET2NUM(total);
3668}
3669
3670/*
3671 * Same as IO.
3672 */
3673static VALUE
3674rb_gzwriter_putc(VALUE obj, VALUE ch)
3675{
3676 struct gzfile *gz = get_gzfile(obj);
3677 char c = NUM2CHR(ch);
3678
3679 gzfile_write(gz, (Bytef*)&c, 1);
3680 return ch;
3681}
3682
3683
3684
3685/*
3686 * Document-method: <<
3687 * Same as IO.
3689#define rb_gzwriter_addstr rb_io_addstr
3690/*
3691 * Document-method: printf
3692 * Same as IO.
3694#define rb_gzwriter_printf rb_io_printf
3695/*
3696 * Document-method: print
3697 * Same as IO.
3699#define rb_gzwriter_print rb_io_print
3700/*
3701 * Document-method: puts
3702 * Same as IO.
3704#define rb_gzwriter_puts rb_io_puts
3705
3706
3707/* ------------------------------------------------------------------------- */
3708
3709/*
3710 * Document-class: Zlib::GzipReader
3711 *
3712 * Zlib::GzipReader is the class for reading a gzipped file. GzipReader should
3713 * be used as an IO, or -IO-like, object.
3714 *
3715 * Zlib::GzipReader.open('hoge.gz') {|gz|
3716 * print gz.read
3717 * }
3718 *
3719 * File.open('hoge.gz') do |f|
3720 * gz = Zlib::GzipReader.new(f)
3721 * print gz.read
3722 * gz.close
3723 * end
3724 *
3725 * == Method Catalogue
3726 *
3727 * The following methods in Zlib::GzipReader are just like their counterparts
3728 * in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an
3729 * error was found in the gzip file.
3730 * - #each
3731 * - #each_line
3732 * - #each_byte
3733 * - #gets
3734 * - #getc
3735 * - #lineno
3736 * - #lineno=
3737 * - #read
3738 * - #readchar
3739 * - #readline
3740 * - #readlines
3741 * - #ungetc
3742 *
3743 * Be careful of the footer of the gzip file. A gzip file has the checksum of
3744 * pre-compressed data in its footer. GzipReader checks all uncompressed data
3745 * against that checksum at the following cases, and if it fails, raises
3746 * <tt>Zlib::GzipFile::NoFooter</tt>, <tt>Zlib::GzipFile::CRCError</tt>, or
3747 * <tt>Zlib::GzipFile::LengthError</tt> exception.
3748 *
3749 * - When an reading request is received beyond the end of file (the end of
3750 * compressed data). That is, when Zlib::GzipReader#read,
3751 * Zlib::GzipReader#gets, or some other methods for reading returns nil.
3752 * - When Zlib::GzipFile#close method is called after the object reaches the
3753 * end of file.
3754 * - When Zlib::GzipReader#unused method is called after the object reaches
3755 * the end of file.
3756 *
3757 * The rest of the methods are adequately described in their own
3758 * documentation.
3759 */
3760
3761static VALUE
3762rb_gzreader_s_allocate(VALUE klass)
3763{
3764 return gzfile_reader_new(klass);
3765}
3766
3767/*
3768 * Document-method: Zlib::GzipReader.open
3769 *
3770 * call-seq: Zlib::GzipReader.open(filename) {|gz| ... }
3771 *
3772 * Opens a file specified by +filename+ as a gzipped file, and returns a
3773 * GzipReader object associated with that file. Further details of this method
3774 * are in Zlib::GzipReader.new and ZLib::GzipFile.wrap.
3775 */
3776static VALUE
3777rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
3778{
3779 return gzfile_s_open(argc, argv, klass, "rb");
3780}
3781
3782/*
3783 * Document-method: Zlib::GzipReader.new
3784 *
3785 * call-seq:
3786 * Zlib::GzipReader.new(io, options = {})
3787 *
3788 * Creates a GzipReader object associated with +io+. The GzipReader object reads
3789 * gzipped data from +io+, and parses/decompresses it. The +io+ must
3790 * have a +read+ method that behaves same as the IO#read.
3791 *
3792 * The +options+ hash may be used to set the encoding of the data.
3793 * +:external_encoding+, +:internal_encoding+ and +:encoding+ may be set as in
3794 * IO::new.
3795 *
3796 * If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
3797 * exception.
3798 */
3799static VALUE
3800rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
3801{
3802 VALUE io, opt = Qnil;
3803 struct gzfile *gz;
3804 int err;
3805
3806 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3807 rb_scan_args(argc, argv, "1:", &io, &opt);
3808
3809 /* this is undocumented feature of zlib */
3810 err = inflateInit2(&gz->z.stream, -MAX_WBITS);
3811 if (err != Z_OK) {
3812 raise_zlib_error(err, gz->z.stream.msg);
3813 }
3814 gz->io = io;
3815 ZSTREAM_READY(&gz->z);
3816 gzfile_read_header(gz, Qnil);
3817 rb_gzfile_ecopts(gz, opt);
3818
3819 if (rb_respond_to(io, id_path)) {
3820 gz->path = rb_funcall(gz->io, id_path, 0);
3821 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
3822 }
3823
3824 return obj;
3825}
3826
3827/*
3828 * Document-method: Zlib::GzipReader#rewind
3829 *
3830 * Resets the position of the file pointer to the point created the GzipReader
3831 * object. The associated IO object needs to respond to the +seek+ method.
3832 */
3833static VALUE
3834rb_gzreader_rewind(VALUE obj)
3835{
3836 struct gzfile *gz = get_gzfile(obj);
3837 gzfile_reader_rewind(gz);
3838 return INT2FIX(0);
3839}
3840
3841/*
3842 * Document-method: Zlib::GzipReader#unused
3843 *
3844 * Returns the rest of the data which had read for parsing gzip format, or
3845 * +nil+ if the whole gzip file is not parsed yet.
3846 */
3847static VALUE
3848rb_gzreader_unused(VALUE obj)
3849{
3850 struct gzfile *gz;
3851 TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
3852 return gzfile_reader_get_unused(gz);
3853}
3854
3855/*
3856 * Document-method: Zlib::GzipReader#read
3857 *
3858 * See Zlib::GzipReader documentation for a description.
3859 */
3860static VALUE
3861rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
3862{
3863 struct gzfile *gz = get_gzfile(obj);
3864 VALUE vlen;
3865 long len;
3866
3867 rb_scan_args(argc, argv, "01", &vlen);
3868 if (NIL_P(vlen)) {
3869 return gzfile_read_all(gz);
3870 }
3871
3872 len = NUM2INT(vlen);
3873 if (len < 0) {
3874 rb_raise(rb_eArgError, "negative length %ld given", len);
3875 }
3876 return gzfile_read(gz, len);
3877}
3878
3879/*
3880 * Document-method: Zlib::GzipReader#readpartial
3881 *
3882 * call-seq:
3883 * gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
3884 *
3885 * Reads at most <i>maxlen</i> bytes from the gziped stream but
3886 * it blocks only if <em>gzipreader</em> has no data immediately available.
3887 * If the optional <i>outbuf</i> argument is present,
3888 * it must reference a String, which will receive the data.
3889 * It raises <code>EOFError</code> on end of file.
3890 */
3891static VALUE
3892rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
3893{
3894 struct gzfile *gz = get_gzfile(obj);
3895 VALUE vlen, outbuf;
3896 long len;
3897
3898 rb_scan_args(argc, argv, "11", &vlen, &outbuf);
3899
3900 len = NUM2INT(vlen);
3901 if (len < 0) {
3902 rb_raise(rb_eArgError, "negative length %ld given", len);
3903 }
3904 if (!NIL_P(outbuf))
3905 Check_Type(outbuf, T_STRING);
3906 return gzfile_readpartial(gz, len, outbuf);
3907}
3908
3909/*
3910 * Document-method: Zlib::GzipReader#getc
3911 *
3912 * See Zlib::GzipReader documentation for a description.
3913 */
3914static VALUE
3915rb_gzreader_getc(VALUE obj)
3916{
3917 struct gzfile *gz = get_gzfile(obj);
3918
3919 return gzfile_getc(gz);
3920}
3921
3922/*
3923 * Document-method: Zlib::GzipReader#readchar
3924 *
3925 * See Zlib::GzipReader documentation for a description.
3926 */
3927static VALUE
3928rb_gzreader_readchar(VALUE obj)
3929{
3930 VALUE dst;
3931 dst = rb_gzreader_getc(obj);
3932 if (NIL_P(dst)) {
3933 rb_raise(rb_eEOFError, "end of file reached");
3934 }
3935 return dst;
3936}
3937
3938/*
3939 * Document-method: Zlib::GzipReader#getbyte
3940 *
3941 * See Zlib::GzipReader documentation for a description.
3942 */
3943static VALUE
3944rb_gzreader_getbyte(VALUE obj)
3945{
3946 struct gzfile *gz = get_gzfile(obj);
3947 VALUE dst;
3948
3949 dst = gzfile_read(gz, 1);
3950 if (!NIL_P(dst)) {
3951 dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
3952 }
3953 return dst;
3954}
3955
3956/*
3957 * Document-method: Zlib::GzipReader#readbyte
3958 *
3959 * See Zlib::GzipReader documentation for a description.
3960 */
3961static VALUE
3962rb_gzreader_readbyte(VALUE obj)
3963{
3964 VALUE dst;
3965 dst = rb_gzreader_getbyte(obj);
3966 if (NIL_P(dst)) {
3967 rb_raise(rb_eEOFError, "end of file reached");
3968 }
3969 return dst;
3970}
3971
3972/*
3973 * Document-method: Zlib::GzipReader#each_char
3974 *
3975 * See Zlib::GzipReader documentation for a description.
3976 */
3977static VALUE
3978rb_gzreader_each_char(VALUE obj)
3979{
3980 VALUE c;
3981
3982 RETURN_ENUMERATOR(obj, 0, 0);
3983
3984 while (!NIL_P(c = rb_gzreader_getc(obj))) {
3985 rb_yield(c);
3986 }
3987 return Qnil;
3988}
3989
3990/*
3991 * Document-method: Zlib::GzipReader#each_byte
3992 *
3993 * See Zlib::GzipReader documentation for a description.
3994 */
3995static VALUE
3996rb_gzreader_each_byte(VALUE obj)
3997{
3998 VALUE c;
3999
4000 RETURN_ENUMERATOR(obj, 0, 0);
4001
4002 while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
4003 rb_yield(c);
4004 }
4005 return Qnil;
4006}
4007
4008/*
4009 * Document-method: Zlib::GzipReader#bytes
4010 *
4011 * This is a deprecated alias for <code>each_byte</code>.
4012 */
4013static VALUE
4014rb_gzreader_bytes(VALUE obj)
4015{
4016 rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
4017 if (!rb_block_given_p())
4018 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
4019 return rb_gzreader_each_byte(obj);
4020}
4021
4022/*
4023 * Document-method: Zlib::GzipReader#ungetc
4024 *
4025 * See Zlib::GzipReader documentation for a description.
4026 */
4027static VALUE
4028rb_gzreader_ungetc(VALUE obj, VALUE s)
4029{
4030 struct gzfile *gz;
4031
4032 if (FIXNUM_P(s))
4033 return rb_gzreader_ungetbyte(obj, s);
4034 gz = get_gzfile(obj);
4035 StringValue(s);
4036 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
4037 s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
4038 }
4039 gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
4040 RB_GC_GUARD(s);
4041 return Qnil;
4042}
4043
4044/*
4045 * Document-method: Zlib::GzipReader#ungetbyte
4046 *
4047 * See Zlib::GzipReader documentation for a description.
4048 */
4049static VALUE
4050rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
4051{
4052 struct gzfile *gz = get_gzfile(obj);
4053 gzfile_ungetbyte(gz, NUM2CHR(ch));
4054 return Qnil;
4055}
4056
4057static void
4058gzreader_skip_linebreaks(struct gzfile *gz)
4059{
4060 VALUE str;
4061 char *p;
4062 int n;
4063
4064 while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
4065 if (GZFILE_IS_FINISHED(gz)) return;
4066 gzfile_read_more(gz, Qnil);
4067 }
4068 n = 0;
4069 p = RSTRING_PTR(gz->z.buf);
4070
4071 while (n++, *(p++) == '\n') {
4072 if (n >= ZSTREAM_BUF_FILLED(&gz->z)) {
4073 str = zstream_detach_buffer(&gz->z);
4074 gzfile_calc_crc(gz, str);
4075 while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
4076 if (GZFILE_IS_FINISHED(gz)) return;
4077 gzfile_read_more(gz, Qnil);
4078 }
4079 n = 0;
4080 p = RSTRING_PTR(gz->z.buf);
4081 }
4082 }
4083
4084 str = zstream_shift_buffer(&gz->z, n - 1);
4085 gzfile_calc_crc(gz, str);
4086}
4087
4088static void
4089rscheck(const char *rsptr, long rslen, VALUE rs)
4090{
4091 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
4092 rb_raise(rb_eRuntimeError, "rs modified");
4093}
4094
4095static long
4096gzreader_charboundary(struct gzfile *gz, long n)
4097{
4098 char *s = RSTRING_PTR(gz->z.buf);
4099 char *e = s + ZSTREAM_BUF_FILLED(&gz->z);
4100 char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
4101 long l = p - s;
4102 if (l < n) {
4103 n = rb_enc_precise_mbclen(p, e, gz->enc);
4104 if (MBCLEN_NEEDMORE_P(n)) {
4105 if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
4106 return l;
4107 }
4108 }
4109 else if (MBCLEN_CHARFOUND_P(n)) {
4110 return l + MBCLEN_CHARFOUND_LEN(n);
4111 }
4112 }
4113 return n;
4114}
4115
4116static VALUE
4117gzreader_gets(int argc, VALUE *argv, VALUE obj)
4118{
4119 struct gzfile *gz = get_gzfile(obj);
4120 VALUE rs;
4121 VALUE dst;
4122 const char *rsptr;
4123 char *p, *res;
4124 long rslen, n, limit = -1;
4125 int rspara;
4126 rb_encoding *enc = gz->enc;
4127 int maxlen = rb_enc_mbmaxlen(enc);
4128
4129 if (argc == 0) {
4130 rs = rb_rs;
4131 }
4132 else {
4133 VALUE lim, tmp;
4134
4135 rb_scan_args(argc, argv, "11", &rs, &lim);
4136 if (!NIL_P(lim)) {
4137 if (!NIL_P(rs)) StringValue(rs);
4138 }
4139 else if (!NIL_P(rs)) {
4140 tmp = rb_check_string_type(rs);
4141 if (NIL_P(tmp)) {
4142 lim = rs;
4143 rs = rb_rs;
4144 }
4145 else {
4146 rs = tmp;
4147 }
4148 }
4149 if (!NIL_P(lim)) {
4150 limit = NUM2LONG(lim);
4151 if (limit == 0) return rb_str_new(0,0);
4152 }
4153 }
4154
4155 if (NIL_P(rs)) {
4156 if (limit < 0) {
4157 dst = gzfile_read_all(gz);
4158 if (RSTRING_LEN(dst) == 0) return Qnil;
4159 }
4160 else if ((n = gzfile_fill(gz, limit)) <= 0) {
4161 return Qnil;
4162 }
4163 else {
4164 if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
4165 n = gzreader_charboundary(gz, n);
4166 }
4167 else {
4168 n = limit;
4169 }
4170 dst = zstream_shift_buffer(&gz->z, n);
4171 if (NIL_P(dst)) return dst;
4172 gzfile_calc_crc(gz, dst);
4173 dst = gzfile_newstr(gz, dst);
4174 }
4175 gz->lineno++;
4176 return dst;
4177 }
4178
4179 if (RSTRING_LEN(rs) == 0) {
4180 rsptr = "\n\n";
4181 rslen = 2;
4182 rspara = 1;
4183 }
4184 else {
4185 rsptr = RSTRING_PTR(rs);
4186 rslen = RSTRING_LEN(rs);
4187 rspara = 0;
4188 }
4189
4190 if (rspara) {
4191 gzreader_skip_linebreaks(gz);
4192 }
4193
4194 while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) {
4195 if (ZSTREAM_IS_FINISHED(&gz->z)) {
4196 if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
4197 return gzfile_read(gz, rslen);
4198 }
4199 gzfile_read_more(gz, Qnil);
4200 }
4201
4202 p = RSTRING_PTR(gz->z.buf);
4203 n = rslen;
4204 for (;;) {
4205 long filled;
4206 if (n > ZSTREAM_BUF_FILLED(&gz->z)) {
4207 if (ZSTREAM_IS_FINISHED(&gz->z)) break;
4208 gzfile_read_more(gz, Qnil);
4209 p = RSTRING_PTR(gz->z.buf) + n - rslen;
4210 }
4211 if (!rspara) rscheck(rsptr, rslen, rs);
4212 filled = ZSTREAM_BUF_FILLED(&gz->z);
4213 if (limit > 0 && filled >= limit) {
4214 filled = limit;
4215 }
4216 res = memchr(p, rsptr[0], (filled - n + 1));
4217 if (!res) {
4218 n = filled;
4219 if (limit > 0 && filled >= limit) break;
4220 n++;
4221 }
4222 else {
4223 n += (long)(res - p);
4224 p = res;
4225 if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
4226 p++, n++;
4227 }
4228 }
4229 if (maxlen > 1 && n == limit && (ZSTREAM_BUF_FILLED(&gz->z) > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
4230 n = gzreader_charboundary(gz, n);
4231 }
4232
4233 gz->lineno++;
4234 dst = gzfile_read(gz, n);
4235 if (NIL_P(dst)) return dst;
4236 if (rspara) {
4237 gzreader_skip_linebreaks(gz);
4238 }
4239 RB_GC_GUARD(rs);
4240
4241 return gzfile_newstr(gz, dst);
4242}
4243
4244/*
4245 * Document-method: Zlib::GzipReader#gets
4246 *
4247 * See Zlib::GzipReader documentation for a description.
4248 */
4249static VALUE
4250rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
4251{
4252 VALUE dst;
4253 dst = gzreader_gets(argc, argv, obj);
4254 if (!NIL_P(dst)) {
4255 rb_lastline_set(dst);
4256 }
4257 return dst;
4258}
4259
4260/*
4261 * Document-method: Zlib::GzipReader#readline
4262 *
4263 * See Zlib::GzipReader documentation for a description.
4264 */
4265static VALUE
4266rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
4267{
4268 VALUE dst;
4269 dst = rb_gzreader_gets(argc, argv, obj);
4270 if (NIL_P(dst)) {
4271 rb_raise(rb_eEOFError, "end of file reached");
4272 }
4273 return dst;
4274}
4275
4276/*
4277 * Document-method: Zlib::GzipReader#each
4278 *
4279 * See Zlib::GzipReader documentation for a description.
4280 */
4281static VALUE
4282rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
4283{
4284 VALUE str;
4285
4286 RETURN_ENUMERATOR(obj, 0, 0);
4287
4288 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4289 rb_yield(str);
4290 }
4291 return obj;
4292}
4293
4294/*
4295 * Document-method: Zlib::GzipReader#lines
4296 *
4297 * This is a deprecated alias for <code>each_line</code>.
4298 */
4299static VALUE
4300rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
4301{
4302 rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
4303 if (!rb_block_given_p())
4304 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
4305 return rb_gzreader_each(argc, argv, obj);
4306}
4307
4308/*
4309 * Document-method: Zlib::GzipReader#readlines
4310 *
4311 * See Zlib::GzipReader documentation for a description.
4312 */
4313static VALUE
4314rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
4315{
4316 VALUE str, dst;
4317 dst = rb_ary_new();
4318 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
4319 rb_ary_push(dst, str);
4320 }
4321 return dst;
4322}
4323
4324/*
4325 * Document-method: Zlib::GzipReader#external_encoding
4326 *
4327 * See Zlib::GzipReader documentation for a description.
4328 */
4329static VALUE
4330rb_gzreader_external_encoding(VALUE self)
4331{
4332 return rb_enc_from_encoding(get_gzfile(self)->enc);
4333}
4334
4335static VALUE
4336zlib_gzip_end_rescue(VALUE arg)
4337{
4338 struct gzfile *gz = (struct gzfile *)arg;
4339 gz->end(gz);
4340 return Qnil;
4341}
4342
4343static VALUE
4344zlib_gzip_ensure(VALUE arg)
4345{
4346 return rb_rescue(zlib_gzip_end_rescue, arg, NULL, Qnil);
4347}
4348
4349static void
4350zlib_gzip_end(struct gzfile *gz)
4351{
4353 zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
4354 gzfile_make_footer(gz);
4355 zstream_end(&gz->z);
4356}
4358#define OPTHASH_GIVEN_P(opts) \
4359 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
4360static ID id_level, id_strategy;
4361static VALUE zlib_gzip_run(VALUE arg);
4362
4363/*
4364 * call-seq:
4365 * Zlib.gzip(src, level: nil, strategy: nil) -> String
4366 *
4367 * Gzip the given +string+. Valid values of level are
4368 * Zlib::NO_COMPRESSION, Zlib::BEST_SPEED, Zlib::BEST_COMPRESSION,
4369 * Zlib::DEFAULT_COMPRESSION (default), or an integer from 0 to 9.
4370 *
4371 * This method is almost equivalent to the following code:
4372 *
4373 * def gzip(string, level: nil, strategy: nil)
4374 * sio = StringIO.new
4375 * sio.binmode
4376 * gz = Zlib::GzipWriter.new(sio, level, strategy)
4377 * gz.write(string)
4378 * gz.close
4379 * sio.string
4380 * end
4381 *
4382 * See also Zlib.gunzip
4383 *
4384 */
4385static VALUE
4386zlib_s_gzip(int argc, VALUE *argv, VALUE klass)
4387{
4388 struct gzfile gz0;
4389 struct gzfile *gz = &gz0;
4390 int err;
4391 VALUE src, opts, level=Qnil, strategy=Qnil, args[2];
4392
4393 if (OPTHASH_GIVEN_P(opts)) {
4394 ID keyword_ids[2];
4395 VALUE kwargs[2];
4396 keyword_ids[0] = id_level;
4397 keyword_ids[1] = id_strategy;
4398 rb_get_kwargs(opts, keyword_ids, 0, 2, kwargs);
4399 if (kwargs[0] != Qundef) {
4400 level = kwargs[0];
4401 }
4402 if (kwargs[1] != Qundef) {
4403 strategy = kwargs[1];
4404 }
4405 }
4406 rb_scan_args(argc, argv, "10", &src);
4408 gzfile_init(gz, &deflate_funcs, zlib_gzip_end);
4409 gz->level = ARG_LEVEL(level);
4410 err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
4411 -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
4412 if (err != Z_OK) {
4413 zlib_gzip_end(gz);
4414 raise_zlib_error(err, gz->z.stream.msg);
4415 }
4416 ZSTREAM_READY(&gz->z);
4417 args[0] = (VALUE)gz;
4418 args[1] = src;
4419 return rb_ensure(zlib_gzip_run, (VALUE)args, zlib_gzip_ensure, (VALUE)gz);
4420}
4421
4422static VALUE
4423zlib_gzip_run(VALUE arg)
4424{
4425 VALUE *args = (VALUE *)arg;
4426 struct gzfile *gz = (struct gzfile *)args[0];
4427 VALUE src = args[1];
4428 long len;
4429
4430 gzfile_make_header(gz);
4431 len = RSTRING_LEN(src);
4432 if (len > 0) {
4433 Bytef *ptr = (Bytef *)RSTRING_PTR(src);
4434 gz->crc = checksum_long(crc32, gz->crc, ptr, len);
4435 zstream_run(&gz->z, ptr, len, Z_NO_FLUSH);
4436 }
4437 gzfile_close(gz, 0);
4438 return zstream_detach_buffer(&gz->z);
4439}
4440
4441static void
4442zlib_gunzip_end(struct gzfile *gz)
4443{
4445 zstream_end(&gz->z);
4446}
4447
4448static VALUE zlib_gunzip_run(VALUE arg);
4449
4450/*
4451 * call-seq:
4452 * Zlib.gunzip(src) -> String
4453 *
4454 * Decode the given gzipped +string+.
4455 *
4456 * This method is almost equivalent to the following code:
4457 *
4458 * def gunzip(string)
4459 * sio = StringIO.new(string)
4460 * gz = Zlib::GzipReader.new(sio, encoding: Encoding::ASCII_8BIT)
4461 * gz.read
4462 * ensure
4463 * gz&.close
4464 * end
4465 *
4466 * See also Zlib.gzip
4467 */
4468static VALUE
4469zlib_gunzip(VALUE klass, VALUE src)
4470{
4471 struct gzfile gz0;
4472 struct gzfile *gz = &gz0;
4473 int err;
4474
4476
4477 gzfile_init(gz, &inflate_funcs, zlib_gunzip_end);
4478 err = inflateInit2(&gz->z.stream, -MAX_WBITS);
4479 if (err != Z_OK) {
4480 raise_zlib_error(err, gz->z.stream.msg);
4481 }
4482 gz->io = Qundef;
4483 gz->z.input = src;
4484 ZSTREAM_READY(&gz->z);
4485 return rb_ensure(zlib_gunzip_run, (VALUE)gz, zlib_gzip_ensure, (VALUE)gz);
4486}
4487
4488static VALUE
4489zlib_gunzip_run(VALUE arg)
4490{
4491 struct gzfile *gz = (struct gzfile *)arg;
4492 VALUE dst;
4493
4494 gzfile_read_header(gz, Qnil);
4495 dst = zstream_detach_buffer(&gz->z);
4496 gzfile_calc_crc(gz, dst);
4497 if (!ZSTREAM_IS_FINISHED(&gz->z)) {
4498 rb_raise(cGzError, "unexpected end of file");
4499 }
4500 if (NIL_P(gz->z.input)) {
4501 rb_raise(cNoFooter, "footer is not found");
4502 }
4503 gzfile_check_footer(gz, Qnil);
4504 return dst;
4505}
4506
4507#endif /* GZIP_SUPPORT */
4508
4509void
4510Init_zlib(void)
4511{
4512#undef rb_intern
4513 VALUE mZlib, cZStream, cDeflate, cInflate;
4514#if GZIP_SUPPORT
4515 VALUE cGzipFile, cGzipWriter, cGzipReader;
4516#endif
4517
4518 mZlib = rb_define_module("Zlib");
4519
4520 id_dictionaries = rb_intern("@dictionaries");
4521
4522 cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
4523 cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
4524 cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
4525 cDataError = rb_define_class_under(mZlib, "DataError", cZError);
4526 cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
4527 cMemError = rb_define_class_under(mZlib, "MemError", cZError);
4528 cBufError = rb_define_class_under(mZlib, "BufError", cZError);
4529 cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
4530 cInProgressError = rb_define_class_under(mZlib, "InProgressError", cZError);
4531
4532 rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
4533 rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
4534 rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
4535 rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
4536 rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
4537 rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
4538
4539 /* The Ruby/zlib version string. */
4540 rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
4541 /* The string which represents the version of zlib.h */
4542 rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
4543
4544 cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
4545 rb_undef_alloc_func(cZStream);
4546 rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
4547 rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
4548 rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
4549 rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
4550 rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
4551 rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
4552 rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
4553 rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
4554 rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
4555 rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
4556 rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
4557 rb_define_method(cZStream, "close", rb_zstream_end, 0);
4558 rb_define_method(cZStream, "end", rb_zstream_end, 0);
4559 rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
4560 rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
4561 rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
4562 rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
4563
4564 /* Represents binary data as guessed by deflate.
4565 *
4566 * See Zlib::Deflate#data_type. */
4567 rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
4568
4569 /* Represents text data as guessed by deflate.
4570 *
4571 * NOTE: The underlying constant Z_ASCII was deprecated in favor of Z_TEXT
4572 * in zlib 1.2.2. New applications should not use this constant.
4573 *
4574 * See Zlib::Deflate#data_type. */
4575 rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
4576
4577#ifdef Z_TEXT
4578 /* Represents text data as guessed by deflate.
4579 *
4580 * See Zlib::Deflate#data_type. */
4581 rb_define_const(mZlib, "TEXT", INT2FIX(Z_TEXT));
4582#endif
4583
4584 /* Represents an unknown data type as guessed by deflate.
4585 *
4586 * See Zlib::Deflate#data_type. */
4587 rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
4588
4589 cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
4590 rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
4591 rb_define_singleton_method(mZlib, "deflate", rb_deflate_s_deflate, -1);
4592 rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
4593 rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
4594 rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
4595 rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
4596 rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
4597 rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
4598 rb_define_method(cDeflate, "params", rb_deflate_params, 2);
4599 rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
4600
4601 cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
4602 rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
4603 rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
4604 rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
4605 rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
4606 rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
4607 rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
4608 rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
4609 rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
4610 rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
4611 rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
4612
4613 /* No compression, passes through data untouched. Use this for appending
4614 * pre-compressed data to a deflate stream.
4615 */
4616 rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
4617 /* Fastest compression level, but with the lowest space savings. */
4618 rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
4619 /* Slowest compression level, but with the best space savings. */
4620 rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
4621 /* Default compression level which is a good trade-off between space and
4622 * time
4623 */
4624 rb_define_const(mZlib, "DEFAULT_COMPRESSION",
4625 INT2FIX(Z_DEFAULT_COMPRESSION));
4626
4627 /* Deflate strategy for data produced by a filter (or predictor). The
4628 * effect of FILTERED is to force more Huffman codes and less string
4629 * matching; it is somewhat intermediate between DEFAULT_STRATEGY and
4630 * HUFFMAN_ONLY. Filtered data consists mostly of small values with a
4631 * somewhat random distribution.
4632 */
4633 rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
4634
4635 /* Deflate strategy which uses Huffman codes only (no string matching). */
4636 rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
4637
4638#ifdef Z_RLE
4639 /* Deflate compression strategy designed to be almost as fast as
4640 * HUFFMAN_ONLY, but give better compression for PNG image data.
4641 */
4642 rb_define_const(mZlib, "RLE", INT2FIX(Z_RLE));
4643#endif
4644
4645#ifdef Z_FIXED
4646 /* Deflate strategy which prevents the use of dynamic Huffman codes,
4647 * allowing for a simpler decoder for specialized applications.
4648 */
4649 rb_define_const(mZlib, "FIXED", INT2FIX(Z_FIXED));
4650#endif
4651
4652 /* Default deflate strategy which is used for normal data. */
4653 rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
4654
4655 /* The maximum size of the zlib history buffer. Note that zlib allows
4656 * larger values to enable different inflate modes. See Zlib::Inflate.new
4657 * for details.
4658 */
4659 rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
4660
4661 /* The default memory level for allocating zlib deflate compression state.
4662 */
4663 rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
4664
4665 /* The maximum memory level for allocating zlib deflate compression state.
4666 */
4667 rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
4668
4669 /* NO_FLUSH is the default flush method and allows deflate to decide how
4670 * much data to accumulate before producing output in order to maximize
4671 * compression.
4672 */
4673 rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
4674
4675 /* The SYNC_FLUSH method flushes all pending output to the output buffer
4676 * and the output is aligned on a byte boundary. Flushing may degrade
4677 * compression so it should be used only when necessary, such as at a
4678 * request or response boundary for a network stream.
4679 */
4680 rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
4681
4682 /* Flushes all output as with SYNC_FLUSH, and the compression state is
4683 * reset so that decompression can restart from this point if previous
4684 * compressed data has been damaged or if random access is desired. Like
4685 * SYNC_FLUSH, using FULL_FLUSH too often can seriously degrade
4686 * compression.
4687 */
4688 rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
4689
4690 /* Processes all pending input and flushes pending output. */
4691 rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
4692
4693#if GZIP_SUPPORT
4694 id_write = rb_intern("write");
4695 id_read = rb_intern("read");
4696 id_readpartial = rb_intern("readpartial");
4697 id_flush = rb_intern("flush");
4698 id_seek = rb_intern("seek");
4699 id_close = rb_intern("close");
4700 id_path = rb_intern("path");
4701 id_input = rb_intern("@input");
4702
4703 cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
4704 cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
4705
4706 /* input gzipped string */
4707 rb_define_attr(cGzError, "input", 1, 0);
4708 rb_define_method(cGzError, "inspect", gzfile_error_inspect, 0);
4709
4710 cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
4711 cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
4712 cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
4713
4714 cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
4715 cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
4716 rb_include_module(cGzipReader, rb_mEnumerable);
4717
4718 rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
4719 rb_undef_alloc_func(cGzipFile);
4720 rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
4721 rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
4722 rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
4723 rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
4724 rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
4725 rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
4726 rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
4727 rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
4728 rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
4729 rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
4730 rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
4731 rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
4732 rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
4733 rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
4734 rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
4735 rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
4736 rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
4737 rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
4738 rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
4739 rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
4740 rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
4741 rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
4742 rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
4743
4744 rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
4745 rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
4746 rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
4747 rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
4748 rb_define_method(cGzipWriter, "write", rb_gzwriter_write, -1);
4749 rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
4750 rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
4751 rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
4752 rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
4753 rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
4754
4755 rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
4756 rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
4757 rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
4758 rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
4759 rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
4760 rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
4761 rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
4762 rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
4763 rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
4764 rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
4765 rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
4766 rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
4767 rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
4768 rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
4769 rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
4770 rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
4771 rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
4772 rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
4773 rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
4774 rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
4775 rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
4776 rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
4777 rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0);
4778
4779 rb_define_singleton_method(mZlib, "gzip", zlib_s_gzip, -1);
4780 rb_define_singleton_method(mZlib, "gunzip", zlib_gunzip, 1);
4781
4782 /* The OS code of current host */
4783 rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
4784 /* OS code for MSDOS hosts */
4785 rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
4786 /* OS code for Amiga hosts */
4787 rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
4788 /* OS code for VMS hosts */
4789 rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
4790 /* OS code for UNIX hosts */
4791 rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
4792 /* OS code for Atari hosts */
4793 rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
4794 /* OS code for OS2 hosts */
4795 rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
4796 /* OS code for Mac OS hosts */
4797 rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
4798 /* OS code for TOPS-20 hosts */
4799 rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
4800 /* OS code for Win32 hosts */
4801 rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
4802 /* OS code for VM OS hosts */
4803 rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
4804 /* OS code for Z-System hosts */
4805 rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
4806 /* OS code for CP/M hosts */
4807 rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
4808 /* OS code for QDOS hosts */
4809 rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
4810 /* OS code for RISC OS hosts */
4811 rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
4812 /* OS code for unknown hosts */
4813 rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
4814
4815 id_level = rb_intern("level");
4816 id_strategy = rb_intern("strategy");
4817#endif /* GZIP_SUPPORT */
4818}
4819
4820/* Document error classes. */
4821
4822/*
4823 * Document-class: Zlib::Error
4824 *
4825 * The superclass for all exceptions raised by Ruby/zlib.
4826 *
4827 * The following exceptions are defined as subclasses of Zlib::Error. These
4828 * exceptions are raised when zlib library functions return with an error
4829 * status.
4830 *
4831 * - Zlib::StreamEnd
4832 * - Zlib::NeedDict
4833 * - Zlib::DataError
4834 * - Zlib::StreamError
4835 * - Zlib::MemError
4836 * - Zlib::BufError
4837 * - Zlib::VersionError
4838 * - Zlib::InProgressError
4839 *
4840 */
4841
4842/*
4843 * Document-class: Zlib::StreamEnd
4844 *
4845 * Subclass of Zlib::Error
4846 *
4847 * When zlib returns a Z_STREAM_END
4848 * is return if the end of the compressed data has been reached
4849 * and all uncompressed out put has been produced.
4850 *
4851 */
4852
4853/*
4854 * Document-class: Zlib::NeedDict
4855 *
4856 * Subclass of Zlib::Error
4857 *
4858 * When zlib returns a Z_NEED_DICT
4859 * if a preset dictionary is needed at this point.
4860 *
4861 * Used by Zlib::Inflate.inflate and <tt>Zlib.inflate</tt>
4862 */
4863
4864/*
4865 * Document-class: Zlib::VersionError
4866 *
4867 * Subclass of Zlib::Error
4868 *
4869 * When zlib returns a Z_VERSION_ERROR,
4870 * usually if the zlib library version is incompatible with the
4871 * version assumed by the caller.
4872 *
4873 */
4874
4875/*
4876 * Document-class: Zlib::MemError
4877 *
4878 * Subclass of Zlib::Error
4879 *
4880 * When zlib returns a Z_MEM_ERROR,
4881 * usually if there was not enough memory.
4882 *
4883 */
4884
4885/*
4886 * Document-class: Zlib::StreamError
4887 *
4888 * Subclass of Zlib::Error
4889 *
4890 * When zlib returns a Z_STREAM_ERROR,
4891 * usually if the stream state was inconsistent.
4892 *
4893 */
4894
4895/*
4896 * Document-class: Zlib::BufError
4897 *
4898 * Subclass of Zlib::Error when zlib returns a Z_BUF_ERROR.
4899 *
4900 * Usually if no progress is possible.
4901 *
4902 */
4903
4904/*
4905 * Document-class: Zlib::DataError
4906 *
4907 * Subclass of Zlib::Error when zlib returns a Z_DATA_ERROR.
4908 *
4909 * Usually if a stream was prematurely freed.
4910 *
4911 */
4912
4913/*
4914 * Document-class: Zlib::InProgressError
4915 *
4916 * Subclass of Zlib::Error. This error is raised when the zlib
4917 * stream is currently in progress.
4918 *
4919 * For example:
4920 *
4921 * inflater = Zlib::Inflate.new
4922 * inflater.inflate(compressed) do
4923 * inflater.inflate(compressed) # Raises Zlib::InProgressError
4924 * end
4925 */
4926
4927/*
4928 * Document-class: Zlib::GzipFile::Error
4929 *
4930 * Base class of errors that occur when processing GZIP files.
4931 */
4932
4933/*
4934 * Document-class: Zlib::GzipFile::NoFooter
4935 *
4936 * Raised when gzip file footer is not found.
4937 */
4938
4939/*
4940 * Document-class: Zlib::GzipFile::CRCError
4941 *
4942 * Raised when the CRC checksum recorded in gzip file footer is not equivalent
4943 * to the CRC checksum of the actual uncompressed data.
4944 */
4945
4946/*
4947 * Document-class: Zlib::GzipFile::LengthError
4948 *
4949 * Raised when the data length recorded in the gzip file footer is not equivalent
4950 * to the length of the actual uncompressed data.
4951 */
struct RIMemo * ptr
Definition: debug.c:65
int rb_enc_dummy_p(rb_encoding *enc)
Definition: encoding.c:131
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:416
int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts)
Definition: transcode.c:2555
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Definition: string.c:1030
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:222
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Definition: transcode.c:1429
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Definition: string.c:914
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:195
#define rb_enc_mbmaxlen(enc)
Definition: encoding.h:181
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1860
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2561
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4224
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:194
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:415
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1685
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module(const char *)
Definition: class.c:785
void rb_define_attr(VALUE, const char *, int, int)
Defines (a) public accessor method(s) for an attribute.
Definition: class.c:1831
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
Definition: class.c:1904
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_eEOFError
Definition: ruby.h:2061
VALUE rb_cString
Definition: ruby.h:2046
VALUE rb_mEnumerable
Definition: enum.c:20
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_rescue2(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE, VALUE), VALUE,...)
An equivalent of rescue clause.
Definition: eval.c:962
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
VALUE rb_eStandardError
Definition: error.c:921
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
VALUE rb_eNoMethodError
Definition: error.c:932
VALUE rb_eRuntimeError
Definition: error.c:922
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_exc_new_str(VALUE, VALUE)
Definition: error.c:974
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_rescue(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE, VALUE), VALUE)
An equivalent of rescue clause.
Definition: eval.c:1047
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
VALUE rb_errinfo(void)
The current exception in the current thread.
Definition: eval.c:1882
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
void rb_sys_fail(const char *mesg)
Definition: error.c:2795
VALUE rb_obj_reveal(VALUE obj, VALUE klass)
Make a hidden object visible again.
Definition: object.c:95
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Tries to convert an object into another type.
Definition: object.c:2941
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3106
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5748
unsigned int input
Definition: nkf.c:4325
__uint32_t uint32_t
void * memchr(const void *, int, size_t)
#define rb_str_new2
VALUE rb_str_to_str(VALUE)
Definition: string.c:1382
#define NULL
#define rb_funcallv(recv, mid, argc, argv)
int memcmp(const void *, const void *, size_t)
Definition: memcmp.c:7
#define dp(v)
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
#define UNLIMITED_ARGUMENTS
use StringValue() instead")))
#define RSTRING_LEN(str)
#define _(args)
#define RTEST(v)
VALUE rb_rs
Definition: intern.h:585
VALUE rb_int2inum(intptr_t)
Definition: bignum.c:3208
#define NUM2ULONG(x)
#define T_STRING
VALUE rb_mutex_new(void)
Definition: thread_sync.c:165
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:2037
#define xfree
time_t time(time_t *_timer)
#define LONG2FIX(i)
#define Qundef
const struct rb_call_cache * cc
#define rb_str_cat2
VALUE rb_uint2inum(uintptr_t)
Definition: bignum.c:3201
VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *)
Definition: enumerator.c:516
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
#define RSTRING_END(str)
const VALUE VALUE obj
VALUE rb_io_close(VALUE)
Definition: io.c:4824
#define RSTRING_PTR(str)
const rb_iseq_t const char * error
#define rb_str_new(str, len)
#define NIL_P(v)
#define rb_str_buf_cat
#define NUM2CHR(x)
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
#define ID2SYM(x)
#define RSTRING_LENINT(str)
int fprintf(FILE *__restrict__, const char *__restrict__,...) __attribute__((__format__(__printf__
const char size_t n
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2207
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
#define stderr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
__inline__ const void *__restrict__ src
VALUE rb_time_new(time_t, long)
Definition: time.c:2506
VALUE rb_str_buf_new(long)
Definition: string.c:1315
#define rb_exc_new2
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:522
VALUE rb_str_resurrect(VALUE str)
Definition: string.c:1522
VALUE rb_str_inspect(VALUE)
Definition: string.c:5930
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
#define NUM2UINT(x)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
VALUE rb_file_open_str(VALUE, const char *)
Definition: io.c:6256
__inline__ const void *__restrict__ size_t len
#define INT2NUM(x)
void rb_define_module_function(VALUE, const char *, VALUE(*)(), int)
#define T_HASH
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define long
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RB_GC_GUARD(v)
#define xmalloc2
#define RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define rb_funcall(recv, mid, argc,...)
#define FIX2INT(x)
int VALUE v
VALUE rb_ary_new(void)
Definition: array.c:723
#define rb_scan_args(argc, argvp, fmt,...)
#define RB_PASS_CALLED_KEYWORDS
void rb_gc_mark(VALUE)
Definition: gc.c:5228
#define rb_intern(str)
VALUE rb_mutex_unlock(VALUE mutex)
Definition: thread_sync.c:403
unsigned int size
#define Qtrue
struct rb_call_cache buf
#define memmove(dst, src, len)
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
#define Qnil
#define Qfalse
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
#define ULONG2NUM(x)
#define RB_TYPE_P(obj, type)
#define INT2FIX(i)
void rb_gc_force_recycle(VALUE)
Definition: gc.c:7027
#define UINT_MAX
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
#define TypedData_Make_Struct(klass, type, data_type, sval)
const VALUE * argv
__inline__ int
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
#define FIXNUM_P(f)
#define RETURN_ENUMERATOR(obj, argc, argv)
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:729
if((__builtin_expect(!!(!me), 0)))
#define Check_Type(v, t)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
#define rb_check_arity
void rb_lastline_set(VALUE)
Definition: vm.c:1322
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
#define RBASIC_CLASS(obj)
unsigned long ID
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
const char *void rb_warning(const char *,...) __attribute__((format(printf
const rb_iseq_t const VALUE exc
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
VALUE rb_hash_new(void)
Definition: hash.c:1523
VALUE rb_mutex_lock(VALUE mutex)
Definition: thread_sync.c:333
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:306
#define SIZET2NUM(v)
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
const char * name
Definition: onigmo.h:162
Definition: zlib.c:2263
rb_econv_t * ec
Definition: zlib.c:2278
struct zstream z
Definition: zlib.c:2264
rb_encoding * enc
Definition: zlib.c:2276
VALUE orig_name
Definition: zlib.c:2269
VALUE comment
Definition: zlib.c:2270
time_t mtime
Definition: zlib.c:2268
rb_encoding * enc2
Definition: zlib.c:2277
unsigned long crc
Definition: zlib.c:2271
int level
Definition: zlib.c:2266
void(* end)(struct gzfile *)
Definition: zlib.c:2275
VALUE path
Definition: zlib.c:2280
VALUE io
Definition: zlib.c:2265
int lineno
Definition: zlib.c:2273
int ecflags
Definition: zlib.c:2272
int os_code
Definition: zlib.c:2267
long ungetc
Definition: zlib.c:2274
VALUE ecopts
Definition: zlib.c:2279
VALUE buf
Definition: zlib.c:2300
struct read_raw_arg::@135::@136 in
union read_raw_arg::@135 as
const VALUE argv[2]
Definition: zlib.c:2297
VALUE len
Definition: zlib.c:2299
VALUE io
Definition: zlib.c:2295
int(* reset)(z_streamp)
Definition: zlib.c:537
int(* run)(z_streamp, int)
Definition: zlib.c:539
int(* end)(z_streamp)
Definition: zlib.c:538
int jump_state
Definition: zlib.c:581
int interrupt
Definition: zlib.c:580
struct zstream *const z
Definition: zlib.c:576
int stream_output
Definition: zlib.c:582
Bytef * src
Definition: zlib.c:577
Definition: zlib.c:530
VALUE input
Definition: zlib.c:533
VALUE buf
Definition: zlib.c:532
VALUE mutex
Definition: zlib.c:534
unsigned long flags
Definition: zlib.c:531
z_stream stream
Definition: zlib.c:535
const struct zstream::zstream_funcs * func
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1661
#define RB_NOGVL_UBF_ASYNC_SAFE
Definition: thread.h:26
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Definition: thread.c:1451
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
#define ZSTREAM_READY(z)
Definition: zlib.c:551
#define RUBY_ZLIB_VERSION
Definition: zlib.c:28
#define rb_zlib_crc32_combine
Definition: zlib.c:498
#define ZSTREAM_IS_READY(z)
Definition: zlib.c:552
#define zstream_append_input2(z, v)
Definition: zlib.c:845
#define VALGRIND_MAKE_MEM_DEFINED(p, n)
Definition: zlib.c:24
#define ZSTREAM_BUF_FILLED(z)
Definition: zlib.c:556
#define DEF_MEM_LEVEL
Definition: zlib.c:43
#define GZ_METHOD_DEFLATE
Definition: zlib.c:2223
#define rb_zlib_adler32_combine
Definition: zlib.c:460
#define zstream_append_buffer2(z, v)
Definition: zlib.c:741
#define GZ_FLAG_ENCRYPT
Definition: zlib.c:2228
#define OS_UNIX
Definition: zlib.c:2238
#define GZFILE_READ_SIZE
Definition: zlib.c:2292
#define GZ_FLAG_ORIG_NAME
Definition: zlib.c:2226
NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *))
#define ZSTREAM_FLAG_IN_STREAM
Definition: zlib.c:544
#define GZ_MAGIC1
Definition: zlib.c:2221
#define GZ_EXTRAFLAG_FAST
Definition: zlib.c:2231
#define GZFILE_IS_FINISHED(gz)
Definition: zlib.c:2289
#define zstream_init_deflate(z)
Definition: zlib.c:621
#define OS_RISCOS
Definition: zlib.c:2249
#define rb_gzwriter_puts
Definition: zlib.c:3703
#define OS_CPM
Definition: zlib.c:2247
#define rb_gzwriter_addstr
Definition: zlib.c:3688
#define zstream_init_inflate(z)
Definition: zlib.c:622
#define rb_gzwriter_printf
Definition: zlib.c:3693
#define gzfile_writer_new(gz)
Definition: zlib.c:2379
#define zstream_deflate_new(klass)
Definition: zlib.c:1254
#define GZ_FLAG_MULTIPART
Definition: zlib.c:2224
#define ZSTREAM_FLAG_READY
Definition: zlib.c:543
#define GZFILE_FLAG_SYNC
Definition: zlib.c:2284
#define ZSTREAM_INITIAL_BUFSIZE
Definition: zlib.c:562
#define GZFILE_FLAG_FOOTER_FINISHED
Definition: zlib.c:2286
#define ZSTREAM_IS_GZFILE(z)
Definition: zlib.c:555
#define OS_OS2
Definition: zlib.c:2240
#define GZ_EXTRAFLAG_SLOW
Definition: zlib.c:2232
#define OS_MSDOS
Definition: zlib.c:2235
#define OS_ZSYSTEM
Definition: zlib.c:2246
#define checksum_long(func, sum, ptr, len)
Definition: zlib.c:387
#define ARG_MEMLEVEL(val)
Definition: zlib.c:1521
#define GZ_FLAG_COMMENT
Definition: zlib.c:2227
#define rb_gzwriter_print
Definition: zlib.c:3698
#define GZFILE_CBUF_CAPA
Definition: zlib.c:2282
#define OS_CODE
Definition: zlib.c:2253
#define ZSTREAM_IN_PROGRESS
Definition: zlib.c:548
#define OS_VMCMS
Definition: zlib.c:2245
#define OS_TOPS20
Definition: zlib.c:2242
#define OS_VMS
Definition: zlib.c:2237
#define ARG_WBITS(val)
Definition: zlib.c:1520
#define ZSTREAM_FLAG_FINISHED
Definition: zlib.c:545
#define gzfile_reader_new(gz)
Definition: zlib.c:2380
#define OS_AMIGA
Definition: zlib.c:2236
#define GZ_FLAG_UNKNOWN_MASK
Definition: zlib.c:2229
#define MAX_UINT(n)
Definition: zlib.c:56
#define OS_WIN32
Definition: zlib.c:2243
#define GZFILE_FLAG_MTIME_IS_SET
Definition: zlib.c:2287
#define OS_UNKNOWN
Definition: zlib.c:2250
#define ZSTREAM_AVAIL_OUT_STEP_MAX
Definition: zlib.c:564
#define ZSTREAM_FLAG_GZFILE
Definition: zlib.c:547
#define OS_QDOS
Definition: zlib.c:2248
#define ZSTREAM_IS_FINISHED(z)
Definition: zlib.c:553
void Init_zlib(void)
Definition: zlib.c:4509
#define ARG_LEVEL(val)
Definition: zlib.c:1519
#define OPTHASH_GIVEN_P(opts)
Definition: zlib.c:4357
#define OS_MACOS
Definition: zlib.c:2241
#define GZFILE_FLAG_HEADER_FINISHED
Definition: zlib.c:2285
#define GZ_MAGIC2
Definition: zlib.c:2222
#define ZSTREAM_AVAIL_OUT_STEP_MIN
Definition: zlib.c:565
#define ZSTREAM_FLAG_CLOSING
Definition: zlib.c:546
#define FIXNUMARG(val, ifnil)
Definition: zlib.c:1515
#define OS_ATARI
Definition: zlib.c:2239
#define GZ_FLAG_EXTRA
Definition: zlib.c:2225
#define zstream_inflate_new(klass)
Definition: zlib.c:1255
#define ZSTREAM_IS_CLOSING(z)
Definition: zlib.c:554
#define ARG_FLUSH(val)
Definition: zlib.c:1523
#define ZSTREAM_EXPAND_BUFFER_OK
Definition: zlib.c:558
#define ARG_STRATEGY(val)
Definition: zlib.c:1522