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