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