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 (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 static VALUE
02392 gzfile_reader_get_unused(struct gzfile *gz)
02393 {
02394 VALUE str;
02395
02396 if (!ZSTREAM_IS_READY(&gz->z)) return Qnil;
02397 if (!GZFILE_IS_FINISHED(gz)) return Qnil;
02398 if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
02399 gzfile_check_footer(gz);
02400 }
02401 if (NIL_P(gz->z.input)) return Qnil;
02402
02403 str = rb_str_dup(gz->z.input);
02404 OBJ_TAINT(str);
02405 return str;
02406 }
02407
02408 static struct gzfile *
02409 get_gzfile(VALUE obj)
02410 {
02411 struct gzfile *gz;
02412
02413 Data_Get_Struct(obj, struct gzfile, gz);
02414 if (!ZSTREAM_IS_READY(&gz->z)) {
02415 rb_raise(cGzError, "closed gzip stream");
02416 }
02417 return gz;
02418 }
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434 static VALUE
02435 gzfile_ensure_close(VALUE obj)
02436 {
02437 struct gzfile *gz;
02438
02439 Data_Get_Struct(obj, struct gzfile, gz);
02440 if (ZSTREAM_IS_READY(&gz->z)) {
02441 gzfile_close(gz, 1);
02442 }
02443 return Qnil;
02444 }
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456 static VALUE
02457 rb_gzfile_s_wrap(int argc, VALUE *argv, VALUE klass)
02458 {
02459 VALUE obj = rb_class_new_instance(argc, argv, klass);
02460
02461 if (rb_block_given_p()) {
02462 return rb_ensure(rb_yield, obj, gzfile_ensure_close, obj);
02463 }
02464 else {
02465 return obj;
02466 }
02467 }
02468
02469
02470
02471
02472 static VALUE
02473 gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
02474 {
02475 VALUE io, filename;
02476
02477 if (argc < 1) {
02478 rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
02479 }
02480 filename = argv[0];
02481 io = rb_file_open_str(filename, mode);
02482 argv[0] = io;
02483 return rb_gzfile_s_wrap(argc, argv, klass);
02484 }
02485
02486
02487
02488
02489 static VALUE
02490 rb_gzfile_to_io(VALUE obj)
02491 {
02492 return get_gzfile(obj)->io;
02493 }
02494
02495
02496
02497
02498 static VALUE
02499 rb_gzfile_crc(VALUE obj)
02500 {
02501 return rb_uint2inum(get_gzfile(obj)->crc);
02502 }
02503
02504
02505
02506
02507 static VALUE
02508 rb_gzfile_mtime(VALUE obj)
02509 {
02510 return rb_time_new(get_gzfile(obj)->mtime, (time_t)0);
02511 }
02512
02513
02514
02515
02516 static VALUE
02517 rb_gzfile_level(VALUE obj)
02518 {
02519 return INT2FIX(get_gzfile(obj)->level);
02520 }
02521
02522
02523
02524
02525 static VALUE
02526 rb_gzfile_os_code(VALUE obj)
02527 {
02528 return INT2FIX(get_gzfile(obj)->os_code);
02529 }
02530
02531
02532
02533
02534
02535 static VALUE
02536 rb_gzfile_orig_name(VALUE obj)
02537 {
02538 VALUE str = get_gzfile(obj)->orig_name;
02539 if (!NIL_P(str)) {
02540 str = rb_str_dup(str);
02541 }
02542 OBJ_TAINT(str);
02543 return str;
02544 }
02545
02546
02547
02548
02549
02550 static VALUE
02551 rb_gzfile_comment(VALUE obj)
02552 {
02553 VALUE str = get_gzfile(obj)->comment;
02554 if (!NIL_P(str)) {
02555 str = rb_str_dup(str);
02556 }
02557 OBJ_TAINT(str);
02558 return str;
02559 }
02560
02561
02562
02563
02564 static VALUE
02565 rb_gzfile_lineno(VALUE obj)
02566 {
02567 return INT2NUM(get_gzfile(obj)->lineno);
02568 }
02569
02570
02571
02572
02573 static VALUE
02574 rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
02575 {
02576 struct gzfile *gz = get_gzfile(obj);
02577 gz->lineno = NUM2INT(lineno);
02578 return lineno;
02579 }
02580
02581
02582
02583
02584 static VALUE
02585 rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
02586 {
02587 struct gzfile *gz = get_gzfile(obj);
02588 VALUE val;
02589
02590 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02591 rb_raise(cGzError, "header is already written");
02592 }
02593
02594 if (FIXNUM_P(mtime)) {
02595 gz->mtime = FIX2INT(mtime);
02596 }
02597 else {
02598 val = rb_Integer(mtime);
02599 gz->mtime = FIXNUM_P(val) ? FIX2UINT(val) : rb_big2ulong(val);
02600 }
02601 return mtime;
02602 }
02603
02604
02605
02606
02607 static VALUE
02608 rb_gzfile_set_orig_name(VALUE obj, VALUE str)
02609 {
02610 struct gzfile *gz = get_gzfile(obj);
02611 VALUE s;
02612 char *p;
02613
02614 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02615 rb_raise(cGzError, "header is already written");
02616 }
02617 s = rb_str_dup(rb_str_to_str(str));
02618 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
02619 if (p) {
02620 rb_str_resize(s, p - RSTRING_PTR(s));
02621 }
02622 gz->orig_name = s;
02623 return str;
02624 }
02625
02626
02627
02628
02629 static VALUE
02630 rb_gzfile_set_comment(VALUE obj, VALUE str)
02631 {
02632 struct gzfile *gz = get_gzfile(obj);
02633 VALUE s;
02634 char *p;
02635
02636 if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
02637 rb_raise(cGzError, "header is already written");
02638 }
02639 s = rb_str_dup(rb_str_to_str(str));
02640 p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
02641 if (p) {
02642 rb_str_resize(s, p - RSTRING_PTR(s));
02643 }
02644 gz->comment = s;
02645 return str;
02646 }
02647
02648
02649
02650
02651
02652 static VALUE
02653 rb_gzfile_close(VALUE obj)
02654 {
02655 struct gzfile *gz = get_gzfile(obj);
02656 VALUE io;
02657
02658 io = gz->io;
02659 gzfile_close(gz, 1);
02660 return io;
02661 }
02662
02663
02664
02665
02666
02667
02668 static VALUE
02669 rb_gzfile_finish(VALUE obj)
02670 {
02671 struct gzfile *gz = get_gzfile(obj);
02672 VALUE io;
02673
02674 io = gz->io;
02675 gzfile_close(gz, 0);
02676 return io;
02677 }
02678
02679
02680
02681
02682 static VALUE
02683 rb_gzfile_closed_p(VALUE obj)
02684 {
02685 struct gzfile *gz;
02686 Data_Get_Struct(obj, struct gzfile, gz);
02687 return NIL_P(gz->io) ? Qtrue : Qfalse;
02688 }
02689
02690
02691
02692
02693 static VALUE
02694 rb_gzfile_eof_p(VALUE obj)
02695 {
02696 struct gzfile *gz = get_gzfile(obj);
02697 return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
02698 }
02699
02700
02701
02702
02703 static VALUE
02704 rb_gzfile_sync(VALUE obj)
02705 {
02706 return (get_gzfile(obj)->z.flags & GZFILE_FLAG_SYNC) ? Qtrue : Qfalse;
02707 }
02708
02709
02710
02711
02712
02713
02714
02715
02716 static VALUE
02717 rb_gzfile_set_sync(VALUE obj, VALUE mode)
02718 {
02719 struct gzfile *gz = get_gzfile(obj);
02720
02721 if (RTEST(mode)) {
02722 gz->z.flags |= GZFILE_FLAG_SYNC;
02723 }
02724 else {
02725 gz->z.flags &= ~GZFILE_FLAG_SYNC;
02726 }
02727 return mode;
02728 }
02729
02730
02731
02732
02733 static VALUE
02734 rb_gzfile_total_in(VALUE obj)
02735 {
02736 return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
02737 }
02738
02739
02740
02741
02742 static VALUE
02743 rb_gzfile_total_out(VALUE obj)
02744 {
02745 struct gzfile *gz = get_gzfile(obj);
02746 return rb_uint2inum(gz->z.stream.total_out - gz->z.buf_filled);
02747 }
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757 static VALUE
02758 rb_gzfile_path(VALUE obj)
02759 {
02760 struct gzfile *gz;
02761 Data_Get_Struct(obj, struct gzfile, gz);
02762 return gz->path;
02763 }
02764
02765 static void
02766 rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
02767 {
02768 if (!NIL_P(opts)) {
02769 rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2);
02770 }
02771 if (gz->enc2) {
02772 gz->ecflags = rb_econv_prepare_opts(opts, &opts);
02773 gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
02774 gz->ecflags, opts);
02775 gz->ecopts = opts;
02776 }
02777 }
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 static VALUE
02809 rb_gzwriter_s_allocate(VALUE klass)
02810 {
02811 return gzfile_writer_new(klass);
02812 }
02813
02814
02815
02816
02817
02818
02819
02820
02821 static VALUE
02822 rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
02823 {
02824 return gzfile_s_open(argc, argv, klass, "wb");
02825 }
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835 static VALUE
02836 rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
02837 {
02838 struct gzfile *gz;
02839 VALUE io, level, strategy, opt = Qnil;
02840 int err;
02841
02842 if (argc > 1) {
02843 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
02844 if (!NIL_P(opt)) argc--;
02845 }
02846
02847 rb_scan_args(argc, argv, "12", &io, &level, &strategy);
02848 Data_Get_Struct(obj, struct gzfile, gz);
02849
02850
02851 gz->level = ARG_LEVEL(level);
02852 err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
02853 -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
02854 if (err != Z_OK) {
02855 raise_zlib_error(err, gz->z.stream.msg);
02856 }
02857 gz->io = io;
02858 ZSTREAM_READY(&gz->z);
02859 rb_gzfile_ecopts(gz, opt);
02860
02861 if (rb_respond_to(io, id_path)) {
02862 gz->path = rb_funcall(gz->io, id_path, 0);
02863 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
02864 }
02865
02866 return obj;
02867 }
02868
02869
02870
02871
02872
02873
02874
02875
02876 static VALUE
02877 rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
02878 {
02879 struct gzfile *gz = get_gzfile(obj);
02880 VALUE v_flush;
02881 int flush;
02882
02883 rb_scan_args(argc, argv, "01", &v_flush);
02884
02885 flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
02886 if (flush != Z_NO_FLUSH) {
02887 zstream_run(&gz->z, (Bytef*)"", 0, flush);
02888 }
02889
02890 gzfile_write_raw(gz);
02891 if (rb_respond_to(gz->io, id_flush)) {
02892 rb_funcall(gz->io, id_flush, 0);
02893 }
02894 return obj;
02895 }
02896
02897
02898
02899
02900 static VALUE
02901 rb_gzwriter_write(VALUE obj, VALUE str)
02902 {
02903 struct gzfile *gz = get_gzfile(obj);
02904
02905 if (TYPE(str) != T_STRING)
02906 str = rb_obj_as_string(str);
02907 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
02908 str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
02909 }
02910 gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
02911 return INT2FIX(RSTRING_LEN(str));
02912 }
02913
02914
02915
02916
02917 static VALUE
02918 rb_gzwriter_putc(VALUE obj, VALUE ch)
02919 {
02920 struct gzfile *gz = get_gzfile(obj);
02921 char c = NUM2CHR(ch);
02922
02923 gzfile_write(gz, (Bytef*)&c, 1);
02924 return ch;
02925 }
02926
02927
02928
02929
02930
02931
02932
02933 #define rb_gzwriter_addstr rb_io_addstr
02934
02935
02936
02937
02938 #define rb_gzwriter_printf rb_io_printf
02939
02940
02941
02942
02943 #define rb_gzwriter_print rb_io_print
02944
02945
02946
02947
02948 #define rb_gzwriter_puts rb_io_puts
02949
02950
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 static VALUE
03009 rb_gzreader_s_allocate(VALUE klass)
03010 {
03011 return gzfile_reader_new(klass);
03012 }
03013
03014
03015
03016
03017
03018
03019
03020
03021 static VALUE
03022 rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
03023 {
03024 return gzfile_s_open(argc, argv, klass, "rb");
03025 }
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 static VALUE
03038 rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
03039 {
03040 VALUE io, opt = Qnil;
03041 struct gzfile *gz;
03042 int err;
03043
03044 Data_Get_Struct(obj, struct gzfile, gz);
03045 if (argc > 1) {
03046 opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
03047 if (!NIL_P(opt)) argc--;
03048 }
03049 rb_scan_args(argc, argv, "1", &io);
03050
03051
03052 err = inflateInit2(&gz->z.stream, -MAX_WBITS);
03053 if (err != Z_OK) {
03054 raise_zlib_error(err, gz->z.stream.msg);
03055 }
03056 gz->io = io;
03057 ZSTREAM_READY(&gz->z);
03058 gzfile_read_header(gz);
03059 rb_gzfile_ecopts(gz, opt);
03060
03061 if (rb_respond_to(io, id_path)) {
03062 gz->path = rb_funcall(gz->io, id_path, 0);
03063 rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
03064 }
03065
03066 return obj;
03067 }
03068
03069
03070
03071
03072
03073 static VALUE
03074 rb_gzreader_rewind(VALUE obj)
03075 {
03076 struct gzfile *gz = get_gzfile(obj);
03077 gzfile_reader_rewind(gz);
03078 return INT2FIX(0);
03079 }
03080
03081
03082
03083
03084
03085 static VALUE
03086 rb_gzreader_unused(VALUE obj)
03087 {
03088 struct gzfile *gz;
03089 Data_Get_Struct(obj, struct gzfile, gz);
03090 return gzfile_reader_get_unused(gz);
03091 }
03092
03093
03094
03095
03096 static VALUE
03097 rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
03098 {
03099 struct gzfile *gz = get_gzfile(obj);
03100 VALUE vlen;
03101 int len;
03102
03103 rb_scan_args(argc, argv, "01", &vlen);
03104 if (NIL_P(vlen)) {
03105 return gzfile_read_all(gz);
03106 }
03107
03108 len = NUM2INT(vlen);
03109 if (len < 0) {
03110 rb_raise(rb_eArgError, "negative length %d given", len);
03111 }
03112 return gzfile_read(gz, len);
03113 }
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125 static VALUE
03126 rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
03127 {
03128 struct gzfile *gz = get_gzfile(obj);
03129 VALUE vlen, outbuf;
03130 int len;
03131
03132 rb_scan_args(argc, argv, "11", &vlen, &outbuf);
03133
03134 len = NUM2INT(vlen);
03135 if (len < 0) {
03136 rb_raise(rb_eArgError, "negative length %d given", len);
03137 }
03138 if (!NIL_P(outbuf))
03139 Check_Type(outbuf, T_STRING);
03140 return gzfile_readpartial(gz, len, outbuf);
03141 }
03142
03143
03144
03145
03146 static VALUE
03147 rb_gzreader_getc(VALUE obj)
03148 {
03149 struct gzfile *gz = get_gzfile(obj);
03150
03151 return gzfile_getc(gz);
03152 }
03153
03154
03155
03156
03157 static VALUE
03158 rb_gzreader_readchar(VALUE obj)
03159 {
03160 VALUE dst;
03161 dst = rb_gzreader_getc(obj);
03162 if (NIL_P(dst)) {
03163 rb_raise(rb_eEOFError, "end of file reached");
03164 }
03165 return dst;
03166 }
03167
03168
03169
03170
03171 static VALUE
03172 rb_gzreader_getbyte(VALUE obj)
03173 {
03174 struct gzfile *gz = get_gzfile(obj);
03175 VALUE dst;
03176
03177 dst = gzfile_read(gz, 1);
03178 if (!NIL_P(dst)) {
03179 dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
03180 }
03181 return dst;
03182 }
03183
03184
03185
03186
03187 static VALUE
03188 rb_gzreader_readbyte(VALUE obj)
03189 {
03190 VALUE dst;
03191 dst = rb_gzreader_getbyte(obj);
03192 if (NIL_P(dst)) {
03193 rb_raise(rb_eEOFError, "end of file reached");
03194 }
03195 return dst;
03196 }
03197
03198
03199
03200
03201 static VALUE
03202 rb_gzreader_each_char(VALUE obj)
03203 {
03204 VALUE c;
03205
03206 RETURN_ENUMERATOR(obj, 0, 0);
03207
03208 while (!NIL_P(c = rb_gzreader_getc(obj))) {
03209 rb_yield(c);
03210 }
03211 return Qnil;
03212 }
03213
03214
03215
03216
03217 static VALUE
03218 rb_gzreader_each_byte(VALUE obj)
03219 {
03220 VALUE c;
03221
03222 RETURN_ENUMERATOR(obj, 0, 0);
03223
03224 while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
03225 rb_yield(c);
03226 }
03227 return Qnil;
03228 }
03229
03230
03231
03232
03233 static VALUE
03234 rb_gzreader_ungetc(VALUE obj, VALUE s)
03235 {
03236 struct gzfile *gz;
03237
03238 if (FIXNUM_P(s))
03239 return rb_gzreader_ungetbyte(obj, s);
03240 gz = get_gzfile(obj);
03241 StringValue(s);
03242 if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
03243 s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
03244 }
03245 gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
03246 return Qnil;
03247 }
03248
03249
03250
03251
03252 static VALUE
03253 rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
03254 {
03255 struct gzfile *gz = get_gzfile(obj);
03256 gzfile_ungetbyte(gz, NUM2CHR(ch));
03257 return Qnil;
03258 }
03259
03260 static void
03261 gzreader_skip_linebreaks(struct gzfile *gz)
03262 {
03263 VALUE str;
03264 char *p;
03265 int n;
03266
03267 while (gz->z.buf_filled == 0) {
03268 if (GZFILE_IS_FINISHED(gz)) return;
03269 gzfile_read_more(gz);
03270 }
03271 n = 0;
03272 p = RSTRING_PTR(gz->z.buf);
03273
03274 while (n++, *(p++) == '\n') {
03275 if (n >= gz->z.buf_filled) {
03276 str = zstream_detach_buffer(&gz->z);
03277 gzfile_calc_crc(gz, str);
03278 while (gz->z.buf_filled == 0) {
03279 if (GZFILE_IS_FINISHED(gz)) return;
03280 gzfile_read_more(gz);
03281 }
03282 n = 0;
03283 p = RSTRING_PTR(gz->z.buf);
03284 }
03285 }
03286
03287 str = zstream_shift_buffer(&gz->z, n - 1);
03288 gzfile_calc_crc(gz, str);
03289 }
03290
03291 static void
03292 rscheck(const char *rsptr, long rslen, VALUE rs)
03293 {
03294 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
03295 rb_raise(rb_eRuntimeError, "rs modified");
03296 }
03297
03298 static VALUE
03299 gzreader_gets(int argc, VALUE *argv, VALUE obj)
03300 {
03301 struct gzfile *gz = get_gzfile(obj);
03302 volatile VALUE rs;
03303 VALUE dst;
03304 const char *rsptr;
03305 char *p, *res;
03306 long rslen, n;
03307 int rspara;
03308
03309 if (argc == 0) {
03310 rs = rb_rs;
03311 }
03312 else {
03313 rb_scan_args(argc, argv, "1", &rs);
03314 if (!NIL_P(rs)) {
03315 Check_Type(rs, T_STRING);
03316 }
03317 }
03318
03319 if (NIL_P(rs)) {
03320 dst = gzfile_read_all(gz);
03321 if (RSTRING_LEN(dst) != 0) gz->lineno++;
03322 else
03323 return Qnil;
03324 return dst;
03325 }
03326
03327 if (RSTRING_LEN(rs) == 0) {
03328 rsptr = "\n\n";
03329 rslen = 2;
03330 rspara = 1;
03331 } else {
03332 rsptr = RSTRING_PTR(rs);
03333 rslen = RSTRING_LEN(rs);
03334 rspara = 0;
03335 }
03336
03337 if (rspara) {
03338 gzreader_skip_linebreaks(gz);
03339 }
03340
03341 while (gz->z.buf_filled < rslen) {
03342 if (ZSTREAM_IS_FINISHED(&gz->z)) {
03343 if (gz->z.buf_filled > 0) gz->lineno++;
03344 return gzfile_read(gz, rslen);
03345 }
03346 gzfile_read_more(gz);
03347 }
03348
03349 p = RSTRING_PTR(gz->z.buf);
03350 n = rslen;
03351 for (;;) {
03352 if (n > gz->z.buf_filled) {
03353 if (ZSTREAM_IS_FINISHED(&gz->z)) break;
03354 gzfile_read_more(gz);
03355 p = RSTRING_PTR(gz->z.buf) + n - rslen;
03356 }
03357 if (!rspara) rscheck(rsptr, rslen, rs);
03358 res = memchr(p, rsptr[0], (gz->z.buf_filled - n + 1));
03359 if (!res) {
03360 n = gz->z.buf_filled + 1;
03361 } else {
03362 n += (long)(res - p);
03363 p = res;
03364 if (rslen == 1 || memcmp(p, rsptr, rslen) == 0) break;
03365 p++, n++;
03366 }
03367 }
03368
03369 gz->lineno++;
03370 dst = gzfile_read(gz, n);
03371 if (rspara) {
03372 gzreader_skip_linebreaks(gz);
03373 }
03374
03375 return gzfile_newstr(gz, dst);
03376 }
03377
03378
03379
03380
03381 static VALUE
03382 rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
03383 {
03384 VALUE dst;
03385 dst = gzreader_gets(argc, argv, obj);
03386 if (!NIL_P(dst)) {
03387 rb_lastline_set(dst);
03388 }
03389 return dst;
03390 }
03391
03392
03393
03394
03395 static VALUE
03396 rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
03397 {
03398 VALUE dst;
03399 dst = rb_gzreader_gets(argc, argv, obj);
03400 if (NIL_P(dst)) {
03401 rb_raise(rb_eEOFError, "end of file reached");
03402 }
03403 return dst;
03404 }
03405
03406
03407
03408
03409 static VALUE
03410 rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
03411 {
03412 VALUE str;
03413
03414 RETURN_ENUMERATOR(obj, 0, 0);
03415
03416 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
03417 rb_yield(str);
03418 }
03419 return obj;
03420 }
03421
03422
03423
03424
03425 static VALUE
03426 rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
03427 {
03428 VALUE str, dst;
03429 dst = rb_ary_new();
03430 while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
03431 rb_ary_push(dst, str);
03432 }
03433 return dst;
03434 }
03435
03436 #endif
03437
03438
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 void
03520 Init_zlib()
03521 {
03522 VALUE mZlib, cZStream, cDeflate, cInflate;
03523 #if GZIP_SUPPORT
03524 VALUE cGzipFile, cGzipWriter, cGzipReader;
03525 #endif
03526
03527 mZlib = rb_define_module("Zlib");
03528
03529 cZError = rb_define_class_under(mZlib, "Error", rb_eStandardError);
03530 cStreamEnd = rb_define_class_under(mZlib, "StreamEnd", cZError);
03531 cNeedDict = rb_define_class_under(mZlib, "NeedDict", cZError);
03532 cDataError = rb_define_class_under(mZlib, "DataError", cZError);
03533 cStreamError = rb_define_class_under(mZlib, "StreamError", cZError);
03534 cMemError = rb_define_class_under(mZlib, "MemError", cZError);
03535 cBufError = rb_define_class_under(mZlib, "BufError", cZError);
03536 cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
03537
03538 rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
03539 rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
03540 rb_define_module_function(mZlib, "adler32_combine", rb_zlib_adler32_combine, 3);
03541 rb_define_module_function(mZlib, "crc32", rb_zlib_crc32, -1);
03542 rb_define_module_function(mZlib, "crc32_combine", rb_zlib_crc32_combine, 3);
03543 rb_define_module_function(mZlib, "crc_table", rb_zlib_crc_table, 0);
03544
03545 rb_define_const(mZlib, "VERSION", rb_str_new2(RUBY_ZLIB_VERSION));
03546 rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
03547
03548 cZStream = rb_define_class_under(mZlib, "ZStream", rb_cObject);
03549 rb_undef_alloc_func(cZStream);
03550 rb_define_method(cZStream, "avail_out", rb_zstream_avail_out, 0);
03551 rb_define_method(cZStream, "avail_out=", rb_zstream_set_avail_out, 1);
03552 rb_define_method(cZStream, "avail_in", rb_zstream_avail_in, 0);
03553 rb_define_method(cZStream, "total_in", rb_zstream_total_in, 0);
03554 rb_define_method(cZStream, "total_out", rb_zstream_total_out, 0);
03555 rb_define_method(cZStream, "data_type", rb_zstream_data_type, 0);
03556 rb_define_method(cZStream, "adler", rb_zstream_adler, 0);
03557 rb_define_method(cZStream, "finished?", rb_zstream_finished_p, 0);
03558 rb_define_method(cZStream, "stream_end?", rb_zstream_finished_p, 0);
03559 rb_define_method(cZStream, "closed?", rb_zstream_closed_p, 0);
03560 rb_define_method(cZStream, "ended?", rb_zstream_closed_p, 0);
03561 rb_define_method(cZStream, "close", rb_zstream_end, 0);
03562 rb_define_method(cZStream, "end", rb_zstream_end, 0);
03563 rb_define_method(cZStream, "reset", rb_zstream_reset, 0);
03564 rb_define_method(cZStream, "finish", rb_zstream_finish, 0);
03565 rb_define_method(cZStream, "flush_next_in", rb_zstream_flush_next_in, 0);
03566 rb_define_method(cZStream, "flush_next_out", rb_zstream_flush_next_out, 0);
03567
03568 rb_define_const(mZlib, "BINARY", INT2FIX(Z_BINARY));
03569 rb_define_const(mZlib, "ASCII", INT2FIX(Z_ASCII));
03570 rb_define_const(mZlib, "UNKNOWN", INT2FIX(Z_UNKNOWN));
03571
03572 cDeflate = rb_define_class_under(mZlib, "Deflate", cZStream);
03573 rb_define_singleton_method(cDeflate, "deflate", rb_deflate_s_deflate, -1);
03574 rb_define_alloc_func(cDeflate, rb_deflate_s_allocate);
03575 rb_define_method(cDeflate, "initialize", rb_deflate_initialize, -1);
03576 rb_define_method(cDeflate, "initialize_copy", rb_deflate_init_copy, 1);
03577 rb_define_method(cDeflate, "deflate", rb_deflate_deflate, -1);
03578 rb_define_method(cDeflate, "<<", rb_deflate_addstr, 1);
03579 rb_define_method(cDeflate, "flush", rb_deflate_flush, -1);
03580 rb_define_method(cDeflate, "params", rb_deflate_params, 2);
03581 rb_define_method(cDeflate, "set_dictionary", rb_deflate_set_dictionary, 1);
03582
03583 cInflate = rb_define_class_under(mZlib, "Inflate", cZStream);
03584 rb_define_singleton_method(cInflate, "inflate", rb_inflate_s_inflate, 1);
03585 rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
03586 rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
03587 rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
03588 rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
03589 rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
03590 rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
03591 rb_define_method(cInflate, "set_dictionary", rb_inflate_set_dictionary, 1);
03592
03593 rb_define_const(mZlib, "NO_COMPRESSION", INT2FIX(Z_NO_COMPRESSION));
03594 rb_define_const(mZlib, "BEST_SPEED", INT2FIX(Z_BEST_SPEED));
03595 rb_define_const(mZlib, "BEST_COMPRESSION", INT2FIX(Z_BEST_COMPRESSION));
03596 rb_define_const(mZlib, "DEFAULT_COMPRESSION",
03597 INT2FIX(Z_DEFAULT_COMPRESSION));
03598
03599 rb_define_const(mZlib, "FILTERED", INT2FIX(Z_FILTERED));
03600 rb_define_const(mZlib, "HUFFMAN_ONLY", INT2FIX(Z_HUFFMAN_ONLY));
03601 rb_define_const(mZlib, "DEFAULT_STRATEGY", INT2FIX(Z_DEFAULT_STRATEGY));
03602
03603 rb_define_const(mZlib, "MAX_WBITS", INT2FIX(MAX_WBITS));
03604 rb_define_const(mZlib, "DEF_MEM_LEVEL", INT2FIX(DEF_MEM_LEVEL));
03605 rb_define_const(mZlib, "MAX_MEM_LEVEL", INT2FIX(MAX_MEM_LEVEL));
03606
03607 rb_define_const(mZlib, "NO_FLUSH", INT2FIX(Z_NO_FLUSH));
03608 rb_define_const(mZlib, "SYNC_FLUSH", INT2FIX(Z_SYNC_FLUSH));
03609 rb_define_const(mZlib, "FULL_FLUSH", INT2FIX(Z_FULL_FLUSH));
03610 rb_define_const(mZlib, "FINISH", INT2FIX(Z_FINISH));
03611
03612 #if GZIP_SUPPORT
03613 id_write = rb_intern("write");
03614 id_read = rb_intern("read");
03615 id_readpartial = rb_intern("readpartial");
03616 id_flush = rb_intern("flush");
03617 id_seek = rb_intern("seek");
03618 id_close = rb_intern("close");
03619 id_path = rb_intern("path");
03620
03621 cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
03622 cGzError = rb_define_class_under(cGzipFile, "Error", cZError);
03623
03624 cNoFooter = rb_define_class_under(cGzipFile, "NoFooter", cGzError);
03625 cCRCError = rb_define_class_under(cGzipFile, "CRCError", cGzError);
03626 cLengthError = rb_define_class_under(cGzipFile,"LengthError",cGzError);
03627
03628 cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
03629 cGzipReader = rb_define_class_under(mZlib, "GzipReader", cGzipFile);
03630 rb_include_module(cGzipReader, rb_mEnumerable);
03631
03632 rb_define_singleton_method(cGzipFile, "wrap", rb_gzfile_s_wrap, -1);
03633 rb_undef_alloc_func(cGzipFile);
03634 rb_define_method(cGzipFile, "to_io", rb_gzfile_to_io, 0);
03635 rb_define_method(cGzipFile, "crc", rb_gzfile_crc, 0);
03636 rb_define_method(cGzipFile, "mtime", rb_gzfile_mtime, 0);
03637 rb_define_method(cGzipFile, "level", rb_gzfile_level, 0);
03638 rb_define_method(cGzipFile, "os_code", rb_gzfile_os_code, 0);
03639 rb_define_method(cGzipFile, "orig_name", rb_gzfile_orig_name, 0);
03640 rb_define_method(cGzipFile, "comment", rb_gzfile_comment, 0);
03641 rb_define_method(cGzipReader, "lineno", rb_gzfile_lineno, 0);
03642 rb_define_method(cGzipReader, "lineno=", rb_gzfile_set_lineno, 1);
03643 rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
03644 rb_define_method(cGzipWriter, "orig_name=", rb_gzfile_set_orig_name,1);
03645 rb_define_method(cGzipWriter, "comment=", rb_gzfile_set_comment, 1);
03646 rb_define_method(cGzipFile, "close", rb_gzfile_close, 0);
03647 rb_define_method(cGzipFile, "finish", rb_gzfile_finish, 0);
03648 rb_define_method(cGzipFile, "closed?", rb_gzfile_closed_p, 0);
03649 rb_define_method(cGzipReader, "eof", rb_gzfile_eof_p, 0);
03650 rb_define_method(cGzipReader, "eof?", rb_gzfile_eof_p, 0);
03651 rb_define_method(cGzipFile, "sync", rb_gzfile_sync, 0);
03652 rb_define_method(cGzipFile, "sync=", rb_gzfile_set_sync, 1);
03653 rb_define_method(cGzipReader, "pos", rb_gzfile_total_out, 0);
03654 rb_define_method(cGzipWriter, "pos", rb_gzfile_total_in, 0);
03655 rb_define_method(cGzipReader, "tell", rb_gzfile_total_out, 0);
03656 rb_define_method(cGzipWriter, "tell", rb_gzfile_total_in, 0);
03657
03658 rb_define_singleton_method(cGzipWriter, "open", rb_gzwriter_s_open,-1);
03659 rb_define_alloc_func(cGzipWriter, rb_gzwriter_s_allocate);
03660 rb_define_method(cGzipWriter, "initialize", rb_gzwriter_initialize,-1);
03661 rb_define_method(cGzipWriter, "flush", rb_gzwriter_flush, -1);
03662 rb_define_method(cGzipWriter, "write", rb_gzwriter_write, 1);
03663 rb_define_method(cGzipWriter, "putc", rb_gzwriter_putc, 1);
03664 rb_define_method(cGzipWriter, "<<", rb_gzwriter_addstr, 1);
03665 rb_define_method(cGzipWriter, "printf", rb_gzwriter_printf, -1);
03666 rb_define_method(cGzipWriter, "print", rb_gzwriter_print, -1);
03667 rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
03668
03669 rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
03670 rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
03671 rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
03672 rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
03673 rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
03674 rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
03675 rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
03676 rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
03677 rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
03678 rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
03679 rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
03680 rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
03681 rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
03682 rb_define_method(cGzipReader, "bytes", rb_gzreader_each_byte, 0);
03683 rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
03684 rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
03685 rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
03686 rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
03687 rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
03688 rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
03689 rb_define_method(cGzipReader, "lines", rb_gzreader_each, -1);
03690 rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
03691
03692 rb_define_const(mZlib, "OS_CODE", INT2FIX(OS_CODE));
03693 rb_define_const(mZlib, "OS_MSDOS", INT2FIX(OS_MSDOS));
03694 rb_define_const(mZlib, "OS_AMIGA", INT2FIX(OS_AMIGA));
03695 rb_define_const(mZlib, "OS_VMS", INT2FIX(OS_VMS));
03696 rb_define_const(mZlib, "OS_UNIX", INT2FIX(OS_UNIX));
03697 rb_define_const(mZlib, "OS_ATARI", INT2FIX(OS_ATARI));
03698 rb_define_const(mZlib, "OS_OS2", INT2FIX(OS_OS2));
03699 rb_define_const(mZlib, "OS_MACOS", INT2FIX(OS_MACOS));
03700 rb_define_const(mZlib, "OS_TOPS20", INT2FIX(OS_TOPS20));
03701 rb_define_const(mZlib, "OS_WIN32", INT2FIX(OS_WIN32));
03702
03703 rb_define_const(mZlib, "OS_VMCMS", INT2FIX(OS_VMCMS));
03704 rb_define_const(mZlib, "OS_ZSYSTEM", INT2FIX(OS_ZSYSTEM));
03705 rb_define_const(mZlib, "OS_CPM", INT2FIX(OS_CPM));
03706 rb_define_const(mZlib, "OS_QDOS", INT2FIX(OS_QDOS));
03707 rb_define_const(mZlib, "OS_RISCOS", INT2FIX(OS_RISCOS));
03708 rb_define_const(mZlib, "OS_UNKNOWN", INT2FIX(OS_UNKNOWN));
03709
03710 #endif
03711 }
03712
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