Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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