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