00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <ruby.h>
00010 #include <zlib.h>
00011 #include <time.h>
00012 #include <ruby/io.h>
00013 #include <ruby/thread.h>
00014
00015 #ifdef HAVE_VALGRIND_MEMCHECK_H
00016 # include <valgrind/memcheck.h>
00017 # ifndef VALGRIND_MAKE_MEM_DEFINED
00018 # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
00019 # endif
00020 # ifndef VALGRIND_MAKE_MEM_UNDEFINED
00021 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
00022 # endif
00023 #else
00024 # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
00025 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
00026 #endif
00027
00028 #define RUBY_ZLIB_VERSION "0.6.0"
00029
00030
00031 #define OBJ_IS_FREED(val) (RBASIC(val)->flags == 0)
00032
00033 #ifndef GZIP_SUPPORT
00034 #define GZIP_SUPPORT 1
00035 #endif
00036
00037
00038 #ifndef DEF_MEM_LEVEL
00039 #if MAX_MEM_LEVEL >= 8
00040 #define DEF_MEM_LEVEL 8
00041 #else
00042 #define DEF_MEM_LEVEL MAX_MEM_LEVEL
00043 #endif
00044 #endif
00045
00046 #if SIZEOF_LONG > SIZEOF_INT
00047 static inline uInt
00048 max_uint(long n)
00049 {
00050 if (n > UINT_MAX) n = UINT_MAX;
00051 return (uInt)n;
00052 }
00053 #define MAX_UINT(n) max_uint(n)
00054 #else
00055 #define MAX_UINT(n) (uInt)(n)
00056 #endif
00057
00058 #define sizeof(x) ((int)sizeof(x))
00059
00060 static ID id_dictionaries;
00061
00062
00063
00064 static NORETURN(void raise_zlib_error(int, const char*));
00065 static VALUE rb_zlib_version(VALUE);
00066 static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
00067 static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
00068 static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
00069 static VALUE rb_zlib_crc_table(VALUE);
00070 static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
00071 static void zlib_mem_free(voidpf, voidpf);
00072 static void finalizer_warn(const char*);
00073
00074 struct zstream;
00075 struct zstream_funcs;
00076 struct zstream_run_args;
00077 static void zstream_init(struct zstream*, const struct zstream_funcs*);
00078 static void zstream_expand_buffer(struct zstream*);
00079 static void zstream_expand_buffer_into(struct zstream*, unsigned long);
00080 static void zstream_append_buffer(struct zstream*, const Bytef*, long);
00081 static VALUE zstream_detach_buffer(struct zstream*);
00082 static VALUE zstream_shift_buffer(struct zstream*, long);
00083 static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
00084 static void zstream_buffer_ungetbyte(struct zstream*, int);
00085 static void zstream_append_input(struct zstream*, const Bytef*, long);
00086 static void zstream_discard_input(struct zstream*, long);
00087 static void zstream_reset_input(struct zstream*);
00088 static void zstream_passthrough_input(struct zstream*);
00089 static VALUE zstream_detach_input(struct zstream*);
00090 static void zstream_reset(struct zstream*);
00091 static VALUE zstream_end(struct zstream*);
00092 static void zstream_run(struct zstream*, Bytef*, long, int);
00093 static VALUE zstream_sync(struct zstream*, Bytef*, long);
00094 static void zstream_mark(struct zstream*);
00095 static void zstream_free(struct zstream*);
00096 static VALUE zstream_new(VALUE, const struct zstream_funcs*);
00097 static struct zstream *get_zstream(VALUE);
00098 static void zstream_finalize(struct zstream*);
00099
00100 static VALUE rb_zstream_end(VALUE);
00101 static VALUE rb_zstream_reset(VALUE);
00102 static VALUE rb_zstream_finish(VALUE);
00103 static VALUE rb_zstream_flush_next_in(VALUE);
00104 static VALUE rb_zstream_flush_next_out(VALUE);
00105 static VALUE rb_zstream_avail_out(VALUE);
00106 static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
00107 static VALUE rb_zstream_avail_in(VALUE);
00108 static VALUE rb_zstream_total_in(VALUE);
00109 static VALUE rb_zstream_total_out(VALUE);
00110 static VALUE rb_zstream_data_type(VALUE);
00111 static VALUE rb_zstream_adler(VALUE);
00112 static VALUE rb_zstream_finished_p(VALUE);
00113 static VALUE rb_zstream_closed_p(VALUE);
00114
00115 static VALUE rb_deflate_s_allocate(VALUE);
00116 static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
00117 static VALUE rb_deflate_init_copy(VALUE, VALUE);
00118 static VALUE deflate_run(VALUE);
00119 static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
00120 static void do_deflate(struct zstream*, VALUE, int);
00121 static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
00122 static VALUE rb_deflate_addstr(VALUE, VALUE);
00123 static VALUE rb_deflate_flush(int, VALUE*, VALUE);
00124 static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
00125 static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
00126
00127 static VALUE inflate_run(VALUE);
00128 static VALUE rb_inflate_s_allocate(VALUE);
00129 static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
00130 static VALUE rb_inflate_s_inflate(VALUE, VALUE);
00131 static void do_inflate(struct zstream*, VALUE);
00132 static VALUE rb_inflate_inflate(VALUE, VALUE);
00133 static VALUE rb_inflate_addstr(VALUE, VALUE);
00134 static VALUE rb_inflate_sync(VALUE, VALUE);
00135 static VALUE rb_inflate_sync_point_p(VALUE);
00136 static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
00137
00138 #if GZIP_SUPPORT
00139 struct gzfile;
00140 static void gzfile_mark(struct gzfile*);
00141 static void gzfile_free(struct gzfile*);
00142 static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
00143 static void gzfile_reset(struct gzfile*);
00144 static void gzfile_close(struct gzfile*, int);
00145 static void gzfile_write_raw(struct gzfile*);
00146 static VALUE gzfile_read_raw_partial(VALUE);
00147 static VALUE gzfile_read_raw_rescue(VALUE);
00148 static VALUE gzfile_read_raw(struct gzfile*);
00149 static int gzfile_read_raw_ensure(struct gzfile*, long);
00150 static char *gzfile_read_raw_until_zero(struct gzfile*, long);
00151 static unsigned int gzfile_get16(const unsigned char*);
00152 static unsigned long gzfile_get32(const unsigned char*);
00153 static void gzfile_set32(unsigned long n, unsigned char*);
00154 static void gzfile_make_header(struct gzfile*);
00155 static void gzfile_make_footer(struct gzfile*);
00156 static void gzfile_read_header(struct gzfile*);
00157 static void gzfile_check_footer(struct gzfile*);
00158 static void gzfile_write(struct gzfile*, Bytef*, long);
00159 static long gzfile_read_more(struct gzfile*);
00160 static void gzfile_calc_crc(struct gzfile*, VALUE);
00161 static VALUE gzfile_read(struct gzfile*, long);
00162 static VALUE gzfile_read_all(struct gzfile*);
00163 static void gzfile_ungets(struct gzfile*, const Bytef*, long);
00164 static void gzfile_ungetbyte(struct gzfile*, int);
00165 static VALUE gzfile_writer_end_run(VALUE);
00166 static void gzfile_writer_end(struct gzfile*);
00167 static VALUE gzfile_reader_end_run(VALUE);
00168 static void gzfile_reader_end(struct gzfile*);
00169 static void gzfile_reader_rewind(struct gzfile*);
00170 static VALUE gzfile_reader_get_unused(struct gzfile*);
00171 static struct gzfile *get_gzfile(VALUE);
00172 static VALUE gzfile_ensure_close(VALUE);
00173 static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
00174 static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
00175 NORETURN(static void gzfile_raise(struct gzfile *, VALUE, const char *));
00176 static VALUE gzfile_error_inspect(VALUE);
00177
00178 static VALUE rb_gzfile_to_io(VALUE);
00179 static VALUE rb_gzfile_crc(VALUE);
00180 static VALUE rb_gzfile_mtime(VALUE);
00181 static VALUE rb_gzfile_level(VALUE);
00182 static VALUE rb_gzfile_os_code(VALUE);
00183 static VALUE rb_gzfile_orig_name(VALUE);
00184 static VALUE rb_gzfile_comment(VALUE);
00185 static VALUE rb_gzfile_lineno(VALUE);
00186 static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
00187 static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
00188 static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
00189 static VALUE rb_gzfile_set_comment(VALUE, VALUE);
00190 static VALUE rb_gzfile_close(VALUE);
00191 static VALUE rb_gzfile_finish(VALUE);
00192 static VALUE rb_gzfile_closed_p(VALUE);
00193 static VALUE rb_gzfile_eof_p(VALUE);
00194 static VALUE rb_gzfile_sync(VALUE);
00195 static VALUE rb_gzfile_set_sync(VALUE, VALUE);
00196 static VALUE rb_gzfile_total_in(VALUE);
00197 static VALUE rb_gzfile_total_out(VALUE);
00198 static VALUE rb_gzfile_path(VALUE);
00199
00200 static VALUE rb_gzwriter_s_allocate(VALUE);
00201 static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
00202 static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
00203 static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
00204 static VALUE rb_gzwriter_write(VALUE, VALUE);
00205 static VALUE rb_gzwriter_putc(VALUE, VALUE);
00206
00207 static VALUE rb_gzreader_s_allocate(VALUE);
00208 static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
00209 static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
00210 static VALUE rb_gzreader_rewind(VALUE);
00211 static VALUE rb_gzreader_unused(VALUE);
00212 static VALUE rb_gzreader_read(int, VALUE*, VALUE);
00213 static VALUE rb_gzreader_getc(VALUE);
00214 static VALUE rb_gzreader_readchar(VALUE);
00215 static VALUE rb_gzreader_each_byte(VALUE);
00216 static VALUE rb_gzreader_ungetc(VALUE, VALUE);
00217 static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
00218 static void gzreader_skip_linebreaks(struct gzfile*);
00219 static VALUE gzreader_gets(int, VALUE*, VALUE);
00220 static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
00221 static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
00222 static VALUE rb_gzreader_each(int, VALUE*, VALUE);
00223 static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 void Init_zlib(void);
00299
00300
00301
00302 static VALUE cZError, cStreamEnd, cNeedDict;
00303 static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
00304
00305 static void
00306 raise_zlib_error(int err, const char *msg)
00307 {
00308 VALUE exc;
00309
00310 if (!msg) {
00311 msg = zError(err);
00312 }
00313
00314 switch(err) {
00315 case Z_STREAM_END:
00316 exc = rb_exc_new2(cStreamEnd, msg);
00317 break;
00318 case Z_NEED_DICT:
00319 exc = rb_exc_new2(cNeedDict, msg);
00320 break;
00321 case Z_STREAM_ERROR:
00322 exc = rb_exc_new2(cStreamError, msg);
00323 break;
00324 case Z_DATA_ERROR:
00325 exc = rb_exc_new2(cDataError, msg);
00326 break;
00327 case Z_BUF_ERROR:
00328 exc = rb_exc_new2(cBufError, msg);
00329 break;
00330 case Z_VERSION_ERROR:
00331 exc = rb_exc_new2(cVersionError, msg);
00332 break;
00333 case Z_MEM_ERROR:
00334 exc = rb_exc_new2(cMemError, msg);
00335 break;
00336 case Z_ERRNO:
00337 rb_sys_fail(msg);
00338
00339 default:
00340 exc = rb_exc_new3(cZError,
00341 rb_sprintf("unknown zlib error %d: %s", err, msg));
00342 }
00343
00344 rb_exc_raise(exc);
00345 }
00346
00347
00348
00349
00350 static void
00351 finalizer_warn(const char *msg)
00352 {
00353 fprintf(stderr, "zlib(finalizer): %s\n", msg);
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 static VALUE
00365 rb_zlib_version(VALUE klass)
00366 {
00367 VALUE str;
00368
00369 str = rb_str_new2(zlibVersion());
00370 OBJ_TAINT(str);
00371 return str;
00372 }
00373
00374 #if SIZEOF_LONG > SIZEOF_INT
00375 static uLong
00376 checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
00377 {
00378 if (len > UINT_MAX) {
00379 do {
00380 sum = func(sum, ptr, UINT_MAX);
00381 ptr += UINT_MAX;
00382 len -= UINT_MAX;
00383 } while (len >= UINT_MAX);
00384 }
00385 if (len > 0) sum = func(sum, ptr, (uInt)len);
00386 return sum;
00387 }
00388 #else
00389 #define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
00390 #endif
00391
00392 static VALUE
00393 do_checksum(argc, argv, func)
00394 int argc;
00395 VALUE *argv;
00396 uLong (*func)(uLong, const Bytef*, uInt);
00397 {
00398 VALUE str, vsum;
00399 unsigned long sum;
00400
00401 rb_scan_args(argc, argv, "02", &str, &vsum);
00402
00403 if (!NIL_P(vsum)) {
00404 sum = NUM2ULONG(vsum);
00405 }
00406 else if (NIL_P(str)) {
00407 sum = 0;
00408 }
00409 else {
00410 sum = func(0, Z_NULL, 0);
00411 }
00412
00413 if (NIL_P(str)) {
00414 sum = func(sum, Z_NULL, 0);
00415 }
00416 else {
00417 StringValue(str);
00418 sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
00419 }
00420 return rb_uint2inum(sum);
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 static VALUE
00435 rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
00436 {
00437 return do_checksum(argc, argv, adler32);
00438 }
00439
00440 #ifdef HAVE_ADLER32_COMBINE
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 static VALUE
00452 rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
00453 {
00454 return ULONG2NUM(
00455 adler32_combine(NUM2ULONG(adler1), NUM2ULONG(adler2), NUM2LONG(len2)));
00456 }
00457 #else
00458 #define rb_zlib_adler32_combine rb_f_notimplement
00459 #endif
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 static VALUE
00473 rb_zlib_crc32(int argc, VALUE *argv, VALUE klass)
00474 {
00475 return do_checksum(argc, argv, crc32);
00476 }
00477
00478 #ifdef HAVE_CRC32_COMBINE
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 static VALUE
00490 rb_zlib_crc32_combine(VALUE klass, VALUE crc1, VALUE crc2, VALUE len2)
00491 {
00492 return ULONG2NUM(
00493 crc32_combine(NUM2ULONG(crc1), NUM2ULONG(crc2), NUM2LONG(len2)));
00494 }
00495 #else
00496 #define rb_zlib_crc32_combine rb_f_notimplement
00497 #endif
00498
00499
00500
00501
00502
00503
00504 static VALUE
00505 rb_zlib_crc_table(VALUE obj)
00506 {
00507 #if !defined(HAVE_TYPE_Z_CRC_T)
00508
00509 typedef unsigned long z_crc_t;
00510 #endif
00511 const z_crc_t *crctbl;
00512 VALUE dst;
00513 int i;
00514
00515 crctbl = get_crc_table();
00516 dst = rb_ary_new2(256);
00517
00518 for (i = 0; i < 256; i++) {
00519 rb_ary_push(dst, rb_uint2inum(crctbl[i]));
00520 }
00521 return dst;
00522 }
00523
00524
00525
00526
00527
00528 struct zstream {
00529 unsigned long flags;
00530 VALUE buf;
00531 long buf_filled;
00532 VALUE input;
00533 z_stream stream;
00534 const struct zstream_funcs {
00535 int (*reset)(z_streamp);
00536 int (*end)(z_streamp);
00537 int (*run)(z_streamp, int);
00538 } *func;
00539 };
00540
00541 #define ZSTREAM_FLAG_READY 0x1
00542 #define ZSTREAM_FLAG_IN_STREAM 0x2
00543 #define ZSTREAM_FLAG_FINISHED 0x4
00544 #define ZSTREAM_FLAG_CLOSING 0x8
00545 #define ZSTREAM_FLAG_GZFILE 0x10
00546
00547 #define ZSTREAM_FLAG_UNUSED 0x20
00548
00549 #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
00550 #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
00551 #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED)
00552 #define ZSTREAM_IS_CLOSING(z) ((z)->flags & ZSTREAM_FLAG_CLOSING)
00553 #define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
00554
00555 #define ZSTREAM_EXPAND_BUFFER_OK 0
00556
00557
00558
00559 #define ZSTREAM_INITIAL_BUFSIZE 1024
00560
00561 #define ZSTREAM_AVAIL_OUT_STEP_MAX 16384
00562 #define ZSTREAM_AVAIL_OUT_STEP_MIN 2048
00563
00564 static const struct zstream_funcs deflate_funcs = {
00565 deflateReset, deflateEnd, deflate,
00566 };
00567
00568 static const struct zstream_funcs inflate_funcs = {
00569 inflateReset, inflateEnd, inflate,
00570 };
00571
00572 struct zstream_run_args {
00573 struct zstream * z;
00574 int flush;
00575 int interrupt;
00576 int jump_state;
00577 int stream_output;
00578 };
00579
00580 static voidpf
00581 zlib_mem_alloc(voidpf opaque, uInt items, uInt size)
00582 {
00583 voidpf p = xmalloc(items * size);
00584
00585
00586
00587
00588 (void)VALGRIND_MAKE_MEM_DEFINED(p, items * size);
00589 return p;
00590 }
00591
00592 static void
00593 zlib_mem_free(voidpf opaque, voidpf address)
00594 {
00595 xfree(address);
00596 }
00597
00598 static void
00599 zstream_init(struct zstream *z, const struct zstream_funcs *func)
00600 {
00601 z->flags = 0;
00602 z->buf = Qnil;
00603 z->buf_filled = 0;
00604 z->input = Qnil;
00605 z->stream.zalloc = zlib_mem_alloc;
00606 z->stream.zfree = zlib_mem_free;
00607 z->stream.opaque = Z_NULL;
00608 z->stream.msg = Z_NULL;
00609 z->stream.next_in = Z_NULL;
00610 z->stream.avail_in = 0;
00611 z->stream.next_out = Z_NULL;
00612 z->stream.avail_out = 0;
00613 z->func = func;
00614 }
00615
00616 #define zstream_init_deflate(z) zstream_init((z), &deflate_funcs)
00617 #define zstream_init_inflate(z) zstream_init((z), &inflate_funcs)
00618
00619 static void
00620 zstream_expand_buffer(struct zstream *z)
00621 {
00622 if (NIL_P(z->buf)) {
00623 zstream_expand_buffer_into(z, ZSTREAM_INITIAL_BUFSIZE);
00624 return;
00625 }
00626
00627 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
00628 if (z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00629 int state = 0;
00630 VALUE self = (VALUE)z->stream.opaque;
00631
00632 rb_str_resize(z->buf, z->buf_filled);
00633 RBASIC(z->buf)->klass = rb_cString;
00634 OBJ_INFECT(z->buf, self);
00635
00636 rb_protect(rb_yield, z->buf, &state);
00637
00638 z->buf = Qnil;
00639 zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
00640
00641 if (state)
00642 rb_jump_tag(state);
00643
00644 return;
00645 }
00646 else {
00647 zstream_expand_buffer_into(z,
00648 ZSTREAM_AVAIL_OUT_STEP_MAX - z->buf_filled);
00649 }
00650 }
00651 else {
00652 if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00653 z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
00654 }
00655 else {
00656 long inc = z->buf_filled / 2;
00657 if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
00658 inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
00659 }
00660 rb_str_resize(z->buf, z->buf_filled + inc);
00661 z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
00662 (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
00663 }
00664 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00665 }
00666 }
00667
00668 static void
00669 zstream_expand_buffer_into(struct zstream *z, unsigned long size)
00670 {
00671 if (NIL_P(z->buf)) {
00672
00673
00674 z->buf = rb_str_new(0, size);
00675 z->buf_filled = 0;
00676 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
00677 z->stream.avail_out = MAX_UINT(size);
00678 RBASIC(z->buf)->klass = 0;
00679 }
00680 else if (z->stream.avail_out != size) {
00681 rb_str_resize(z->buf, z->buf_filled + size);
00682 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00683 z->stream.avail_out = MAX_UINT(size);
00684 }
00685 }
00686
00687 static void *
00688 zstream_expand_buffer_protect(void *ptr)
00689 {
00690 struct zstream *z = (struct zstream *)ptr;
00691 int state = 0;
00692
00693 rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
00694
00695 return (void *)(VALUE)state;
00696 }
00697
00698 static int
00699 zstream_expand_buffer_without_gvl(struct zstream *z)
00700 {
00701 char * new_str;
00702 long inc, len;
00703
00704 if (RSTRING_LEN(z->buf) - z->buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
00705 z->stream.avail_out = ZSTREAM_AVAIL_OUT_STEP_MAX;
00706 }
00707 else {
00708 inc = z->buf_filled / 2;
00709 if (inc < ZSTREAM_AVAIL_OUT_STEP_MIN) {
00710 inc = ZSTREAM_AVAIL_OUT_STEP_MIN;
00711 }
00712
00713 len = z->buf_filled + inc;
00714
00715 new_str = ruby_xrealloc(RSTRING(z->buf)->as.heap.ptr, len + 1);
00716
00717
00718 RSTRING(z->buf)->as.heap.ptr = new_str;
00719 RSTRING(z->buf)->as.heap.ptr[len] = '\0';
00720 RSTRING(z->buf)->as.heap.len =
00721 RSTRING(z->buf)->as.heap.aux.capa = len;
00722
00723 z->stream.avail_out = (inc < ZSTREAM_AVAIL_OUT_STEP_MAX) ?
00724 (int)inc : ZSTREAM_AVAIL_OUT_STEP_MAX;
00725 }
00726 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00727
00728 return ZSTREAM_EXPAND_BUFFER_OK;
00729 }
00730
00731 static void
00732 zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
00733 {
00734 if (NIL_P(z->buf)) {
00735 z->buf = rb_str_buf_new(len);
00736 rb_str_buf_cat(z->buf, (const char*)src, len);
00737 z->buf_filled = len;
00738 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
00739 z->stream.avail_out = 0;
00740 RBASIC(z->buf)->klass = 0;
00741 return;
00742 }
00743
00744 if (RSTRING_LEN(z->buf) < z->buf_filled + len) {
00745 rb_str_resize(z->buf, z->buf_filled + len);
00746 z->stream.avail_out = 0;
00747 }
00748 else {
00749 if (z->stream.avail_out >= (uInt)len) {
00750 z->stream.avail_out -= (uInt)len;
00751 }
00752 else {
00753 z->stream.avail_out = 0;
00754 }
00755 }
00756 memcpy(RSTRING_PTR(z->buf) + z->buf_filled, src, len);
00757 z->buf_filled += len;
00758 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00759 }
00760
00761 #define zstream_append_buffer2(z,v) \
00762 zstream_append_buffer((z),(Bytef*)RSTRING_PTR(v),RSTRING_LEN(v))
00763
00764 static VALUE
00765 zstream_detach_buffer(struct zstream *z)
00766 {
00767 VALUE dst, self = (VALUE)z->stream.opaque;
00768
00769 if (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
00770 rb_block_given_p()) {
00771
00772
00773 return Qnil;
00774 }
00775
00776 if (NIL_P(z->buf)) {
00777 dst = rb_str_new(0, 0);
00778 }
00779 else {
00780 dst = z->buf;
00781 rb_str_resize(dst, z->buf_filled);
00782 RBASIC(dst)->klass = rb_cString;
00783 }
00784
00785 OBJ_INFECT(dst, self);
00786
00787 z->buf = Qnil;
00788 z->buf_filled = 0;
00789 z->stream.next_out = 0;
00790 z->stream.avail_out = 0;
00791
00792 if (!ZSTREAM_IS_GZFILE(z) && rb_block_given_p()) {
00793 rb_yield(dst);
00794 dst = Qnil;
00795 }
00796
00797 return dst;
00798 }
00799
00800 static VALUE
00801 zstream_shift_buffer(struct zstream *z, long len)
00802 {
00803 VALUE dst;
00804 long buflen;
00805
00806 if (z->buf_filled <= len) {
00807 return zstream_detach_buffer(z);
00808 }
00809
00810 dst = rb_str_subseq(z->buf, 0, len);
00811 RBASIC(dst)->klass = rb_cString;
00812 z->buf_filled -= len;
00813 memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
00814 z->buf_filled);
00815 z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf) + z->buf_filled;
00816 buflen = RSTRING_LEN(z->buf) - z->buf_filled;
00817 if (buflen > ZSTREAM_AVAIL_OUT_STEP_MAX) {
00818 buflen = ZSTREAM_AVAIL_OUT_STEP_MAX;
00819 }
00820 z->stream.avail_out = (uInt)buflen;
00821
00822 return dst;
00823 }
00824
00825 static void
00826 zstream_buffer_ungets(struct zstream *z, const Bytef *b, unsigned long len)
00827 {
00828 if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
00829 zstream_expand_buffer_into(z, len);
00830 }
00831
00832 memmove(RSTRING_PTR(z->buf) + len, RSTRING_PTR(z->buf), z->buf_filled);
00833 memmove(RSTRING_PTR(z->buf), b, len);
00834 z->buf_filled+=len;
00835 if (z->stream.avail_out > 0) {
00836 if (len > z->stream.avail_out) len = z->stream.avail_out;
00837 z->stream.next_out+=len;
00838 z->stream.avail_out-=(uInt)len;
00839 }
00840 }
00841
00842 static void
00843 zstream_buffer_ungetbyte(struct zstream *z, int c)
00844 {
00845 if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
00846 zstream_expand_buffer(z);
00847 }
00848
00849 memmove(RSTRING_PTR(z->buf) + 1, RSTRING_PTR(z->buf), z->buf_filled);
00850 RSTRING_PTR(z->buf)[0] = (char)c;
00851 z->buf_filled++;
00852 if (z->stream.avail_out > 0) {
00853 z->stream.next_out++;
00854 z->stream.avail_out--;
00855 }
00856 }
00857
00858 static void
00859 zstream_append_input(struct zstream *z, const Bytef *src, long len)
00860 {
00861 if (len <= 0) return;
00862
00863 if (NIL_P(z->input)) {
00864 z->input = rb_str_buf_new(len);
00865 rb_str_buf_cat(z->input, (const char*)src, len);
00866 RBASIC(z->input)->klass = 0;
00867 }
00868 else {
00869 rb_str_buf_cat(z->input, (const char*)src, len);
00870 }
00871 }
00872
00873 #define zstream_append_input2(z,v)\
00874 RB_GC_GUARD(v),\
00875 zstream_append_input((z), (Bytef*)RSTRING_PTR(v), RSTRING_LEN(v))
00876
00877 static void
00878 zstream_discard_input(struct zstream *z, long len)
00879 {
00880 if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
00881 z->input = Qnil;
00882 }
00883 else {
00884 memmove(RSTRING_PTR(z->input), RSTRING_PTR(z->input) + len,
00885 RSTRING_LEN(z->input) - len);
00886 rb_str_resize(z->input, RSTRING_LEN(z->input) - len);
00887 }
00888 }
00889
00890 static void
00891 zstream_reset_input(struct zstream *z)
00892 {
00893 z->input = Qnil;
00894 }
00895
00896 static void
00897 zstream_passthrough_input(struct zstream *z)
00898 {
00899 if (!NIL_P(z->input)) {
00900 zstream_append_buffer2(z, z->input);
00901 z->input = Qnil;
00902 }
00903 }
00904
00905 static VALUE
00906 zstream_detach_input(struct zstream *z)
00907 {
00908 VALUE dst;
00909
00910 if (NIL_P(z->input)) {
00911 dst = rb_str_new(0, 0);
00912 }
00913 else {
00914 dst = z->input;
00915 RBASIC(dst)->klass = rb_cString;
00916 }
00917 z->input = Qnil;
00918 RBASIC(dst)->klass = rb_cString;
00919 return dst;
00920 }
00921
00922 static void
00923 zstream_reset(struct zstream *z)
00924 {
00925 int err;
00926
00927 err = z->func->reset(&z->stream);
00928 if (err != Z_OK) {
00929 raise_zlib_error(err, z->stream.msg);
00930 }
00931 z->flags = ZSTREAM_FLAG_READY;
00932 z->buf = Qnil;
00933 z->buf_filled = 0;
00934 z->stream.next_out = 0;
00935 z->stream.avail_out = 0;
00936 zstream_reset_input(z);
00937 }
00938
00939 static VALUE
00940 zstream_end(struct zstream *z)
00941 {
00942 int err;
00943
00944 if (!ZSTREAM_IS_READY(z)) {
00945 rb_warning("attempt to close uninitialized zstream; ignored.");
00946 return Qnil;
00947 }
00948 if (z->flags & ZSTREAM_FLAG_IN_STREAM) {
00949 rb_warning("attempt to close unfinished zstream; reset forced.");
00950 zstream_reset(z);
00951 }
00952
00953 zstream_reset_input(z);
00954 err = z->func->end(&z->stream);
00955 if (err != Z_OK) {
00956 raise_zlib_error(err, z->stream.msg);
00957 }
00958 z->flags = 0;
00959 return Qnil;
00960 }
00961
00962 static void *
00963 zstream_run_func(void *ptr)
00964 {
00965 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
00966 int err, state, flush = args->flush;
00967 struct zstream *z = args->z;
00968 uInt n;
00969
00970 err = Z_OK;
00971 while (!args->interrupt) {
00972 n = z->stream.avail_out;
00973 err = z->func->run(&z->stream, flush);
00974 z->buf_filled += n - z->stream.avail_out;
00975
00976 if (err == Z_STREAM_END) {
00977 z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
00978 z->flags |= ZSTREAM_FLAG_FINISHED;
00979 break;
00980 }
00981
00982 if (err != Z_OK && err != Z_BUF_ERROR)
00983 break;
00984
00985 if (z->stream.avail_out > 0) {
00986 z->flags |= ZSTREAM_FLAG_IN_STREAM;
00987 break;
00988 }
00989
00990 if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
00991
00992
00993
00994 z->flags |= ZSTREAM_FLAG_IN_STREAM;
00995 break;
00996 }
00997
00998 if (args->stream_output) {
00999 state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
01000 (void *)z);
01001 } else {
01002 state = zstream_expand_buffer_without_gvl(z);
01003 }
01004
01005 if (state) {
01006 err = Z_OK;
01007 args->jump_state = state;
01008 break;
01009 }
01010 }
01011
01012 return (void *)(VALUE)err;
01013 }
01014
01015
01016
01017
01018 static void
01019 zstream_unblock_func(void *ptr)
01020 {
01021 struct zstream_run_args *args = (struct zstream_run_args *)ptr;
01022
01023 args->interrupt = 1;
01024 }
01025
01026 static void
01027 zstream_run(struct zstream *z, Bytef *src, long len, int flush)
01028 {
01029 struct zstream_run_args args;
01030 int err;
01031 volatile VALUE guard = Qnil;
01032
01033 args.z = z;
01034 args.flush = flush;
01035 args.interrupt = 0;
01036 args.jump_state = 0;
01037 args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
01038
01039 if (NIL_P(z->input) && len == 0) {
01040 z->stream.next_in = (Bytef*)"";
01041 z->stream.avail_in = 0;
01042 }
01043 else {
01044 zstream_append_input(z, src, len);
01045 z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
01046 z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
01047
01048
01049
01050 guard = z->input;
01051 }
01052
01053 if (z->stream.avail_out == 0) {
01054 zstream_expand_buffer(z);
01055 }
01056
01057 loop:
01058 err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
01059 zstream_unblock_func, (void *)&args);
01060
01061 if (flush != Z_FINISH && err == Z_BUF_ERROR
01062 && z->stream.avail_out > 0) {
01063 z->flags |= ZSTREAM_FLAG_IN_STREAM;
01064 }
01065
01066 zstream_reset_input(z);
01067
01068 if (err != Z_OK && err != Z_STREAM_END) {
01069 if (z->stream.avail_in > 0) {
01070 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01071 }
01072 if (err == Z_NEED_DICT) {
01073 VALUE self = (VALUE)z->stream.opaque;
01074 if (self) {
01075 VALUE dicts = rb_ivar_get(self, id_dictionaries);
01076 VALUE dict = rb_hash_aref(dicts, rb_uint2inum(z->stream.adler));
01077 if (!NIL_P(dict)) {
01078 rb_inflate_set_dictionary(self, dict);
01079 goto loop;
01080 }
01081 }
01082 }
01083 raise_zlib_error(err, z->stream.msg);
01084 }
01085
01086 if (z->stream.avail_in > 0) {
01087 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01088 RB_GC_GUARD(guard) = Qnil;
01089 }
01090
01091 if (args.jump_state)
01092 rb_jump_tag(args.jump_state);
01093 }
01094
01095 static VALUE
01096 zstream_sync(struct zstream *z, Bytef *src, long len)
01097 {
01098
01099 int err;
01100
01101 if (!NIL_P(z->input)) {
01102 z->stream.next_in = (Bytef*)RSTRING_PTR(z->input);
01103 z->stream.avail_in = MAX_UINT(RSTRING_LEN(z->input));
01104 err = inflateSync(&z->stream);
01105 if (err == Z_OK) {
01106 zstream_discard_input(z,
01107 RSTRING_LEN(z->input) - z->stream.avail_in);
01108 zstream_append_input(z, src, len);
01109 return Qtrue;
01110 }
01111 zstream_reset_input(z);
01112 if (err != Z_DATA_ERROR) {
01113
01114 raise_zlib_error(err, z->stream.msg);
01115 }
01116 }
01117
01118 if (len <= 0) return Qfalse;
01119
01120 z->stream.next_in = src;
01121 z->stream.avail_in = MAX_UINT(len);
01122 err = inflateSync(&z->stream);
01123 if (err == Z_OK) {
01124 zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
01125 return Qtrue;
01126 }
01127 if (err != Z_DATA_ERROR) {
01128
01129 raise_zlib_error(err, z->stream.msg);
01130 }
01131 return Qfalse;
01132 }
01133
01134 static void
01135 zstream_mark(struct zstream *z)
01136 {
01137 rb_gc_mark(z->buf);
01138 rb_gc_mark(z->input);
01139 }
01140
01141 static void
01142 zstream_finalize(struct zstream *z)
01143 {
01144 int err = z->func->end(&z->stream);
01145 if (err == Z_STREAM_ERROR)
01146 finalizer_warn("the stream state was inconsistent.");
01147 if (err == Z_DATA_ERROR)
01148 finalizer_warn("the stream was freed prematurely.");
01149 }
01150
01151 static void
01152 zstream_free(struct zstream *z)
01153 {
01154 if (ZSTREAM_IS_READY(z)) {
01155 zstream_finalize(z);
01156 }
01157 xfree(z);
01158 }
01159
01160 static VALUE
01161 zstream_new(VALUE klass, const struct zstream_funcs *funcs)
01162 {
01163 VALUE obj;
01164 struct zstream *z;
01165
01166 obj = Data_Make_Struct(klass, struct zstream,
01167 zstream_mark, zstream_free, z);
01168 zstream_init(z, funcs);
01169 z->stream.opaque = (voidpf)obj;
01170 return obj;
01171 }
01172
01173 #define zstream_deflate_new(klass) zstream_new((klass), &deflate_funcs)
01174 #define zstream_inflate_new(klass) zstream_new((klass), &inflate_funcs)
01175
01176 static struct zstream *
01177 get_zstream(VALUE obj)
01178 {
01179 struct zstream *z;
01180
01181 Data_Get_Struct(obj, struct zstream, z);
01182 if (!ZSTREAM_IS_READY(z)) {
01183 rb_raise(cZError, "stream is not ready");
01184 }
01185 return z;
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 static VALUE
01257 rb_zstream_end(VALUE obj)
01258 {
01259 zstream_end(get_zstream(obj));
01260 return Qnil;
01261 }
01262
01263
01264
01265
01266
01267 static VALUE
01268 rb_zstream_reset(VALUE obj)
01269 {
01270 zstream_reset(get_zstream(obj));
01271 return Qnil;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 static VALUE
01284 rb_zstream_finish(VALUE obj)
01285 {
01286 struct zstream *z = get_zstream(obj);
01287
01288 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01289
01290 return zstream_detach_buffer(z);
01291 }
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 static VALUE
01303 rb_zstream_flush_next_in(VALUE obj)
01304 {
01305 struct zstream *z;
01306 VALUE dst;
01307
01308 Data_Get_Struct(obj, struct zstream, z);
01309 dst = zstream_detach_input(z);
01310 OBJ_INFECT(dst, obj);
01311 return dst;
01312 }
01313
01314
01315
01316
01317 static VALUE
01318 rb_zstream_flush_next_out(VALUE obj)
01319 {
01320 struct zstream *z;
01321
01322 Data_Get_Struct(obj, struct zstream, z);
01323
01324 return zstream_detach_buffer(z);
01325 }
01326
01327
01328
01329
01330
01331 static VALUE
01332 rb_zstream_avail_out(VALUE obj)
01333 {
01334 struct zstream *z;
01335 Data_Get_Struct(obj, struct zstream, z);
01336 return rb_uint2inum(z->stream.avail_out);
01337 }
01338
01339
01340
01341
01342
01343
01344
01345 static VALUE
01346 rb_zstream_set_avail_out(VALUE obj, VALUE size)
01347 {
01348 struct zstream *z = get_zstream(obj);
01349
01350 Check_Type(size, T_FIXNUM);
01351 zstream_expand_buffer_into(z, FIX2INT(size));
01352 return size;
01353 }
01354
01355
01356
01357
01358 static VALUE
01359 rb_zstream_avail_in(VALUE obj)
01360 {
01361 struct zstream *z;
01362 Data_Get_Struct(obj, struct zstream, z);
01363 return INT2FIX(NIL_P(z->input) ? 0 : (int)(RSTRING_LEN(z->input)));
01364 }
01365
01366
01367
01368
01369 static VALUE
01370 rb_zstream_total_in(VALUE obj)
01371 {
01372 return rb_uint2inum(get_zstream(obj)->stream.total_in);
01373 }
01374
01375
01376
01377
01378 static VALUE
01379 rb_zstream_total_out(VALUE obj)
01380 {
01381 return rb_uint2inum(get_zstream(obj)->stream.total_out);
01382 }
01383
01384
01385
01386
01387
01388
01389 static VALUE
01390 rb_zstream_data_type(VALUE obj)
01391 {
01392 return INT2FIX(get_zstream(obj)->stream.data_type);
01393 }
01394
01395
01396
01397
01398 static VALUE
01399 rb_zstream_adler(VALUE obj)
01400 {
01401 return rb_uint2inum(get_zstream(obj)->stream.adler);
01402 }
01403
01404
01405
01406
01407 static VALUE
01408 rb_zstream_finished_p(VALUE obj)
01409 {
01410 return ZSTREAM_IS_FINISHED(get_zstream(obj)) ? Qtrue : Qfalse;
01411 }
01412
01413
01414
01415
01416 static VALUE
01417 rb_zstream_closed_p(VALUE obj)
01418 {
01419 struct zstream *z;
01420 Data_Get_Struct(obj, struct zstream, z);
01421 return ZSTREAM_IS_READY(z) ? Qfalse : Qtrue;
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 #define FIXNUMARG(val, ifnil) \
01435 (NIL_P((val)) ? (ifnil) \
01436 : ((void)Check_Type((val), T_FIXNUM), FIX2INT((val))))
01437
01438 #define ARG_LEVEL(val) FIXNUMARG((val), Z_DEFAULT_COMPRESSION)
01439 #define ARG_WBITS(val) FIXNUMARG((val), MAX_WBITS)
01440 #define ARG_MEMLEVEL(val) FIXNUMARG((val), DEF_MEM_LEVEL)
01441 #define ARG_STRATEGY(val) FIXNUMARG((val), Z_DEFAULT_STRATEGY)
01442 #define ARG_FLUSH(val) FIXNUMARG((val), Z_NO_FLUSH)
01443
01444
01445 static VALUE
01446 rb_deflate_s_allocate(VALUE klass)
01447 {
01448 return zstream_deflate_new(klass);
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522 static VALUE
01523 rb_deflate_initialize(int argc, VALUE *argv, VALUE obj)
01524 {
01525 struct zstream *z;
01526 VALUE level, wbits, memlevel, strategy;
01527 int err;
01528
01529 rb_scan_args(argc, argv, "04", &level, &wbits, &memlevel, &strategy);
01530 Data_Get_Struct(obj, struct zstream, z);
01531
01532 err = deflateInit2(&z->stream, ARG_LEVEL(level), Z_DEFLATED,
01533 ARG_WBITS(wbits), ARG_MEMLEVEL(memlevel),
01534 ARG_STRATEGY(strategy));
01535 if (err != Z_OK) {
01536 raise_zlib_error(err, z->stream.msg);
01537 }
01538 ZSTREAM_READY(z);
01539
01540 return obj;
01541 }
01542
01543
01544
01545
01546
01547
01548 static VALUE
01549 rb_deflate_init_copy(VALUE self, VALUE orig)
01550 {
01551 struct zstream *z1, *z2;
01552 int err;
01553
01554 Data_Get_Struct(self, struct zstream, z1);
01555 z2 = get_zstream(orig);
01556
01557 if (z1 == z2) return self;
01558 err = deflateCopy(&z1->stream, &z2->stream);
01559 if (err != Z_OK) {
01560 raise_zlib_error(err, 0);
01561 }
01562 z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input);
01563 z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf);
01564 z1->buf_filled = z2->buf_filled;
01565 z1->flags = z2->flags;
01566
01567 return self;
01568 }
01569
01570 static VALUE
01571 deflate_run(VALUE args)
01572 {
01573 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
01574 VALUE src = ((VALUE*)args)[1];
01575
01576 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_FINISH);
01577 return zstream_detach_buffer(z);
01578 }
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 static VALUE
01604 rb_deflate_s_deflate(int argc, VALUE *argv, VALUE klass)
01605 {
01606 struct zstream z;
01607 VALUE src, level, dst, args[2];
01608 int err, lev;
01609
01610 rb_scan_args(argc, argv, "11", &src, &level);
01611
01612 lev = ARG_LEVEL(level);
01613 StringValue(src);
01614 zstream_init_deflate(&z);
01615 err = deflateInit(&z.stream, lev);
01616 if (err != Z_OK) {
01617 raise_zlib_error(err, z.stream.msg);
01618 }
01619 ZSTREAM_READY(&z);
01620
01621 args[0] = (VALUE)&z;
01622 args[1] = src;
01623 dst = rb_ensure(deflate_run, (VALUE)args, zstream_end, (VALUE)&z);
01624
01625 OBJ_INFECT(dst, src);
01626 return dst;
01627 }
01628
01629 static void
01630 do_deflate(struct zstream *z, VALUE src, int flush)
01631 {
01632 if (NIL_P(src)) {
01633 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01634 return;
01635 }
01636 StringValue(src);
01637 if (flush != Z_NO_FLUSH || RSTRING_LEN(src) > 0) {
01638 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), flush);
01639 }
01640 }
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 static VALUE
01669 rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
01670 {
01671 struct zstream *z = get_zstream(obj);
01672 VALUE src, flush;
01673
01674 rb_scan_args(argc, argv, "11", &src, &flush);
01675 OBJ_INFECT(obj, src);
01676 do_deflate(z, src, ARG_FLUSH(flush));
01677
01678 return zstream_detach_buffer(z);
01679 }
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 static VALUE
01691 rb_deflate_addstr(VALUE obj, VALUE src)
01692 {
01693 OBJ_INFECT(obj, src);
01694 do_deflate(get_zstream(obj), src, Z_NO_FLUSH);
01695 return obj;
01696 }
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713 static VALUE
01714 rb_deflate_flush(int argc, VALUE *argv, VALUE obj)
01715 {
01716 struct zstream *z = get_zstream(obj);
01717 VALUE v_flush;
01718 int flush;
01719
01720 rb_scan_args(argc, argv, "01", &v_flush);
01721 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
01722 if (flush != Z_NO_FLUSH) {
01723 zstream_run(z, (Bytef*)"", 0, flush);
01724 }
01725
01726 return zstream_detach_buffer(z);
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 static VALUE
01742 rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
01743 {
01744 struct zstream *z = get_zstream(obj);
01745 int level, strategy;
01746 int err;
01747 uInt n;
01748
01749 level = ARG_LEVEL(v_level);
01750 strategy = ARG_STRATEGY(v_strategy);
01751
01752 n = z->stream.avail_out;
01753 err = deflateParams(&z->stream, level, strategy);
01754 z->buf_filled += n - z->stream.avail_out;
01755 while (err == Z_BUF_ERROR) {
01756 rb_warning("deflateParams() returned Z_BUF_ERROR");
01757 zstream_expand_buffer(z);
01758 n = z->stream.avail_out;
01759 err = deflateParams(&z->stream, level, strategy);
01760 z->buf_filled += n - z->stream.avail_out;
01761 }
01762 if (err != Z_OK) {
01763 raise_zlib_error(err, z->stream.msg);
01764 }
01765
01766 return Qnil;
01767 }
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783 static VALUE
01784 rb_deflate_set_dictionary(VALUE obj, VALUE dic)
01785 {
01786 struct zstream *z = get_zstream(obj);
01787 VALUE src = dic;
01788 int err;
01789
01790 OBJ_INFECT(obj, dic);
01791 StringValue(src);
01792 err = deflateSetDictionary(&z->stream,
01793 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
01794 if (err != Z_OK) {
01795 raise_zlib_error(err, z->stream.msg);
01796 }
01797
01798 return dic;
01799 }
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812 static VALUE
01813 rb_inflate_s_allocate(VALUE klass)
01814 {
01815 VALUE inflate = zstream_inflate_new(klass);
01816 rb_ivar_set(inflate, id_dictionaries, rb_hash_new());
01817 return inflate;
01818 }
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 static VALUE
01866 rb_inflate_initialize(int argc, VALUE *argv, VALUE obj)
01867 {
01868 struct zstream *z;
01869 VALUE wbits;
01870 int err;
01871
01872 rb_scan_args(argc, argv, "01", &wbits);
01873 Data_Get_Struct(obj, struct zstream, z);
01874
01875 err = inflateInit2(&z->stream, ARG_WBITS(wbits));
01876 if (err != Z_OK) {
01877 raise_zlib_error(err, z->stream.msg);
01878 }
01879 ZSTREAM_READY(z);
01880
01881 return obj;
01882 }
01883
01884 static VALUE
01885 inflate_run(VALUE args)
01886 {
01887 struct zstream *z = (struct zstream*)((VALUE*)args)[0];
01888 VALUE src = ((VALUE*)args)[1];
01889
01890 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
01891 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01892 return zstream_detach_buffer(z);
01893 }
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 static VALUE
01919 rb_inflate_s_inflate(VALUE obj, VALUE src)
01920 {
01921 struct zstream z;
01922 VALUE dst, args[2];
01923 int err;
01924
01925 StringValue(src);
01926 zstream_init_inflate(&z);
01927 err = inflateInit(&z.stream);
01928 if (err != Z_OK) {
01929 raise_zlib_error(err, z.stream.msg);
01930 }
01931 ZSTREAM_READY(&z);
01932
01933 args[0] = (VALUE)&z;
01934 args[1] = src;
01935 dst = rb_ensure(inflate_run, (VALUE)args, zstream_end, (VALUE)&z);
01936
01937 OBJ_INFECT(dst, src);
01938 return dst;
01939 }
01940
01941 static void
01942 do_inflate(struct zstream *z, VALUE src)
01943 {
01944 if (NIL_P(src)) {
01945 zstream_run(z, (Bytef*)"", 0, Z_FINISH);
01946 return;
01947 }
01948 StringValue(src);
01949 if (RSTRING_LEN(src) > 0 || z->stream.avail_in > 0) {
01950 zstream_run(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src), Z_SYNC_FLUSH);
01951 }
01952 }
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963 static VALUE
01964 rb_inflate_add_dictionary(VALUE obj, VALUE dictionary) {
01965 VALUE dictionaries = rb_ivar_get(obj, id_dictionaries);
01966 VALUE checksum = do_checksum(1, &dictionary, adler32);
01967
01968 rb_hash_aset(dictionaries, checksum, dictionary);
01969
01970 return obj;
01971 }
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010 static VALUE
02011 rb_inflate_inflate(VALUE obj, VALUE src)
02012 {
02013 struct zstream *z = get_zstream(obj);
02014 VALUE dst;
02015
02016 OBJ_INFECT(obj, src);
02017
02018 if (ZSTREAM_IS_FINISHED(z)) {
02019 if (NIL_P(src)) {
02020 dst = zstream_detach_buffer(z);
02021 }
02022 else {
02023 StringValue(src);
02024 zstream_append_buffer2(z, src);
02025 dst = rb_str_new(0, 0);
02026 OBJ_INFECT(dst, obj);
02027 }
02028 }
02029 else {
02030 do_inflate(z, src);
02031 dst = zstream_detach_buffer(z);
02032 if (ZSTREAM_IS_FINISHED(z)) {
02033 zstream_passthrough_input(z);
02034 }
02035 }
02036
02037 return dst;
02038 }
02039
02040
02041
02042
02043
02044
02045
02046
02047 static VALUE
02048 rb_inflate_addstr(VALUE obj, VALUE src)
02049 {
02050 struct zstream *z = get_zstream(obj);
02051
02052 OBJ_INFECT(obj, src);
02053
02054 if (ZSTREAM_IS_FINISHED(z)) {
02055 if (!NIL_P(src)) {
02056 StringValue(src);
02057 zstream_append_buffer2(z, src);
02058 }
02059 }
02060 else {
02061 do_inflate(z, src);
02062 if (ZSTREAM_IS_FINISHED(z)) {
02063 zstream_passthrough_input(z);
02064 }
02065 }
02066
02067 return obj;
02068 }
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 static VALUE
02079 rb_inflate_sync(VALUE obj, VALUE src)
02080 {
02081 struct zstream *z = get_zstream(obj);
02082
02083 OBJ_INFECT(obj, src);
02084 StringValue(src);
02085 return zstream_sync(z, (Bytef*)RSTRING_PTR(src), RSTRING_LEN(src));
02086 }
02087
02088
02089
02090
02091
02092
02093
02094
02095 static VALUE
02096 rb_inflate_sync_point_p(VALUE obj)
02097 {
02098 struct zstream *z = get_zstream(obj);
02099 int err;
02100
02101 err = inflateSyncPoint(&z->stream);
02102 if (err == 1) {
02103 return Qtrue;
02104 }
02105 if (err != Z_OK) {
02106 raise_zlib_error(err, z->stream.msg);
02107 }
02108 return Qfalse;
02109 }
02110
02111
02112
02113
02114
02115
02116
02117
02118 static VALUE
02119 rb_inflate_set_dictionary(VALUE obj, VALUE dic)
02120 {
02121 struct zstream *z = get_zstream(obj);
02122 VALUE src = dic;
02123 int err;
02124
02125 OBJ_INFECT(obj, dic);
02126 StringValue(src);
02127 err = inflateSetDictionary(&z->stream,
02128 (Bytef*)RSTRING_PTR(src), RSTRING_LENINT(src));
02129 if (err != Z_OK) {
02130 raise_zlib_error(err, z->stream.msg);
02131 }
02132
02133 return dic;
02134 }
02135
02136
02137
02138 #if GZIP_SUPPORT
02139
02140
02141
02142
02143
02144
02145
02146
02147 #define GZ_MAGIC1 0x1f
02148 #define GZ_MAGIC2 0x8b
02149 #define GZ_METHOD_DEFLATE 8
02150 #define GZ_FLAG_MULTIPART 0x2
02151 #define GZ_FLAG_EXTRA 0x4
02152 #define GZ_FLAG_ORIG_NAME 0x8
02153 #define GZ_FLAG_COMMENT 0x10
02154 #define GZ_FLAG_ENCRYPT 0x20
02155 #define GZ_FLAG_UNKNOWN_MASK 0xc0
02156
02157 #define GZ_EXTRAFLAG_FAST 0x4
02158 #define GZ_EXTRAFLAG_SLOW 0x2
02159
02160
02161 #define OS_MSDOS 0x00
02162 #define OS_AMIGA 0x01
02163 #define OS_VMS 0x02
02164 #define OS_UNIX 0x03
02165 #define OS_ATARI 0x05
02166 #define OS_OS2 0x06
02167 #define OS_MACOS 0x07
02168 #define OS_TOPS20 0x0a
02169 #define OS_WIN32 0x0b
02170
02171 #define OS_VMCMS 0x04
02172 #define OS_ZSYSTEM 0x08
02173 #define OS_CPM 0x09
02174 #define OS_QDOS 0x0c
02175 #define OS_RISCOS 0x0d
02176 #define OS_UNKNOWN 0xff
02177
02178 #ifndef OS_CODE
02179 #define OS_CODE OS_UNIX
02180 #endif
02181
02182 static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
02183 static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
02184
02185
02186
02187
02188
02189 struct gzfile {
02190 struct zstream z;
02191 VALUE io;
02192 int level;
02193 time_t mtime;
02194 int os_code;
02195 VALUE orig_name;
02196 VALUE comment;
02197 unsigned long crc;
02198 int lineno;
02199 long ungetc;
02200 void (*end)(struct gzfile *);
02201 rb_encoding *enc;
02202 rb_encoding *enc2;
02203 rb_econv_t *ec;
02204 int ecflags;
02205 VALUE ecopts;
02206 char *cbuf;
02207 VALUE path;
02208 };
02209 #define GZFILE_CBUF_CAPA 10
02210
02211 #define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
02212 #define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
02213 #define GZFILE_FLAG_FOOTER_FINISHED (ZSTREAM_FLAG_UNUSED << 2)
02214
02215 #define GZFILE_IS_FINISHED(gz) \
02216 (ZSTREAM_IS_FINISHED(&(gz)->z) && (gz)->z.buf_filled == 0)
02217
02218 #define GZFILE_READ_SIZE 2048
02219
02220
02221 static void
02222 gzfile_mark(struct gzfile *gz)
02223 {
02224 rb_gc_mark(gz->io);
02225 rb_gc_mark(gz->orig_name);
02226 rb_gc_mark(gz->comment);
02227 zstream_mark(&gz->z);
02228 rb_gc_mark(gz->ecopts);
02229 rb_gc_mark(gz->path);
02230 }
02231
02232 static void
02233 gzfile_free(struct gzfile *gz)
02234 {
02235 struct zstream *z = &gz->z;
02236
02237 if (ZSTREAM_IS_READY(z)) {
02238 if (z->func == &deflate_funcs) {
02239 finalizer_warn("Zlib::GzipWriter object must be closed explicitly.");
02240 }
02241 zstream_finalize(z);
02242 }
02243 if (gz->cbuf) {
02244 xfree(gz->cbuf);
02245 }
02246 xfree(gz);
02247 }
02248
02249 static VALUE
02250 gzfile_new(klass, funcs, endfunc)
02251 VALUE klass;
02252 const struct zstream_funcs *funcs;
02253 void (*endfunc)(struct gzfile *);
02254 {
02255 VALUE obj;
02256 struct gzfile *gz;
02257
02258 obj = Data_Make_Struct(klass, struct gzfile, gzfile_mark, gzfile_free, gz);
02259 zstream_init(&gz->z, funcs);
02260 gz->z.flags |= ZSTREAM_FLAG_GZFILE;
02261 gz->io = Qnil;
02262 gz->level = 0;
02263 gz->mtime = 0;
02264 gz->os_code = OS_CODE;
02265 gz->orig_name = Qnil;
02266 gz->comment = Qnil;
02267 gz->crc = crc32(0, Z_NULL, 0);
02268 gz->lineno = 0;
02269 gz->ungetc = 0;
02270 gz->end = endfunc;
02271 gz->enc = rb_default_external_encoding();
02272 gz->enc2 = 0;
02273 gz->ec = NULL;
02274 gz->ecflags = 0;
02275 gz->ecopts = Qnil;
02276 gz->cbuf = 0;
02277 gz->path = Qnil;
02278
02279 return obj;
02280 }
02281
02282 #define gzfile_writer_new(gz) gzfile_new((gz),&deflate_funcs,gzfile_writer_end)
02283 #define gzfile_reader_new(gz) gzfile_new((gz),&inflate_funcs,gzfile_reader_end)
02284
02285 static void
02286 gzfile_reset(struct gzfile *gz)
02287 {
02288 zstream_reset(&gz->z);
02289 gz->z.flags |= ZSTREAM_FLAG_GZFILE;
02290 gz->crc = crc32(0, Z_NULL, 0);
02291 gz->lineno = 0;
02292 gz->ungetc = 0;
02293 if (gz->ec) {
02294 rb_econv_close(gz->ec);
02295 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
02296 gz->ecflags, gz->ecopts);
02297 }
02298 }
02299
02300 static void
02301 gzfile_close(struct gzfile *gz, int closeflag)
02302 {
02303 VALUE io = gz->io;
02304
02305 gz->end(gz);
02306 gz->io = Qnil;
02307 gz->orig_name = Qnil;
02308 gz->comment = Qnil;
02309 if (closeflag && rb_respond_to(io, id_close)) {
02310 rb_funcall(io, id_close, 0);
02311 }
02312 }
02313
02314 static void
02315 gzfile_write_raw(struct gzfile *gz)
02316 {
02317 VALUE str;
02318
02319 if (gz->z.buf_filled > 0) {
02320 str = zstream_detach_buffer(&gz->z);
02321 OBJ_TAINT(str);
02322 rb_funcall(gz->io, id_write, 1, str);
02323 if ((gz->z.flags & GZFILE_FLAG_SYNC)
02324 && rb_respond_to(gz->io, id_flush))
02325 rb_funcall(gz->io, id_flush, 0);
02326 }
02327 }
02328
02329 static VALUE
02330 gzfile_read_raw_partial(VALUE arg)
02331 {
02332 struct gzfile *gz = (struct gzfile*)arg;
02333 VALUE str;
02334
02335 str = rb_funcall(gz->io, id_readpartial, 1, INT2FIX(GZFILE_READ_SIZE));
02336 Check_Type(str, T_STRING);
02337 return str;
02338 }
02339
02340 static VALUE
02341 gzfile_read_raw_rescue(VALUE arg)
02342 {
02343 struct gzfile *gz = (struct gzfile*)arg;
02344 VALUE str = Qnil;
02345 if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
02346 str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
02347 if (!NIL_P(str)) {
02348 Check_Type(str, T_STRING);
02349 }
02350 }
02351 return str;
02352 }
02353
02354 static VALUE
02355 gzfile_read_raw(struct gzfile *gz)
02356 {
02357 return rb_rescue2(gzfile_read_raw_partial, (VALUE)gz,
02358 gzfile_read_raw_rescue, (VALUE)gz,
02359 rb_eEOFError, rb_eNoMethodError, (VALUE)0);
02360 }
02361
02362 static int
02363 gzfile_read_raw_ensure(struct gzfile *gz, long size)
02364 {
02365 VALUE str;
02366
02367 while (NIL_P(gz->z.input) || RSTRING_LEN(gz->z.input) < size) {
02368 str = gzfile_read_raw(gz);
02369 if (NIL_P(str)) return 0;
02370 zstream_append_input2(&gz->z, str);
02371 }
02372 return 1;
02373 }
02374
02375 static char *
02376 gzfile_read_raw_until_zero(struct gzfile *gz, long offset)
02377 {
02378 VALUE str;
02379 char *p;
02380
02381 for (;;) {
02382 p = memchr(RSTRING_PTR(gz->z.input) + offset, '\0',
02383 RSTRING_LEN(gz->z.input) - offset);
02384 if (p) break;
02385 str = gzfile_read_raw(gz);
02386 if (NIL_P(str)) {
02387 rb_raise(cGzError, "unexpected end of file");
02388 }
02389 offset = RSTRING_LEN(gz->z.input);
02390 zstream_append_input2(&gz->z, str);
02391 }
02392 return p;
02393 }
02394
02395 static unsigned int
02396 gzfile_get16(const unsigned char *src)
02397 {
02398 unsigned int n;
02399 n = *(src++) & 0xff;
02400 n |= (*(src++) & 0xff) << 8;
02401 return n;
02402 }
02403
02404 static unsigned long
02405 gzfile_get32(const unsigned char *src)
02406 {
02407 unsigned long n;
02408 n = *(src++) & 0xff;
02409 n |= (*(src++) & 0xff) << 8;
02410 n |= (*(src++) & 0xff) << 16;
02411 n |= (*(src++) & 0xffU) << 24;
02412 return n;
02413 }
02414
02415 static void
02416 gzfile_set32(unsigned long n, unsigned char *dst)
02417 {
02418 *(dst++) = n & 0xff;
02419 *(dst++) = (n >> 8) & 0xff;
02420 *(dst++) = (n >> 16) & 0xff;
02421 *dst = (n >> 24) & 0xff;
02422 }
02423
02424 static void
02425 gzfile_raise(struct gzfile *gz, VALUE klass, const char *message)
02426 {
02427 VALUE exc = rb_exc_new2(klass, message);
02428 if (!NIL_P(gz->z.input)) {
02429 rb_ivar_set(exc, id_input, rb_str_resurrect(gz->z.input));
02430 }
02431 rb_exc_raise(exc);
02432 }
02433
02434
02435
02436
02437
02438
02439 static VALUE
02440 gzfile_error_inspect(VALUE error)
02441 {
02442 VALUE str = rb_call_super(0, 0);
02443 VALUE input = rb_attr_get(error, id_input);
02444
02445 if (!NIL_P(input)) {
02446 rb_str_resize(str, RSTRING_LEN(str)-1);
02447 rb_str_cat2(str, ", input=");
02448 rb_str_append(str, rb_str_inspect(input));
02449 rb_str_cat2(str, ">");
02450 }
02451 return str;
02452 }
02453
02454 static void
02455 gzfile_make_header(struct gzfile *gz)
02456 {
02457 Bytef buf[10];
02458 unsigned char flags = 0, extraflags = 0;
02459
02460 if (!NIL_P(gz->orig_name)) {
02461 flags |= GZ_FLAG_ORIG_NAME;
02462 }
02463 if (!NIL_P(gz->comment)) {
02464 flags |= GZ_FLAG_COMMENT;
02465 }
02466 if (gz->mtime == 0) {
02467 gz->mtime = time(0);
02468 }
02469
02470 if (gz->level == Z_BEST_SPEED) {
02471 extraflags |= GZ_EXTRAFLAG_FAST;
02472 }
02473 else if (gz->level == Z_BEST_COMPRESSION) {
02474 extraflags |= GZ_EXTRAFLAG_SLOW;
02475 }
02476
02477 buf[0] = GZ_MAGIC1;
02478 buf[1] = GZ_MAGIC2;
02479 buf[2] = GZ_METHOD_DEFLATE;
02480 buf[3] = flags;
02481 gzfile_set32((unsigned long)gz->mtime, &buf[4]);
02482 buf[8] = extraflags;
02483 buf[9] = gz->os_code;
02484 zstream_append_buffer(&gz->z, buf, sizeof(buf));
02485
02486 if (!NIL_P(gz->orig_name)) {
02487 zstream_append_buffer2(&gz->z, gz->orig_name);
02488 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
02489 }
02490 if (!NIL_P(gz->comment)) {
02491 zstream_append_buffer2(&gz->z, gz->comment);
02492 zstream_append_buffer(&gz->z, (Bytef*)"\0", 1);
02493 }
02494
02495 gz->z.flags |= GZFILE_FLAG_HEADER_FINISHED;
02496 }
02497
02498 static void
02499 gzfile_make_footer(struct gzfile *gz)
02500 {
02501 Bytef buf[8];
02502
02503 gzfile_set32(gz->crc, buf);
02504 gzfile_set32(gz->z.stream.total_in, &buf[4]);
02505 zstream_append_buffer(&gz->z, buf, sizeof(buf));
02506 gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
02507 }
02508
02509 static void
02510 gzfile_read_header(struct gzfile *gz)
02511 {
02512 const unsigned char *head;
02513 long len;
02514 char flags, *p;
02515
02516 if (!gzfile_read_raw_ensure(gz, 10)) {
02517 gzfile_raise(gz, cGzError, "not in gzip format");
02518 }
02519
02520 head = (unsigned char*)RSTRING_PTR(gz->z.input);
02521
02522 if (head[0] != GZ_MAGIC1 || head[1] != GZ_MAGIC2) {
02523 gzfile_raise(gz, cGzError, "not in gzip format");
02524 }
02525 if (head[2] != GZ_METHOD_DEFLATE) {
02526 rb_raise(cGzError, "unsupported compression method %d", head[2]);
02527 }
02528
02529 flags = head[3];
02530 if (flags & GZ_FLAG_MULTIPART) {
02531 rb_raise(cGzError, "multi-part gzip file is not supported");
02532 }
02533 else if (flags & GZ_FLAG_ENCRYPT) {
02534 rb_raise(cGzError, "encrypted gzip file is not supported");
02535 }
02536 else if (flags & GZ_FLAG_UNKNOWN_MASK) {
02537 rb_raise(cGzError, "unknown flags 0x%02x", flags);
02538 }
02539
02540 if (head[8] & GZ_EXTRAFLAG_FAST) {
02541 gz->level = Z_BEST_SPEED;
02542 }
02543 else if (head[8] & GZ_EXTRAFLAG_SLOW) {
02544 gz->level = Z_BEST_COMPRESSION;
02545 }
02546 else {
02547 gz->level = Z_DEFAULT_COMPRESSION;
02548 }
02549
02550 gz->mtime = gzfile_get32(&head[4]);
02551 gz->os_code = head[9];
02552 zstream_discard_input(&gz->z, 10);
02553
02554 if (flags & GZ_FLAG_EXTRA) {
02555 if (!gzfile_read_raw_ensure(gz, 2)) {
02556 rb_raise(cGzError, "unexpected end of file");
02557 }
02558 len = gzfile_get16((Bytef*)RSTRING_PTR(gz->z.input));
02559 if (!gzfile_read_raw_ensure(gz, 2 + len)) {
02560 rb_raise(cGzError, "unexpected end of file");
02561 }
02562 zstream_discard_input(&gz->z, 2 + len);
02563 }
02564 if (flags & GZ_FLAG_ORIG_NAME) {
02565 if (!gzfile_read_raw_ensure(gz, 1)) {
02566 rb_raise(cGzError, "unexpected end of file");
02567 }
02568 p = gzfile_read_raw_until_zero(gz, 0);
02569 len = p - RSTRING_PTR(gz->z.input);
02570 gz->orig_name = rb_str_new(RSTRING_PTR(gz->z.input), len);
02571 OBJ_TAINT(gz->orig_name);
02572 zstream_discard_input(&gz->z, len + 1);
02573 }
02574 if (flags & GZ_FLAG_COMMENT) {
02575 if (!gzfile_read_raw_ensure(gz, 1)) {
02576 rb_raise(cGzError, "unexpected end of file");
02577 }
02578 p = gzfile_read_raw_until_zero(gz, 0);
02579 len = p - RSTRING_PTR(gz->z.input);
02580 gz->comment = rb_str_new(RSTRING_PTR(gz->z.input), len);
02581 OBJ_TAINT(gz->comment);
02582 zstream_discard_input(&gz->z, len + 1);
02583 }
02584
02585 if (gz->z.input != Qnil && RSTRING_LEN(gz->z.input) > 0) {
02586 zstream_run(&gz->z, 0, 0, Z_SYNC_FLUSH);
02587 }
02588 }
02589
02590 static void
02591 gzfile_check_footer(struct gzfile *gz)
02592 {
02593 unsigned long crc, length;
02594
02595 gz->z.flags |= GZFILE_FLAG_FOOTER_FINISHED;
02596
02597 if (!gzfile_read_raw_ensure(gz, 8)) {
02598 gzfile_raise(gz, cNoFooter, "footer is not found");
02599 }
02600
02601 crc = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input));
02602 length = gzfile_get32((Bytef*)RSTRING_PTR(gz->z.input) + 4);
02603
02604 gz->z.stream.total_in += 8;
02605 zstream_discard_input(&gz->z, 8);
02606
02607 if (gz->crc != crc) {
02608 rb_raise(cCRCError, "invalid compressed data -- crc error");
02609 }
02610 if ((uint32_t)gz->z.stream.total_out != length) {
02611 rb_raise(cLengthError, "invalid compressed data -- length error");
02612 }
02613 }
02614
02615 static void
02616 gzfile_write(struct gzfile *gz, Bytef *str, long len)
02617 {
02618 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
02619 gzfile_make_header(gz);
02620 }
02621
02622 if (len > 0 || (gz->z.flags & GZFILE_FLAG_SYNC)) {
02623 gz->crc = checksum_long(crc32, gz->crc, str, len);
02624 zstream_run(&gz->z, str, len, (gz->z.flags & GZFILE_FLAG_SYNC)
02625 ? Z_SYNC_FLUSH : Z_NO_FLUSH);
02626 }
02627 gzfile_write_raw(gz);
02628 }
02629
02630 static long
02631 gzfile_read_more(struct gzfile *gz)
02632 {
02633 volatile VALUE str;
02634
02635 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
02636 str = gzfile_read_raw(gz);
02637 if (NIL_P(str)) {
02638 if (!ZSTREAM_IS_FINISHED(&gz->z)) {
02639 rb_raise(cGzError, "unexpected end of file");
02640 }
02641 break;
02642 }
02643 if (RSTRING_LEN(str) > 0) {
02644 zstream_run(&gz->z, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str),
02645 Z_SYNC_FLUSH);
02646 }
02647 if (gz->z.buf_filled > 0) break;
02648 }
02649 return gz->z.buf_filled;
02650 }
02651
02652 static void
02653 gzfile_calc_crc(struct gzfile *gz, VALUE str)
02654 {
02655 if (RSTRING_LEN(str) <= gz->ungetc) {
02656 gz->ungetc -= RSTRING_LEN(str);
02657 }
02658 else {
02659 gz->crc = checksum_long(crc32, gz->crc, (Bytef*)RSTRING_PTR(str) + gz->ungetc,
02660 RSTRING_LEN(str) - gz->ungetc);
02661 gz->ungetc = 0;
02662 }
02663 }
02664
02665 static VALUE
02666 gzfile_newstr(struct gzfile *gz, VALUE str)
02667 {
02668 if (!gz->enc2) {
02669 rb_enc_associate(str, gz->enc);
02670 OBJ_TAINT(str);
02671 return str;
02672 }
02673 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
02674 str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
02675 rb_enc_associate(str, gz->enc);
02676 OBJ_TAINT(str);
02677 return str;
02678 }
02679 return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
02680 gz->ecflags, gz->ecopts);
02681 }
02682
02683 static long
02684 gzfile_fill(struct gzfile *gz, long len)
02685 {
02686 if (len < 0)
02687 rb_raise(rb_eArgError, "negative length %ld given", len);
02688 if (len == 0)
02689 return 0;
02690 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
02691 gzfile_read_more(gz);
02692 }
02693 if (GZFILE_IS_FINISHED(gz)) {
02694 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02695 gzfile_check_footer(gz);
02696 }
02697 return -1;
02698 }
02699 return len < gz->z.buf_filled ? len : gz->z.buf_filled;
02700 }
02701
02702 static VALUE
02703 gzfile_read(struct gzfile *gz, long len)
02704 {
02705 VALUE dst;
02706
02707 len = gzfile_fill(gz, len);
02708 if (len == 0) return rb_str_new(0, 0);
02709 if (len < 0) return Qnil;
02710 dst = zstream_shift_buffer(&gz->z, len);
02711 if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
02712 return dst;
02713 }
02714
02715 static VALUE
02716 gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
02717 {
02718 VALUE dst;
02719
02720 if (len < 0)
02721 rb_raise(rb_eArgError, "negative length %ld given", len);
02722
02723 if (!NIL_P(outbuf))
02724 OBJ_TAINT(outbuf);
02725
02726 if (len == 0) {
02727 if (NIL_P(outbuf))
02728 return rb_str_new(0, 0);
02729 else {
02730 rb_str_resize(outbuf, 0);
02731 return outbuf;
02732 }
02733 }
02734 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled == 0) {
02735 gzfile_read_more(gz);
02736 }
02737 if (GZFILE_IS_FINISHED(gz)) {
02738 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02739 gzfile_check_footer(gz);
02740 }
02741 if (!NIL_P(outbuf))
02742 rb_str_resize(outbuf, 0);
02743 rb_raise(rb_eEOFError, "end of file reached");
02744 }
02745
02746 dst = zstream_shift_buffer(&gz->z, len);
02747 gzfile_calc_crc(gz, dst);
02748
02749 if (!NIL_P(outbuf)) {
02750 rb_str_resize(outbuf, RSTRING_LEN(dst));
02751 memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
02752 dst = outbuf;
02753 }
02754 OBJ_TAINT(dst);
02755 return dst;
02756 }
02757
02758 static VALUE
02759 gzfile_read_all(struct gzfile *gz)
02760 {
02761 VALUE dst;
02762
02763 while (!ZSTREAM_IS_FINISHED(&gz->z)) {
02764 gzfile_read_more(gz);
02765 }
02766 if (GZFILE_IS_FINISHED(gz)) {
02767 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02768 gzfile_check_footer(gz);
02769 }
02770 return rb_str_new(0, 0);
02771 }
02772
02773 dst = zstream_detach_buffer(&gz->z);
02774 if (NIL_P(dst)) return dst;
02775 gzfile_calc_crc(gz, dst);
02776 OBJ_TAINT(dst);
02777 return gzfile_newstr(gz, dst);
02778 }
02779
02780 static VALUE
02781 gzfile_getc(struct gzfile *gz)
02782 {
02783 VALUE buf, dst = 0;
02784 int len;
02785
02786 len = rb_enc_mbmaxlen(gz->enc);
02787 while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
02788 gzfile_read_more(gz);
02789 }
02790 if (GZFILE_IS_FINISHED(gz)) {
02791 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02792 gzfile_check_footer(gz);
02793 }
02794 return Qnil;
02795 }
02796
02797 if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
02798 const unsigned char *ss, *sp, *se;
02799 unsigned char *ds, *dp, *de;
02800
02801 if (!gz->cbuf) {
02802 gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
02803 }
02804 ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
02805 se = sp + gz->z.buf_filled;
02806 ds = dp = (unsigned char *)gz->cbuf;
02807 de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
02808 (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
02809 rb_econv_check_error(gz->ec);
02810 dst = zstream_shift_buffer(&gz->z, sp - ss);
02811 gzfile_calc_crc(gz, dst);
02812 dst = rb_str_new(gz->cbuf, dp - ds);
02813 rb_enc_associate(dst, gz->enc);
02814 OBJ_TAINT(dst);
02815 return dst;
02816 }
02817 else {
02818 buf = gz->z.buf;
02819 len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
02820 dst = gzfile_read(gz, len);
02821 if (NIL_P(dst)) return dst;
02822 return gzfile_newstr(gz, dst);
02823 }
02824 }
02825
02826 static void
02827 gzfile_ungets(struct gzfile *gz, const Bytef *b, long len)
02828 {
02829 zstream_buffer_ungets(&gz->z, b, len);
02830 gz->ungetc+=len;
02831 }
02832
02833 static void
02834 gzfile_ungetbyte(struct gzfile *gz, int c)
02835 {
02836 zstream_buffer_ungetbyte(&gz->z, c);
02837 gz->ungetc++;
02838 }
02839
02840 static VALUE
02841 gzfile_writer_end_run(VALUE arg)
02842 {
02843 struct gzfile *gz = (struct gzfile *)arg;
02844
02845 if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
02846 gzfile_make_header(gz);
02847 }
02848
02849 zstream_run(&gz->z, (Bytef*)"", 0, Z_FINISH);
02850 gzfile_make_footer(gz);
02851 gzfile_write_raw(gz);
02852
02853 return Qnil;
02854 }
02855
02856 static void
02857 gzfile_writer_end(struct gzfile *gz)
02858 {
02859 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
02860 gz->z.flags |= ZSTREAM_FLAG_CLOSING;
02861
02862 rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
02863 }
02864
02865 static VALUE
02866 gzfile_reader_end_run(VALUE arg)
02867 {
02868 struct gzfile *gz = (struct gzfile *)arg;
02869
02870 if (GZFILE_IS_FINISHED(gz)
02871 && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02872 gzfile_check_footer(gz);
02873 }
02874
02875 return Qnil;
02876 }
02877
02878 static void
02879 gzfile_reader_end(struct gzfile *gz)
02880 {
02881 if (ZSTREAM_IS_CLOSING(&gz->z)) return;
02882 gz->z.flags |= ZSTREAM_FLAG_CLOSING;
02883
02884 rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
02885 }
02886
02887 static void
02888 gzfile_reader_rewind(struct gzfile *gz)
02889 {
02890 long n;
02891
02892 n = gz->z.stream.total_in;
02893 if (!NIL_P(gz->z.input)) {
02894 n += RSTRING_LEN(gz->z.input);
02895 }
02896
02897 rb_funcall(gz->io, id_seek, 2, rb_int2inum(-n), INT2FIX(1));
02898 gzfile_reset(gz);
02899 }
02900
02901 static VALUE
02902 gzfile_reader_get_unused(struct gzfile *gz)
02903 {
02904 VALUE str;
02905
02906 if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
02907 if (!GZFILE_IS_FINISHED(gz)) return Qnil;
02908 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02909 gzfile_check_footer(gz);
02910 }
02911 if (NIL_P(gz->z.input)) return Qnil;
02912
02913 str = rb_str_resurrect(gz->z.input);
02914 OBJ_TAINT(str);
02915 return str;
02916 }
02917
02918 static struct gzfile *
02919 get_gzfile(VALUE obj)
02920 {
02921 struct gzfile *gz;
02922
02923 Data_Get_Struct(obj, struct gzfile, gz);
02924 if (!ZSTREAM_IS_READY(&gz->z)) {
02925 rb_raise(cGzError, "closed gzip stream");
02926 }
02927 return gz;
02928 }
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971 typedef struct {
02972 int argc;
02973 VALUE *argv;
02974 VALUE klass;
02975 } new_wrap_arg_t;
02976
02977 static VALUE
02978 new_wrap(VALUE tmp)
02979 {
02980 new_wrap_arg_t *arg = (new_wrap_arg_t *)tmp;
02981 return rb_class_new_instance(arg->argc, arg->argv, arg->klass);
02982 }
02983
02984 static VALUE
02985 gzfile_ensure_close(VALUE obj)
02986 {
02987 struct gzfile *gz;
02988
02989 Data_Get_Struct(obj, struct gzfile, gz);
02990 if (ZSTREAM_IS_READY(&gz->z)) {
02991 gzfile_close(gz, 1);
02992 }
02993 return Qnil;
02994 }
02995
02996 static VALUE
02997 gzfile_wrap(int argc, VALUE *argv, VALUE klass, int close_io_on_error)
02998 {
02999 VALUE obj;
03000
03001 if (close_io_on_error) {
03002 int state = 0;
03003 new_wrap_arg_t arg;
03004 arg.argc = argc;
03005 arg.argv = argv;
03006 arg.klass = klass;
03007 obj = rb_protect(new_wrap, (VALUE)&arg, &state);
03008 if (state) {
03009 rb_io_close(argv[0]);
03010 rb_jump_tag(state);
03011 }
03012 }
03013 else {
03014 obj = rb_class_new_instance(argc, argv, klass);
03015 }
03016
03017 if (rb_block_given_p()) {
03018 return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
03019 }
03020 else {
03021 return obj;
03022 }
03023 }
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040 static VALUE
03041 rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
03042 {
03043 return gzfile_wrap(argc, argv, klass, 0);
03044 }
03045
03046
03047
03048
03049
03050
03051 static VALUE
03052 gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
03053 {
03054 VALUE io, filename;
03055
03056 if (argc < 1) {
03057 rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
03058 }
03059 filename = argv[0];
03060 io = rb_file_open_str(filename, mode);
03061 argv[0] = io;
03062 return gzfile_wrap(argc, argv, klass, 1);
03063 }
03064
03065
03066
03067
03068
03069
03070 static VALUE
03071 rb_gzfile_to_io(VALUE obj)
03072 {
03073 return get_gzfile(obj)->io;
03074 }
03075
03076
03077
03078
03079
03080
03081 static VALUE
03082 rb_gzfile_crc(VALUE obj)
03083 {
03084 return rb_uint2inum(get_gzfile(obj)->crc);
03085 }
03086
03087
03088
03089
03090
03091
03092 static VALUE
03093 rb_gzfile_mtime(VALUE obj)
03094 {
03095 return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
03096 }
03097
03098
03099
03100
03101
03102
03103 static VALUE
03104 rb_gzfile_level(VALUE obj)
03105 {
03106 return INT2FIX(get_gzfile(obj)->level);
03107 }
03108
03109
03110
03111
03112
03113
03114 static VALUE
03115 rb_gzfile_os_code(VALUE obj)
03116 {
03117 return INT2FIX(get_gzfile(obj)->os_code);
03118 }
03119
03120
03121
03122
03123
03124
03125
03126 static VALUE
03127 rb_gzfile_orig_name(VALUE obj)
03128 {
03129 VALUE str = get_gzfile(obj)->orig_name;
03130 if (!NIL_P(str)) {
03131 str = rb_str_dup(str);
03132 }
03133 OBJ_TAINT(str);
03134 return str;
03135 }
03136
03137
03138
03139
03140
03141
03142
03143 static VALUE
03144 rb_gzfile_comment(VALUE obj)
03145 {
03146 VALUE str = get_gzfile(obj)->comment;
03147 if (!NIL_P(str)) {
03148 str = rb_str_dup(str);
03149 }
03150 OBJ_TAINT(str);
03151 return str;
03152 }
03153
03154
03155
03156
03157
03158
03159 static VALUE
03160 rb_gzfile_lineno(VALUE obj)
03161 {
03162 return INT2NUM(get_gzfile(obj)->lineno);
03163 }
03164
03165
03166
03167
03168
03169
03170 static VALUE
03171 rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
03172 {
03173 struct gzfile *gz = get_gzfile(obj);
03174 gz->lineno = NUM2INT(lineno);
03175 return lineno;
03176 }
03177
03178
03179
03180
03181
03182
03183
03184 static VALUE
03185 rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
03186 {
03187 struct gzfile *gz = get_gzfile(obj);
03188 VALUE val;
03189
03190 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03191 rb_raise(cGzError, "header is already written");
03192 }
03193
03194 if (FIXNUM_P(mtime)) {
03195 gz->mtime = FIX2INT(mtime);
03196 }
03197 else {
03198 val = rb_Integer(mtime);
03199 gz->mtime = FIXNUM_P(val) ? FIX2UINT(val) : rb_big2ulong(val);
03200 }
03201 return mtime;
03202 }
03203
03204
03205
03206
03207
03208
03209 static VALUE
03210 rb_gzfile_set_orig_name(VALUE obj, VALUE str)
03211 {
03212 struct gzfile *gz = get_gzfile(obj);
03213 VALUE s;
03214 char *p;
03215
03216 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03217 rb_raise(cGzError, "header is already written");
03218 }
03219 s = rb_str_dup(rb_str_to_str(str));
03220 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
03221 if (p) {
03222 rb_str_resize(s, p - RSTRING_PTR(s));
03223 }
03224 gz->orig_name = s;
03225 return str;
03226 }
03227
03228
03229
03230
03231
03232
03233 static VALUE
03234 rb_gzfile_set_comment(VALUE obj, VALUE str)
03235 {
03236 struct gzfile *gz = get_gzfile(obj);
03237 VALUE s;
03238 char *p;
03239
03240 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
03241 rb_raise(cGzError, "header is already written");
03242 }
03243 s = rb_str_dup(rb_str_to_str(str));
03244 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
03245 if (p) {
03246 rb_str_resize(s, p - RSTRING_PTR(s));
03247 }
03248 gz->comment = s;
03249 return str;
03250 }
03251
03252
03253
03254
03255
03256
03257
03258 static VALUE
03259 rb_gzfile_close(VALUE obj)
03260 {
03261 struct gzfile *gz = get_gzfile(obj);
03262 VALUE io;
03263
03264 io = gz->io;
03265 gzfile_close(gz, 1);
03266 return io;
03267 }
03268
03269
03270
03271
03272
03273
03274
03275
03276 static VALUE
03277 rb_gzfile_finish(VALUE obj)
03278 {
03279 struct gzfile *gz = get_gzfile(obj);
03280 VALUE io;
03281
03282 io = gz->io;
03283 gzfile_close(gz, 0);
03284 return io;
03285 }
03286
03287
03288
03289
03290
03291
03292
03293 static VALUE
03294 rb_gzfile_closed_p(VALUE obj)
03295 {
03296 struct gzfile *gz;
03297 Data_Get_Struct(obj, struct gzfile, gz);
03298 return NIL_P(gz->io) ? Qtrue : Qfalse;
03299 }
03300
03301
03302
03303
03304
03305
03306 static VALUE
03307 rb_gzfile_eof_p(VALUE obj)
03308 {
03309 struct gzfile *gz = get_gzfile(obj);
03310 return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
03311 }
03312
03313
03314
03315
03316
03317
03318
03319 static VALUE
03320 rb_gzfile_sync(VALUE obj)
03321 {
03322 return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
03323 }
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334 static VALUE
03335 rb_gzfile_set_sync(VALUE obj, VALUE mode)
03336 {
03337 struct gzfile *gz = get_gzfile(obj);
03338
03339 if (RTEST(mode)) {
03340 gz->z.flags |= GZFILE_FLAG_SYNC;
03341 }
03342 else {
03343 gz->z.flags &= ~GZFILE_FLAG_SYNC;
03344 }
03345 return mode;
03346 }
03347
03348
03349
03350
03351
03352
03353 static VALUE
03354 rb_gzfile_total_in(VALUE obj)
03355 {
03356 return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
03357 }
03358
03359
03360
03361
03362
03363
03364 static VALUE
03365 rb_gzfile_total_out(VALUE obj)
03366 {
03367 struct gzfile *gz = get_gzfile(obj);
03368 return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
03369 }
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379 static VALUE
03380 rb_gzfile_path(VALUE obj)
03381 {
03382 struct gzfile *gz;
03383 Data_Get_Struct(obj, struct gzfile, gz);
03384 return gz->path;
03385 }
03386
03387 static void
03388 rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
03389 {
03390 if (!NIL_P(opts)) {
03391 rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
03392 }
03393 if (gz->enc2) {
03394 gz->ecflags = rb_econv_prepare_opts(opts, &opts);
03395 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
03396 gz->ecflags, opts);
03397 gz->ecopts = opts;
03398 }
03399 }
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436 static VALUE
03437 rb_gzwriter_s_allocate(VALUE klass)
03438 {
03439 return gzfile_writer_new(klass);
03440 }
03441
03442
03443
03444
03445
03446
03447
03448
03449 static VALUE
03450 rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
03451 {
03452 return gzfile_s_open(argc, argv, klass, "wb");
03453 }
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468 static VALUE
03469 rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
03470 {
03471 struct gzfile *gz;
03472 VALUE io, level, strategy, opt = Qnil;
03473 int err;
03474
03475 if (argc > 1) {
03476 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
03477 if (!NIL_P(opt)) argc--;
03478 }
03479
03480 rb_scan_args(argc, argv, "12", &io, &level, &strategy);
03481 Data_Get_Struct(obj, struct gzfile, gz);
03482
03483
03484 gz->level = ARG_LEVEL(level);
03485 err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
03486 -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
03487 if (err != Z_OK) {
03488 raise_zlib_error(err, gz->z.stream.msg);
03489 }
03490 gz->io = io;
03491 ZSTREAM_READY(&gz->z);
03492 rb_gzfile_ecopts(gz, opt);
03493
03494 if (rb_respond_to(io, id_path)) {
03495 gz->path = rb_funcall(gz->io, id_path, 0);
03496 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03497 }
03498
03499 return obj;
03500 }
03501
03502
03503
03504
03505
03506
03507
03508
03509 static VALUE
03510 rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
03511 {
03512 struct gzfile *gz = get_gzfile(obj);
03513 VALUE v_flush;
03514 int flush;
03515
03516 rb_scan_args(argc, argv, "01", &v_flush);
03517
03518 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
03519 if (flush != Z_NO_FLUSH) {
03520 zstream_run(&gz->z, (Bytef*)"", 0, flush);
03521 }
03522
03523 gzfile_write_raw(gz);
03524 if (rb_respond_to(gz->io, id_flush)) {
03525 rb_funcall(gz->io, id_flush, 0);
03526 }
03527 return obj;
03528 }
03529
03530
03531
03532
03533 static VALUE
03534 rb_gzwriter_write(VALUE obj, VALUE str)
03535 {
03536 struct gzfile *gz = get_gzfile(obj);
03537
03538 if (!RB_TYPE_P(str, T_STRING))
03539 str = rb_obj_as_string(str);
03540 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03541 str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
03542 }
03543 gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
03544 return INT2FIX(RSTRING_LEN(str));
03545 }
03546
03547
03548
03549
03550 static VALUE
03551 rb_gzwriter_putc(VALUE obj, VALUE ch)
03552 {
03553 struct gzfile *gz = get_gzfile(obj);
03554 char c = NUM2CHR(ch);
03555
03556 gzfile_write(gz, (Bytef*)&c, 1);
03557 return ch;
03558 }
03559
03560
03561
03562
03563
03564
03565
03566 #define rb_gzwriter_addstr rb_io_addstr
03567
03568
03569
03570
03571 #define rb_gzwriter_printf rb_io_printf
03572
03573
03574
03575
03576 #define rb_gzwriter_print rb_io_print
03577
03578
03579
03580
03581 #define rb_gzwriter_puts rb_io_puts
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638 static VALUE
03639 rb_gzreader_s_allocate(VALUE klass)
03640 {
03641 return gzfile_reader_new(klass);
03642 }
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653 static VALUE
03654 rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
03655 {
03656 return gzfile_s_open(argc, argv, klass, "rb");
03657 }
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676 static VALUE
03677 rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
03678 {
03679 VALUE io, opt = Qnil;
03680 struct gzfile *gz;
03681 int err;
03682
03683 Data_Get_Struct(obj, struct gzfile, gz);
03684 rb_scan_args(argc, argv, "1:", &io, &opt);
03685
03686
03687 err = inflateInit2(&gz->z.stream, -MAX_WBITS);
03688 if (err != Z_OK) {
03689 raise_zlib_error(err, gz->z.stream.msg);
03690 }
03691 gz->io = io;
03692 ZSTREAM_READY(&gz->z);
03693 gzfile_read_header(gz);
03694 rb_gzfile_ecopts(gz, opt);
03695
03696 if (rb_respond_to(io, id_path)) {
03697 gz->path = rb_funcall(gz->io, id_path, 0);
03698 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03699 }
03700
03701 return obj;
03702 }
03703
03704
03705
03706
03707
03708
03709
03710 static VALUE
03711 rb_gzreader_rewind(VALUE obj)
03712 {
03713 struct gzfile *gz = get_gzfile(obj);
03714 gzfile_reader_rewind(gz);
03715 return INT2FIX(0);
03716 }
03717
03718
03719
03720
03721
03722
03723
03724 static VALUE
03725 rb_gzreader_unused(VALUE obj)
03726 {
03727 struct gzfile *gz;
03728 Data_Get_Struct(obj, struct gzfile, gz);
03729 return gzfile_reader_get_unused(gz);
03730 }
03731
03732
03733
03734
03735
03736
03737 static VALUE
03738 rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
03739 {
03740 struct gzfile *gz = get_gzfile(obj);
03741 VALUE vlen;
03742 long len;
03743
03744 rb_scan_args(argc, argv, "01", &vlen);
03745 if (NIL_P(vlen)) {
03746 return gzfile_read_all(gz);
03747 }
03748
03749 len = NUM2INT(vlen);
03750 if (len < 0) {
03751 rb_raise(rb_eArgError, "negative length %ld given", len);
03752 }
03753 return gzfile_read(gz, len);
03754 }
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768 static VALUE
03769 rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
03770 {
03771 struct gzfile *gz = get_gzfile(obj);
03772 VALUE vlen, outbuf;
03773 long len;
03774
03775 rb_scan_args(argc, argv, "11", &vlen, &outbuf);
03776
03777 len = NUM2INT(vlen);
03778 if (len < 0) {
03779 rb_raise(rb_eArgError, "negative length %ld given", len);
03780 }
03781 if (!NIL_P(outbuf))
03782 Check_Type(outbuf, T_STRING);
03783 return gzfile_readpartial(gz, len, outbuf);
03784 }
03785
03786
03787
03788
03789
03790
03791 static VALUE
03792 rb_gzreader_getc(VALUE obj)
03793 {
03794 struct gzfile *gz = get_gzfile(obj);
03795
03796 return gzfile_getc(gz);
03797 }
03798
03799
03800
03801
03802
03803
03804 static VALUE
03805 rb_gzreader_readchar(VALUE obj)
03806 {
03807 VALUE dst;
03808 dst = rb_gzreader_getc(obj);
03809 if (NIL_P(dst)) {
03810 rb_raise(rb_eEOFError, "end of file reached");
03811 }
03812 return dst;
03813 }
03814
03815
03816
03817
03818
03819
03820 static VALUE
03821 rb_gzreader_getbyte(VALUE obj)
03822 {
03823 struct gzfile *gz = get_gzfile(obj);
03824 VALUE dst;
03825
03826 dst = gzfile_read(gz, 1);
03827 if (!NIL_P(dst)) {
03828 dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
03829 }
03830 return dst;
03831 }
03832
03833
03834
03835
03836
03837
03838 static VALUE
03839 rb_gzreader_readbyte(VALUE obj)
03840 {
03841 VALUE dst;
03842 dst = rb_gzreader_getbyte(obj);
03843 if (NIL_P(dst)) {
03844 rb_raise(rb_eEOFError, "end of file reached");
03845 }
03846 return dst;
03847 }
03848
03849
03850
03851
03852
03853
03854 static VALUE
03855 rb_gzreader_each_char(VALUE obj)
03856 {
03857 VALUE c;
03858
03859 RETURN_ENUMERATOR(obj, 0, 0);
03860
03861 while (!NIL_P(c = rb_gzreader_getc(obj))) {
03862 rb_yield(c);
03863 }
03864 return Qnil;
03865 }
03866
03867
03868
03869
03870
03871
03872 static VALUE
03873 rb_gzreader_each_byte(VALUE obj)
03874 {
03875 VALUE c;
03876
03877 RETURN_ENUMERATOR(obj, 0, 0);
03878
03879 while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
03880 rb_yield(c);
03881 }
03882 return Qnil;
03883 }
03884
03885
03886
03887
03888
03889
03890 static VALUE
03891 rb_gzreader_bytes(VALUE obj)
03892 {
03893 rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
03894 if (!rb_block_given_p())
03895 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
03896 return rb_gzreader_each_byte(obj);
03897 }
03898
03899
03900
03901
03902
03903
03904 static VALUE
03905 rb_gzreader_ungetc(VALUE obj, VALUE s)
03906 {
03907 struct gzfile *gz;
03908
03909 if (FIXNUM_P(s))
03910 return rb_gzreader_ungetbyte(obj, s);
03911 gz = get_gzfile(obj);
03912 StringValue(s);
03913 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03914 s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
03915 }
03916 gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
03917 return Qnil;
03918 }
03919
03920
03921
03922
03923
03924
03925 static VALUE
03926 rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
03927 {
03928 struct gzfile *gz = get_gzfile(obj);
03929 gzfile_ungetbyte(gz, NUM2CHR(ch));
03930 return Qnil;
03931 }
03932
03933 static void
03934 gzreader_skip_linebreaks(struct gzfile *gz)
03935 {
03936 VALUE str;
03937 char *p;
03938 int n;
03939
03940 while (gz->z.buf_filled == 0) {
03941 if (GZFILE_IS_FINISHED(gz)) return;
03942 gzfile_read_more(gz);
03943 }
03944 n = 0;
03945 p = RSTRING_PTR(gz->z.buf);
03946
03947 while (n++, *(p++) == '\n') {
03948 if (n >= gz->z.buf_filled) {
03949 str = zstream_detach_buffer(&gz->z);
03950 gzfile_calc_crc(gz, str);
03951 while (gz->z.buf_filled == 0) {
03952 if (GZFILE_IS_FINISHED(gz)) return;
03953 gzfile_read_more(gz);
03954 }
03955 n = 0;
03956 p = RSTRING_PTR(gz->z.buf);
03957 }
03958 }
03959
03960 str = zstream_shift_buffer(&gz->z, n - 1);
03961 gzfile_calc_crc(gz, str);
03962 }
03963
03964 static void
03965 rscheck(const char *rsptr, long rslen, VALUE rs)
03966 {
03967 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
03968 rb_raise(rb_eRuntimeError, "rs modified");
03969 }
03970
03971 static long
03972 gzreader_charboundary(struct gzfile *gz, long n)
03973 {
03974 char *s = RSTRING_PTR(gz->z.buf);
03975 char *e = s + gz->z.buf_filled;
03976 char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
03977 long l = p - s;
03978 if (l < n) {
03979 n = rb_enc_precise_mbclen(p, e, gz->enc);
03980 if (MBCLEN_NEEDMORE_P(n)) {
03981 if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
03982 return l;
03983 }
03984 }
03985 else if (MBCLEN_CHARFOUND_P(n)) {
03986 return l + MBCLEN_CHARFOUND_LEN(n);
03987 }
03988 }
03989 return n;
03990 }
03991
03992 static VALUE
03993 gzreader_gets(int argc, VALUE *argv, VALUE obj)
03994 {
03995 struct gzfile *gz = get_gzfile(obj);
03996 volatile VALUE rs;
03997 VALUE dst;
03998 const char *rsptr;
03999 char *p, *res;
04000 long rslen, n, limit = -1;
04001 int rspara;
04002 rb_encoding *enc = gz->enc;
04003 int maxlen = rb_enc_mbmaxlen(enc);
04004
04005 if (argc == 0) {
04006 rs = rb_rs;
04007 }
04008 else {
04009 VALUE lim, tmp;
04010
04011 rb_scan_args(argc, argv, "11", &rs, &lim);
04012 if (!NIL_P(lim)) {
04013 if (!NIL_P(rs)) StringValue(rs);
04014 }
04015 else if (!NIL_P(rs)) {
04016 tmp = rb_check_string_type(rs);
04017 if (NIL_P(tmp)) {
04018 lim = rs;
04019 rs = rb_rs;
04020 }
04021 else {
04022 rs = tmp;
04023 }
04024 }
04025 if (!NIL_P(lim)) {
04026 limit = NUM2LONG(lim);
04027 if (limit == 0) return rb_str_new(0,0);
04028 }
04029 }
04030
04031 if (NIL_P(rs)) {
04032 if (limit < 0) {
04033 dst = gzfile_read_all(gz);
04034 if (RSTRING_LEN(dst) == 0) return Qnil;
04035 }
04036 else if ((n = gzfile_fill(gz, limit)) <= 0) {
04037 return Qnil;
04038 }
04039 else {
04040 if (maxlen > 1 && n >= limit && !GZFILE_IS_FINISHED(gz)) {
04041 n = gzreader_charboundary(gz, n);
04042 }
04043 else {
04044 n = limit;
04045 }
04046 dst = zstream_shift_buffer(&gz->z, n);
04047 if (NIL_P(dst)) return dst;
04048 gzfile_calc_crc(gz, dst);
04049 dst = gzfile_newstr(gz, dst);
04050 }
04051 gz->lineno++;
04052 return dst;
04053 }
04054
04055 if (RSTRING_LEN(rs) == 0) {
04056 rsptr = "\n\n";
04057 rslen = 2;
04058 rspara = 1;
04059 } else {
04060 rsptr = RSTRING_PTR(rs);
04061 rslen = RSTRING_LEN(rs);
04062 rspara = 0;
04063 }
04064
04065 if (rspara) {
04066 gzreader_skip_linebreaks(gz);
04067 }
04068
04069 while (gz->z.buf_filled < rslen) {
04070 if (ZSTREAM_IS_FINISHED(&gz->z)) {
04071 if (gz->z.buf_filled > 0) gz->lineno++;
04072 return gzfile_read(gz, rslen);
04073 }
04074 gzfile_read_more(gz);
04075 }
04076
04077 p = RSTRING_PTR(gz->z.buf);
04078 n = rslen;
04079 for (;;) {
04080 long filled;
04081 if (n > gz->z.buf_filled) {
04082 if (ZSTREAM_IS_FINISHED(&gz->z)) break;
04083 gzfile_read_more(gz);
04084 p = RSTRING_PTR(gz->z.buf) + n - rslen;
04085 }
04086 if (!rspara) rscheck(rsptr, rslen, rs);
04087 filled = gz->z.buf_filled;
04088 if (limit > 0 && filled >= limit) {
04089 filled = limit;
04090 }
04091 res = memchr(p, rsptr[0], (filled - n + 1));
04092 if (!res) {
04093 n = filled;
04094 if (limit > 0 && filled >= limit) break;
04095 n++;
04096 } else {
04097 n += (long)(res - p);
04098 p = res;
04099 if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
04100 p++, n++;
04101 }
04102 }
04103 if (maxlen > 1 && n == limit && (gz->z.buf_filled > n || !ZSTREAM_IS_FINISHED(&gz->z))) {
04104 n = gzreader_charboundary(gz, n);
04105 }
04106
04107 gz->lineno++;
04108 dst = gzfile_read(gz, n);
04109 if (NIL_P(dst)) return dst;
04110 if (rspara) {
04111 gzreader_skip_linebreaks(gz);
04112 }
04113
04114 return gzfile_newstr(gz, dst);
04115 }
04116
04117
04118
04119
04120
04121
04122 static VALUE
04123 rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
04124 {
04125 VALUE dst;
04126 dst = gzreader_gets(argc, argv, obj);
04127 if (!NIL_P(dst)) {
04128 rb_lastline_set(dst);
04129 }
04130 return dst;
04131 }
04132
04133
04134
04135
04136
04137
04138 static VALUE
04139 rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
04140 {
04141 VALUE dst;
04142 dst = rb_gzreader_gets(argc, argv, obj);
04143 if (NIL_P(dst)) {
04144 rb_raise(rb_eEOFError, "end of file reached");
04145 }
04146 return dst;
04147 }
04148
04149
04150
04151
04152
04153
04154 static VALUE
04155 rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
04156 {
04157 VALUE str;
04158
04159 RETURN_ENUMERATOR(obj, 0, 0);
04160
04161 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
04162 rb_yield(str);
04163 }
04164 return obj;
04165 }
04166
04167
04168
04169
04170
04171
04172 static VALUE
04173 rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
04174 {
04175 rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
04176 if (!rb_block_given_p())
04177 return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
04178 return rb_gzreader_each(argc, argv, obj);
04179 }
04180
04181
04182
04183
04184
04185
04186 static VALUE
04187 rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
04188 {
04189 VALUE str, dst;
04190 dst = rb_ary_new();
04191 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
04192 rb_ary_push(dst, str);
04193 }
04194 return dst;
04195 }
04196
04197 #endif
04198
04199 void
04200 Init_zlib()
04201 {
04202 VALUE mZlib, cZStream, cDeflate, cInflate;
04203 #if GZIP_SUPPORT
04204 VALUE cGzipFile, cGzipWriter, cGzipReader;
04205 #endif
04206
04207 mZlib = rb_define_module("Zlib");
04208
04209 id_dictionaries = rb_intern("@dictionaries");
04210
04211 cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
04212 cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
04213 cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
04214 cDataError = rb_define_class_under(mZlib, "DataError", cZError);
04215 cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
04216 cMemError = rb_define_class_under(mZlib, "MemError", cZError);
04217 cBufError = rb_define_class_under(mZlib, "BufError", cZError);
04218 cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
04219
04220 rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
04221 rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
04222 rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
04223 rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
04224 rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
04225 rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
04226
04227
04228 rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
04229
04230 rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
04231
04232 cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
04233 rb_undef_alloc_func(cZStream);
04234 rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
04235 rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
04236 rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
04237 rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
04238 rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
04239 rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
04240 rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
04241 rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
04242 rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
04243 rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
04244 rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
04245 rb_define_method(cZStream, "close", rb_zstream_end, 0);
04246 rb_define_method(cZStream, "end", rb_zstream_end, 0);
04247 rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
04248 rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
04249 rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
04250 rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
04251
04252
04253
04254
04255 rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
04256
04257
04258
04259
04260
04261
04262
04263 rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
04264
04265 #ifdef Z_TEXT
04266
04267
04268
04269 rb_define_const(mZlib, "TEXT", INT2FIX(Z_TEXT));
04270 #endif
04271
04272
04273
04274
04275 rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
04276
04277 cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
04278 rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
04279 rb_define_singleton_method(mZlib, "deflate", rb_deflate_s_deflate, -1);
04280 rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
04281 rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
04282 rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
04283 rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
04284 rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
04285 rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
04286 rb_define_method(cDeflate, "params", rb_deflate_params, 2);
04287 rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
04288
04289 cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
04290 rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
04291 rb_define_singleton_method(mZlib, "inflate", rb_inflate_s_inflate, 1);
04292 rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
04293 rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
04294 rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
04295 rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
04296 rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
04297 rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
04298 rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
04299 rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
04300
04301
04302
04303
04304 rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
04305
04306 rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
04307
04308 rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
04309
04310
04311
04312 rb_define_const(mZlib, "DEFAULT_COMPRESSION",
04313 INT2FIX(Z_DEFAULT_COMPRESSION));
04314
04315
04316
04317
04318
04319
04320
04321 rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
04322
04323
04324 rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
04325
04326 #ifdef Z_RLE
04327
04328
04329
04330 rb_define_const(mZlib, "RLE", INT2FIX(Z_RLE));
04331 #endif
04332
04333 #ifdef Z_FIXED
04334
04335
04336
04337 rb_define_const(mZlib, "FIXED", INT2FIX(Z_FIXED));
04338 #endif
04339
04340
04341 rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
04342
04343
04344
04345
04346
04347 rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
04348
04349
04350
04351 rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
04352
04353
04354
04355 rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
04356
04357
04358
04359
04360
04361 rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
04362
04363
04364
04365
04366
04367
04368 rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
04369
04370
04371
04372
04373
04374
04375
04376 rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
04377
04378
04379 rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
04380
04381 #if GZIP_SUPPORT
04382 id_write = rb_intern("write");
04383 id_read = rb_intern("read");
04384 id_readpartial = rb_intern("readpartial");
04385 id_flush = rb_intern("flush");
04386 id_seek = rb_intern("seek");
04387 id_close = rb_intern("close");
04388 id_path = rb_intern("path");
04389 id_input = rb_intern("@input");
04390
04391 cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
04392 cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
04393
04394
04395 rb_define_attr(cGzError, "input", 1, 0);
04396 rb_define_method(cGzError, "inspect", gzfile_error_inspect, 0);
04397
04398 cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
04399 cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
04400 cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
04401
04402 cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
04403 cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
04404 rb_include_module(cGzipReader, rb_mEnumerable);
04405
04406 rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
04407 rb_undef_alloc_func(cGzipFile);
04408 rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
04409 rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
04410 rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
04411 rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
04412 rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
04413 rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
04414 rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
04415 rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
04416 rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
04417 rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
04418 rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
04419 rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
04420 rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
04421 rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
04422 rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
04423 rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
04424 rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
04425 rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
04426 rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
04427 rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
04428 rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
04429 rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
04430 rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
04431
04432 rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
04433 rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
04434 rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
04435 rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
04436 rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
04437 rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
04438 rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
04439 rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
04440 rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
04441 rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
04442
04443 rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
04444 rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
04445 rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
04446 rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
04447 rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
04448 rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
04449 rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
04450 rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
04451 rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
04452 rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
04453 rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
04454 rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
04455 rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
04456 rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
04457 rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
04458 rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
04459 rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
04460 rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
04461 rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
04462 rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
04463 rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
04464 rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
04465
04466
04467 rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
04468
04469 rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
04470
04471 rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
04472
04473 rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
04474
04475 rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
04476
04477 rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
04478
04479 rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
04480
04481 rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
04482
04483 rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
04484
04485 rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
04486
04487 rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
04488
04489 rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
04490
04491 rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
04492
04493 rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
04494
04495 rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
04496
04497 rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
04498
04499 #endif
04500 }
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621