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