1 28 package org.jruby; 29 30 import java.io.InputStream ; 31 import java.io.IOException ; 32 33 import java.util.List ; 34 import java.util.ArrayList ; 35 36 import java.util.zip.GZIPInputStream ; 37 import java.util.zip.GZIPOutputStream ; 38 39 import org.jruby.exceptions.RaiseException; 40 41 import org.jruby.runtime.Block; 42 import org.jruby.runtime.CallbackFactory; 43 import org.jruby.runtime.ObjectAllocator; 44 import org.jruby.runtime.ThreadContext; 45 import org.jruby.runtime.builtin.IRubyObject; 46 47 import org.jruby.util.IOInputStream; 48 import org.jruby.util.IOOutputStream; 49 import org.jruby.util.CRC32Ext; 50 import org.jruby.util.Adler32Ext; 51 import org.jruby.util.ZlibInflate; 52 import org.jruby.util.ZlibDeflate; 53 54 import org.jruby.util.ByteList; 55 56 public class RubyZlib { 57 60 public static RubyModule createZlibModule(Ruby runtime) { 61 RubyModule result = runtime.defineModule("Zlib"); 62 63 RubyClass gzfile = result.defineClassUnder("GzipFile", runtime.getObject(), RubyGzipFile.GZIPFILE_ALLOCATOR); 64 CallbackFactory callbackFactory = runtime.callbackFactory(RubyGzipFile.class); 65 gzfile.getMetaClass().defineMethod("wrap", callbackFactory.getSingletonMethod("wrap", RubyGzipFile.class, RubyKernel.IRUBY_OBJECT)); 66 gzfile.getMetaClass().defineMethod("new", callbackFactory.getSingletonMethod("newInstance")); 67 gzfile.defineFastMethod("os_code", callbackFactory.getFastMethod("os_code")); 68 gzfile.defineFastMethod("closed?", callbackFactory.getFastMethod("closed_p")); 69 gzfile.defineFastMethod("orig_name", callbackFactory.getFastMethod("orig_name")); 70 gzfile.defineFastMethod("to_io", callbackFactory.getFastMethod("to_io")); 71 gzfile.defineFastMethod("finish", callbackFactory.getFastMethod("finish")); 72 gzfile.defineFastMethod("comment", callbackFactory.getFastMethod("comment")); 73 gzfile.defineFastMethod("crc", callbackFactory.getFastMethod("crc")); 74 gzfile.defineFastMethod("mtime", callbackFactory.getFastMethod("mtime")); 75 gzfile.defineFastMethod("sync", callbackFactory.getFastMethod("sync")); 76 gzfile.defineFastMethod("close", callbackFactory.getFastMethod("close")); 77 gzfile.defineFastMethod("level", callbackFactory.getFastMethod("level")); 78 gzfile.defineFastMethod("sync=", callbackFactory.getFastMethod("set_sync", RubyKernel.IRUBY_OBJECT)); 79 80 CallbackFactory classCB = runtime.callbackFactory(RubyClass.class); 81 RubyClass gzreader = result.defineClassUnder("GzipReader", gzfile, RubyGzipReader.GZIPREADER_ALLOCATOR); 82 gzreader.includeModule(runtime.getModule("Enumerable")); 83 CallbackFactory callbackFactory2 = runtime.callbackFactory(RubyGzipReader.class); 84 gzreader.getMetaClass().defineMethod("open", callbackFactory2.getSingletonMethod("open", RubyString.class)); 85 gzreader.getMetaClass().defineMethod("new", classCB.getOptMethod("newInstance")); 86 gzreader.defineMethod("initialize", callbackFactory2.getMethod("initialize", RubyKernel.IRUBY_OBJECT)); 87 gzreader.defineFastMethod("rewind", callbackFactory2.getFastMethod("rewind")); 88 gzreader.defineFastMethod("lineno", callbackFactory2.getFastMethod("lineno")); 89 gzreader.defineFastMethod("readline", callbackFactory2.getFastMethod("readline")); 90 gzreader.defineFastMethod("read", callbackFactory2.getFastOptMethod("read")); 91 gzreader.defineFastMethod("lineno=", callbackFactory2.getFastMethod("set_lineno", RubyNumeric.class)); 92 gzreader.defineFastMethod("pos", callbackFactory2.getFastMethod("pos")); 93 gzreader.defineFastMethod("readchar", callbackFactory2.getFastMethod("readchar")); 94 gzreader.defineFastMethod("readlines", callbackFactory2.getFastOptMethod("readlines")); 95 gzreader.defineMethod("each_byte", callbackFactory2.getMethod("each_byte")); 96 gzreader.defineFastMethod("getc", callbackFactory2.getFastMethod("getc")); 97 gzreader.defineFastMethod("eof", callbackFactory2.getFastMethod("eof")); 98 gzreader.defineFastMethod("ungetc", callbackFactory2.getFastMethod("ungetc", RubyNumeric.class)); 99 gzreader.defineMethod("each", callbackFactory2.getOptMethod("each")); 100 gzreader.defineFastMethod("unused", callbackFactory2.getFastMethod("unused")); 101 gzreader.defineFastMethod("eof?", callbackFactory2.getFastMethod("eof_p")); 102 gzreader.defineFastMethod("gets", callbackFactory2.getFastOptMethod("gets")); 103 gzreader.defineFastMethod("tell", callbackFactory2.getFastMethod("tell")); 104 105 RubyClass standardError = runtime.getClass("StandardError"); 106 RubyClass zlibError = result.defineClassUnder("Error", standardError, standardError.getAllocator()); 107 gzreader.defineClassUnder("Error", zlibError, zlibError.getAllocator()); 108 109 RubyClass gzwriter = result.defineClassUnder("GzipWriter", gzfile, RubyGzipWriter.GZIPWRITER_ALLOCATOR); 110 CallbackFactory callbackFactory3 = runtime.callbackFactory(RubyGzipWriter.class); 111 gzwriter.getMetaClass().defineMethod("open", callbackFactory3.getOptSingletonMethod("open")); 112 gzwriter.getMetaClass().defineMethod("new", classCB.getOptMethod("newInstance")); 113 gzwriter.defineMethod("initialize", callbackFactory3.getOptMethod("initialize2")); 114 gzwriter.defineFastMethod("<<", callbackFactory3.getFastMethod("append", RubyKernel.IRUBY_OBJECT)); 115 gzwriter.defineFastMethod("printf", callbackFactory3.getFastOptMethod("printf")); 116 gzwriter.defineFastMethod("pos", callbackFactory3.getFastMethod("pos")); 117 gzwriter.defineFastMethod("orig_name=", callbackFactory3.getFastMethod("set_orig_name", RubyString.class)); 118 gzwriter.defineFastMethod("putc", callbackFactory3.getFastMethod("putc", RubyNumeric.class)); 119 gzwriter.defineFastMethod("comment=", callbackFactory3.getFastMethod("set_comment", RubyString.class)); 120 gzwriter.defineFastMethod("puts", callbackFactory3.getFastOptMethod("puts")); 121 gzwriter.defineFastMethod("flush", callbackFactory3.getFastOptMethod("flush")); 122 gzwriter.defineFastMethod("mtime=", callbackFactory3.getFastMethod("set_mtime", RubyKernel.IRUBY_OBJECT)); 123 gzwriter.defineFastMethod("tell", callbackFactory3.getFastMethod("tell")); 124 gzwriter.defineFastMethod("write", callbackFactory3.getFastMethod("write", RubyKernel.IRUBY_OBJECT)); 125 126 result.defineConstant("ZLIB_VERSION",runtime.newString("1.2.1")); 127 result.defineConstant("VERSION",runtime.newString("0.6.0")); 128 129 result.defineConstant("BINARY",runtime.newFixnum(0)); 130 result.defineConstant("ASCII",runtime.newFixnum(1)); 131 result.defineConstant("UNKNOWN",runtime.newFixnum(2)); 132 133 result.defineConstant("DEF_MEM_LEVEL",runtime.newFixnum(8)); 134 result.defineConstant("MAX_MEM_LEVEL",runtime.newFixnum(9)); 135 136 result.defineConstant("OS_UNIX",runtime.newFixnum(3)); 137 result.defineConstant("OS_UNKNOWN",runtime.newFixnum(255)); 138 result.defineConstant("OS_CODE",runtime.newFixnum(11)); 139 result.defineConstant("OS_ZSYSTEM",runtime.newFixnum(8)); 140 result.defineConstant("OS_VMCMS",runtime.newFixnum(4)); 141 result.defineConstant("OS_VMS",runtime.newFixnum(2)); 142 result.defineConstant("OS_RISCOS",runtime.newFixnum(13)); 143 result.defineConstant("OS_MACOS",runtime.newFixnum(7)); 144 result.defineConstant("OS_OS2",runtime.newFixnum(6)); 145 result.defineConstant("OS_AMIGA",runtime.newFixnum(1)); 146 result.defineConstant("OS_QDOS",runtime.newFixnum(12)); 147 result.defineConstant("OS_WIN32",runtime.newFixnum(11)); 148 result.defineConstant("OS_ATARI",runtime.newFixnum(5)); 149 result.defineConstant("OS_MSDOS",runtime.newFixnum(0)); 150 result.defineConstant("OS_CPM",runtime.newFixnum(9)); 151 result.defineConstant("OS_TOPS20",runtime.newFixnum(10)); 152 153 result.defineConstant("DEFAULT_STRATEGY",runtime.newFixnum(0)); 154 result.defineConstant("FILTERED",runtime.newFixnum(1)); 155 result.defineConstant("HUFFMAN_ONLY",runtime.newFixnum(2)); 156 157 result.defineConstant("NO_FLUSH",runtime.newFixnum(0)); 158 result.defineConstant("SYNC_FLUSH",runtime.newFixnum(2)); 159 result.defineConstant("FULL_FLUSH",runtime.newFixnum(3)); 160 result.defineConstant("FINISH",runtime.newFixnum(4)); 161 162 result.defineConstant("NO_COMPRESSION",runtime.newFixnum(0)); 163 result.defineConstant("BEST_SPEED",runtime.newFixnum(1)); 164 result.defineConstant("DEFAULT_COMPRESSION",runtime.newFixnum(-1)); 165 result.defineConstant("BEST_COMPRESSION",runtime.newFixnum(9)); 166 167 result.defineConstant("MAX_WBITS",runtime.newFixnum(15)); 168 169 CallbackFactory cf = runtime.callbackFactory(RubyZlib.class); 170 result.defineFastModuleFunction("zlib_version",cf.getFastSingletonMethod("zlib_version")); 171 result.defineFastModuleFunction("version",cf.getFastSingletonMethod("version")); 172 result.defineFastModuleFunction("adler32",cf.getFastOptSingletonMethod("adler32")); 173 result.defineFastModuleFunction("crc32",cf.getFastOptSingletonMethod("crc32")); 174 result.defineFastModuleFunction("crc_table",cf.getFastSingletonMethod("crc_table")); 175 176 result.defineClassUnder("StreamEnd",zlibError, zlibError.getAllocator()); 177 result.defineClassUnder("StreamError",zlibError, zlibError.getAllocator()); 178 result.defineClassUnder("BufError",zlibError, zlibError.getAllocator()); 179 result.defineClassUnder("NeedDict",zlibError, zlibError.getAllocator()); 180 result.defineClassUnder("MemError",zlibError, zlibError.getAllocator()); 181 result.defineClassUnder("VersionError",zlibError, zlibError.getAllocator()); 182 result.defineClassUnder("DataError",zlibError, zlibError.getAllocator()); 183 184 RubyClass gzError = gzfile.defineClassUnder("Error",zlibError, zlibError.getAllocator()); 185 gzfile.defineClassUnder("CRCError",gzError, gzError.getAllocator()); 186 gzfile.defineClassUnder("NoFooter",gzError, gzError.getAllocator()); 187 gzfile.defineClassUnder("LengthError",gzError, gzError.getAllocator()); 188 189 RubyClass zstream = result.defineClassUnder("ZStream", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 191 CallbackFactory zstreamcb = runtime.callbackFactory(ZStream.class); 192 zstream.defineMethod("initialize",zstreamcb.getMethod("initialize")); 193 zstream.defineFastMethod("flush_next_out",zstreamcb.getFastMethod("flush_next_out")); 194 zstream.defineFastMethod("total_out",zstreamcb.getFastMethod("total_out")); 195 zstream.defineFastMethod("stream_end?",zstreamcb.getFastMethod("stream_end_p")); 196 zstream.defineFastMethod("data_type",zstreamcb.getFastMethod("data_type")); 197 zstream.defineFastMethod("closed?",zstreamcb.getFastMethod("closed_p")); 198 zstream.defineFastMethod("ended?",zstreamcb.getFastMethod("ended_p")); 199 zstream.defineFastMethod("end",zstreamcb.getFastMethod("end")); 200 zstream.defineFastMethod("reset",zstreamcb.getFastMethod("reset")); 201 zstream.defineFastMethod("avail_out",zstreamcb.getFastMethod("avail_out")); 202 zstream.defineFastMethod("avail_out=",zstreamcb.getFastMethod("set_avail_out",RubyKernel.IRUBY_OBJECT)); 203 zstream.defineFastMethod("adler",zstreamcb.getFastMethod("adler")); 204 zstream.defineFastMethod("finish",zstreamcb.getFastMethod("finish")); 205 zstream.defineFastMethod("avail_in",zstreamcb.getFastMethod("avail_in")); 206 zstream.defineFastMethod("flush_next_in",zstreamcb.getFastMethod("flush_next_in")); 207 zstream.defineFastMethod("total_in",zstreamcb.getFastMethod("total_in")); 208 zstream.defineFastMethod("finished?",zstreamcb.getFastMethod("finished_p")); 209 zstream.defineFastMethod("close",zstreamcb.getFastMethod("close")); 210 zstream.undefineMethod("new"); 211 212 RubyClass infl = result.defineClassUnder("Inflate", zstream, Inflate.INFLATE_ALLOCATOR); 213 CallbackFactory inflcb = runtime.callbackFactory(Inflate.class); 214 infl.getMetaClass().defineFastMethod("inflate",inflcb.getFastSingletonMethod("s_inflate",RubyKernel.IRUBY_OBJECT)); 215 infl.defineFastMethod("initialize",inflcb.getFastOptMethod("_initialize")); 216 infl.defineFastMethod("<<",inflcb.getFastMethod("append",RubyKernel.IRUBY_OBJECT)); 217 infl.defineFastMethod("sync_point?",inflcb.getFastMethod("sync_point_p")); 218 infl.defineFastMethod("set_dictionary",inflcb.getFastMethod("set_dictionary",RubyKernel.IRUBY_OBJECT)); 219 infl.defineFastMethod("inflate",inflcb.getFastMethod("inflate",RubyKernel.IRUBY_OBJECT)); 220 infl.defineFastMethod("sync",inflcb.getFastMethod("sync",RubyKernel.IRUBY_OBJECT)); 221 222 RubyClass defl = result.defineClassUnder("Deflate", zstream, Deflate.DEFLATE_ALLOCATOR); 223 CallbackFactory deflcb = runtime.callbackFactory(Deflate.class); 224 defl.getMetaClass().defineFastMethod("deflate",deflcb.getFastOptSingletonMethod("s_deflate")); 225 defl.defineFastMethod("initialize",deflcb.getFastOptMethod("_initialize")); 226 defl.defineFastMethod("<<",deflcb.getFastMethod("append",RubyKernel.IRUBY_OBJECT)); 227 defl.defineFastMethod("params",deflcb.getFastMethod("params",RubyKernel.IRUBY_OBJECT,RubyKernel.IRUBY_OBJECT)); 228 defl.defineFastMethod("set_dictionary",deflcb.getFastMethod("set_dictionary",RubyKernel.IRUBY_OBJECT)); 229 defl.defineFastMethod("flush",deflcb.getFastOptMethod("flush")); 230 defl.defineFastMethod("deflate",deflcb.getFastOptMethod("deflate")); 231 232 runtime.getModule("Kernel").callMethod(runtime.getCurrentContext(),"require",runtime.newString("stringio")); 233 234 return result; 235 } 236 237 public static IRubyObject zlib_version(IRubyObject recv) { 238 return ((RubyModule)recv).getConstant("ZLIB_VERSION"); 239 } 240 241 public static IRubyObject version(IRubyObject recv) { 242 return ((RubyModule)recv).getConstant("VERSION"); 243 } 244 245 public static IRubyObject crc32(IRubyObject recv, IRubyObject[] args) throws Exception { 246 args = recv.scanArgs(args,0,2); 247 int crc = 0; 248 byte[] bytes = null; 249 if(!args[0].isNil()) { 250 bytes = args[0].convertToString().getBytes(); 251 } 252 if(!args[1].isNil()) { 253 crc = RubyNumeric.fix2int(args[1]); 254 } 255 CRC32Ext ext = new CRC32Ext(crc); 256 if(bytes != null) { 257 ext.update(bytes); 258 } 259 return recv.getRuntime().newFixnum(ext.getValue()); 260 } 261 262 public static IRubyObject adler32(IRubyObject recv, IRubyObject[] args) throws Exception { 263 args = recv.scanArgs(args,0,2); 264 int adler = 1; 265 byte[] bytes = null; 266 if(!args[0].isNil()) { 267 bytes = args[0].convertToString().getBytes(); 268 } 269 if(!args[1].isNil()) { 270 adler = RubyNumeric.fix2int(args[1]); 271 } 272 Adler32Ext ext = new Adler32Ext(adler); 273 if(bytes != null) { 274 ext.update(bytes); 275 } 276 return recv.getRuntime().newFixnum(ext.getValue()); 277 } 278 279 private final static long[] crctab = new long[]{ 280 0L, 1996959894L, 3993919788L, 2567524794L, 124634137L, 1886057615L, 3915621685L, 2657392035L, 249268274L, 2044508324L, 3772115230L, 2547177864L, 162941995L, 281 2125561021L, 3887607047L, 2428444049L, 498536548L, 1789927666L, 4089016648L, 2227061214L, 450548861L, 1843258603L, 4107580753L, 2211677639L, 325883990L, 282 1684777152L, 4251122042L, 2321926636L, 335633487L, 1661365465L, 4195302755L, 2366115317L, 997073096L, 1281953886L, 3579855332L, 2724688242L, 1006888145L, 283 1258607687L, 3524101629L, 2768942443L, 901097722L, 1119000684L, 3686517206L, 2898065728L, 853044451L, 1172266101L, 3705015759L, 2882616665L, 651767980L, 284 1373503546L, 3369554304L, 3218104598L, 565507253L, 1454621731L, 3485111705L, 3099436303L, 671266974L, 1594198024L, 3322730930L, 2970347812L, 795835527L, 285 1483230225L, 3244367275L, 3060149565L, 1994146192L, 31158534L, 2563907772L, 4023717930L, 1907459465L, 112637215L, 2680153253L, 3904427059L, 2013776290L, 286 251722036L, 2517215374L, 3775830040L, 2137656763L, 141376813L, 2439277719L, 3865271297L, 1802195444L, 476864866L, 2238001368L, 4066508878L, 1812370925L, 287 453092731L, 2181625025L, 4111451223L, 1706088902L, 314042704L, 2344532202L, 4240017532L, 1658658271L, 366619977L, 2362670323L, 4224994405L, 1303535960L, 288 984961486L, 2747007092L, 3569037538L, 1256170817L, 1037604311L, 2765210733L, 3554079995L, 1131014506L, 879679996L, 2909243462L, 3663771856L, 1141124467L, 289 855842277L, 2852801631L, 3708648649L, 1342533948L, 654459306L, 3188396048L, 3373015174L, 1466479909L, 544179635L, 3110523913L, 3462522015L, 1591671054L, 290 702138776L, 2966460450L, 3352799412L, 1504918807L, 783551873L, 3082640443L, 3233442989L, 3988292384L, 2596254646L, 62317068L, 1957810842L, 3939845945L, 291 2647816111L, 81470997L, 1943803523L, 3814918930L, 2489596804L, 225274430L, 2053790376L, 3826175755L, 2466906013L, 167816743L, 2097651377L, 4027552580L, 292 2265490386L, 503444072L, 1762050814L, 4150417245L, 2154129355L, 426522225L, 1852507879L, 4275313526L, 2312317920L, 282753626L, 1742555852L, 4189708143L, 293 2394877945L, 397917763L, 1622183637L, 3604390888L, 2714866558L, 953729732L, 1340076626L, 3518719985L, 2797360999L, 1068828381L, 1219638859L, 3624741850L, 294 2936675148L, 906185462L, 1090812512L, 3747672003L, 2825379669L, 829329135L, 1181335161L, 3412177804L, 3160834842L, 628085408L, 1382605366L, 3423369109L, 295 3138078467L, 570562233L, 1426400815L, 3317316542L, 2998733608L, 733239954L, 1555261956L, 3268935591L, 3050360625L, 752459403L, 1541320221L, 2607071920L, 296 3965973030L, 1969922972L, 40735498L, 2617837225L, 3943577151L, 1913087877L, 83908371L, 2512341634L, 3803740692L, 2075208622L, 213261112L, 2463272603L, 297 3855990285L, 2094854071L, 198958881L, 2262029012L, 4057260610L, 1759359992L, 534414190L, 2176718541L, 4139329115L, 1873836001L, 414664567L, 2282248934L, 298 4279200368L, 1711684554L, 285281116L, 2405801727L, 4167216745L, 1634467795L, 376229701L, 2685067896L, 3608007406L, 1308918612L, 956543938L, 2808555105L, 299 3495958263L, 1231636301L, 1047427035L, 2932959818L, 3654703836L, 1088359270L, 936918000L, 2847714899L, 3736837829L, 1202900863L, 817233897L, 3183342108L, 300 3401237130L, 1404277552L, 615818150L, 3134207493L, 3453421203L, 1423857449L, 601450431L, 3009837614L, 3294710456L, 1567103746L, 711928724L, 3020668471L, 301 3272380065L, 1510334235L, 755167117}; 302 303 public static IRubyObject crc_table(IRubyObject recv) { 304 List ll = new ArrayList (crctab.length); 305 for(int i=0;i<crctab.length;i++) { 306 ll.add(recv.getRuntime().newFixnum(crctab[i])); 307 } 308 return recv.getRuntime().newArray(ll); 309 } 310 311 312 public static abstract class ZStream extends RubyObject { 313 protected boolean closed = false; 314 protected boolean ended = false; 315 protected boolean finished = false; 316 317 protected abstract int internalTotalOut(); 318 protected abstract boolean internalStreamEndP(); 319 protected abstract void internalEnd(); 320 protected abstract void internalReset(); 321 protected abstract int internalAdler(); 322 protected abstract IRubyObject internalFinish() throws Exception ; 323 protected abstract int internalTotalIn(); 324 protected abstract void internalClose(); 325 326 public ZStream(Ruby runtime, RubyClass type) { 327 super(runtime, type); 328 } 329 330 public IRubyObject initialize(Block unusedBlock) { 331 return this; 332 } 333 334 public IRubyObject flush_next_out() { 335 return getRuntime().getNil(); 336 } 337 338 public IRubyObject total_out() { 339 return getRuntime().newFixnum(internalTotalOut()); 340 } 341 342 public IRubyObject stream_end_p() { 343 return internalStreamEndP() ? getRuntime().getTrue() : getRuntime().getFalse(); 344 } 345 346 public IRubyObject data_type() { 347 return getRuntime().getModule("Zlib").getConstant("UNKNOWN"); 348 } 349 350 public IRubyObject closed_p() { 351 return closed ? getRuntime().getTrue() : getRuntime().getFalse(); 352 } 353 354 public IRubyObject ended_p() { 355 return ended ? getRuntime().getTrue() : getRuntime().getFalse(); 356 } 357 358 public IRubyObject end() { 359 if(!ended) { 360 internalEnd(); 361 ended = true; 362 } 363 return getRuntime().getNil(); 364 } 365 366 public IRubyObject reset() { 367 internalReset(); 368 return getRuntime().getNil(); 369 } 370 371 public IRubyObject avail_out() { 372 return RubyFixnum.zero(getRuntime()); 373 } 374 375 public IRubyObject set_avail_out(IRubyObject p1) { 376 return p1; 377 } 378 379 public IRubyObject adler() { 380 return getRuntime().newFixnum(internalAdler()); 381 } 382 383 public IRubyObject finish() throws Exception { 384 if(!finished) { 385 finished = true; 386 return internalFinish(); 387 } 388 return getRuntime().newString(""); 389 } 390 391 public IRubyObject avail_in() { 392 return RubyFixnum.zero(getRuntime()); 393 } 394 395 public IRubyObject flush_next_in() { 396 return getRuntime().getNil(); 397 } 398 399 public IRubyObject total_in() { 400 return getRuntime().newFixnum(internalTotalIn()); 401 } 402 403 public IRubyObject finished_p() { 404 return finished ? getRuntime().getTrue() : getRuntime().getFalse(); 405 } 406 407 public IRubyObject close() { 408 if(!closed) { 409 internalClose(); 410 closed = true; 411 } 412 return getRuntime().getNil(); 413 } 414 } 415 416 public static class Inflate extends ZStream { 417 protected static ObjectAllocator INFLATE_ALLOCATOR = new ObjectAllocator() { 418 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 419 return new Inflate(runtime, klass); 420 } 421 }; 422 423 public static IRubyObject s_inflate(IRubyObject recv, IRubyObject string) throws Exception { 424 return ZlibInflate.s_inflate(recv,string.convertToString().getByteList()); 425 } 426 427 public Inflate(Ruby runtime, RubyClass type) { 428 super(runtime, type); 429 } 430 431 private ZlibInflate infl; 432 433 public IRubyObject _initialize(IRubyObject[] args) throws Exception { 434 infl = new ZlibInflate(this); 435 return this; 436 } 437 438 public IRubyObject append(IRubyObject arg) { 439 infl.append(arg); 440 return this; 441 } 442 443 public IRubyObject sync_point_p() { 444 return infl.sync_point(); 445 } 446 447 public IRubyObject set_dictionary(IRubyObject arg) throws Exception { 448 return infl.set_dictionary(arg); 449 } 450 451 public IRubyObject inflate(IRubyObject string) throws Exception { 452 return infl.inflate(string.convertToString().getByteList()); 453 } 454 455 public IRubyObject sync(IRubyObject string) { 456 return infl.sync(string); 457 } 458 459 protected int internalTotalOut() { 460 return infl.getInflater().getTotalOut(); 461 } 462 463 protected boolean internalStreamEndP() { 464 return infl.getInflater().finished(); 465 } 466 467 protected void internalEnd() { 468 infl.getInflater().end(); 469 } 470 471 protected void internalReset() { 472 infl.getInflater().reset(); 473 } 474 475 protected int internalAdler() { 476 return infl.getInflater().getAdler(); 477 } 478 479 protected IRubyObject internalFinish() throws Exception { 480 infl.finish(); 481 return getRuntime().getNil(); 482 } 483 484 public IRubyObject finished_p() { 485 return infl.getInflater().finished() ? getRuntime().getTrue() : getRuntime().getFalse(); 486 } 487 488 protected int internalTotalIn() { 489 return infl.getInflater().getTotalIn(); 490 } 491 492 protected void internalClose() { 493 infl.close(); 494 } 495 } 496 497 public static class Deflate extends ZStream { 498 protected static ObjectAllocator DEFLATE_ALLOCATOR = new ObjectAllocator() { 499 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 500 return new Deflate(runtime, klass); 501 } 502 }; 503 504 public static IRubyObject s_deflate(IRubyObject recv, IRubyObject[] args) throws Exception { 505 args = recv.scanArgs(args,1,1); 506 int level = -1; 507 if(!args[1].isNil()) { 508 level = RubyNumeric.fix2int(args[1]); 509 } 510 return ZlibDeflate.s_deflate(recv,args[0].convertToString().getByteList(),level); 511 } 512 513 public Deflate(Ruby runtime, RubyClass type) { 514 super(runtime, type); 515 } 516 517 private ZlibDeflate defl; 518 519 public IRubyObject _initialize(IRubyObject[] args) throws Exception { 520 args = scanArgs(args,0,4); 521 int level = -1; 522 int window_bits = 15; 523 int memlevel = 8; 524 int strategy = 0; 525 if(!args[0].isNil()) { 526 level = RubyNumeric.fix2int(args[0]); 527 } 528 if(!args[1].isNil()) { 529 window_bits = RubyNumeric.fix2int(args[1]); 530 } 531 if(!args[2].isNil()) { 532 memlevel = RubyNumeric.fix2int(args[2]); 533 } 534 if(!args[3].isNil()) { 535 strategy = RubyNumeric.fix2int(args[3]); 536 } 537 defl = new ZlibDeflate(this,level,window_bits,memlevel,strategy); 538 return this; 539 } 540 541 public IRubyObject append(IRubyObject arg) throws Exception { 542 defl.append(arg); 543 return this; 544 } 545 546 public IRubyObject params(IRubyObject level, IRubyObject strategy) { 547 defl.params(RubyNumeric.fix2int(level),RubyNumeric.fix2int(strategy)); 548 return getRuntime().getNil(); 549 } 550 551 public IRubyObject set_dictionary(IRubyObject arg) throws Exception { 552 return defl.set_dictionary(arg); 553 } 554 555 public IRubyObject flush(IRubyObject[] args) throws Exception { 556 int flush = 2; if(checkArgumentCount(args,0,1) == 1) { 558 if(!args[0].isNil()) { 559 flush = RubyNumeric.fix2int(args[0]); 560 } 561 } 562 return defl.flush(flush); 563 } 564 565 public IRubyObject deflate(IRubyObject[] args) throws Exception { 566 args = scanArgs(args,1,1); 567 int flush = 0; if(!args[1].isNil()) { 569 flush = RubyNumeric.fix2int(args[1]); 570 } 571 return defl.deflate(args[0].convertToString().getByteList(),flush); 572 } 573 574 protected int internalTotalOut() { 575 return defl.getDeflater().getTotalOut(); 576 } 577 578 protected boolean internalStreamEndP() { 579 return defl.getDeflater().finished(); 580 } 581 582 protected void internalEnd() { 583 defl.getDeflater().end(); 584 } 585 586 protected void internalReset() { 587 defl.getDeflater().reset(); 588 } 589 590 protected int internalAdler() { 591 return defl.getDeflater().getAdler(); 592 } 593 594 protected IRubyObject internalFinish() throws Exception { 595 return defl.finish(); 596 } 597 598 protected int internalTotalIn() { 599 return defl.getDeflater().getTotalIn(); 600 } 601 602 protected void internalClose() { 603 defl.close(); 604 } 605 } 606 607 public static class RubyGzipFile extends RubyObject { 608 public static IRubyObject wrap(IRubyObject recv, RubyGzipFile io, IRubyObject proc, Block unusedBlock) throws IOException { 609 if (!proc.isNil()) { 610 try { 611 ((RubyProc)proc).call(new IRubyObject[]{io}); 612 } finally { 613 if (!io.isClosed()) { 614 io.close(); 615 } 616 } 617 return recv.getRuntime().getNil(); 618 } 619 620 return io; 621 } 622 623 protected static ObjectAllocator GZIPFILE_ALLOCATOR = new ObjectAllocator() { 624 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 625 return new RubyGzipFile(runtime, klass); 626 } 627 }; 628 629 public static RubyGzipFile newInstance(IRubyObject recv, Block block) { 630 RubyClass klass = (RubyClass)recv; 631 632 RubyGzipFile result = (RubyGzipFile) klass.allocate(); 633 634 result.callInit(new IRubyObject[0], block); 635 636 return result; 637 } 638 639 protected boolean closed = false; 640 protected boolean finished = false; 641 private int os_code = 255; 642 private int level = -1; 643 private String orig_name; 644 private String comment; 645 protected IRubyObject realIo; 646 private IRubyObject mtime; 647 648 public RubyGzipFile(Ruby runtime, RubyClass type) { 649 super(runtime, type); 650 mtime = runtime.getNil(); 651 } 652 653 public IRubyObject os_code() { 654 return getRuntime().newFixnum(os_code); 655 } 656 657 public IRubyObject closed_p() { 658 return closed ? getRuntime().getTrue() : getRuntime().getFalse(); 659 } 660 661 protected boolean isClosed() { 662 return closed; 663 } 664 665 public IRubyObject orig_name() { 666 return orig_name == null ? getRuntime().getNil() : getRuntime().newString(orig_name); 667 } 668 669 public Object to_io() { 670 return realIo; 671 } 672 673 public IRubyObject comment() { 674 return comment == null ? getRuntime().getNil() : getRuntime().newString(comment); 675 } 676 677 public IRubyObject crc() { 678 return RubyFixnum.zero(getRuntime()); 679 } 680 681 public IRubyObject mtime() { 682 return mtime; 683 } 684 685 public IRubyObject sync() { 686 return getRuntime().getNil(); 687 } 688 689 public IRubyObject finish() throws IOException { 690 if (!finished) { 691 } 693 finished = true; 694 return realIo; 695 } 696 697 public IRubyObject close() throws IOException { 698 return null; 699 } 700 701 public IRubyObject level() { 702 return getRuntime().newFixnum(level); 703 } 704 705 public IRubyObject set_sync(IRubyObject ignored) { 706 return getRuntime().getNil(); 707 } 708 } 709 710 public static class RubyGzipReader extends RubyGzipFile { 711 protected static ObjectAllocator GZIPREADER_ALLOCATOR = new ObjectAllocator() { 712 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 713 return new RubyGzipReader(runtime, klass); 714 } 715 }; 716 717 private static RubyGzipReader newInstance(IRubyObject recv, IRubyObject[] args, Block block) { 718 RubyClass klass = (RubyClass)recv; 719 RubyGzipReader result = (RubyGzipReader)klass.allocate(); 720 result.callInit(args, block); 721 return result; 722 } 723 724 public static IRubyObject open(IRubyObject recv, RubyString filename, Block block) throws IOException { 725 Ruby runtime = recv.getRuntime(); 726 IRubyObject proc = block.isGiven() ? runtime.newProc(false, block) : runtime.getNil(); 727 RubyGzipReader io = newInstance( 728 recv, 729 new IRubyObject[]{ runtime.getClass("File").callMethod( 730 runtime.getCurrentContext(), 731 "open", 732 new IRubyObject[]{filename, runtime.newString("rb")})}, 733 block); 734 735 return RubyGzipFile.wrap(recv, io, proc, null); 736 } 737 738 public RubyGzipReader(Ruby runtime, RubyClass type) { 739 super(runtime, type); 740 } 741 742 private int line; 743 private InputStream io; 744 745 public IRubyObject initialize(IRubyObject io, Block unusedBlock) { 746 realIo = io; 747 try { 748 this.io = new GZIPInputStream (new IOInputStream(io)); 749 } catch (IOException e) { 750 Ruby runtime = io.getRuntime(); 751 RubyClass errorClass = runtime.getModule("Zlib").getClass("GzipReader").getClass("Error"); 752 throw new RaiseException(RubyException.newException(runtime, errorClass, e.getMessage())); 753 } 754 755 line = 1; 756 757 return this; 758 } 759 760 public IRubyObject rewind() { 761 return getRuntime().getNil(); 762 } 763 764 public IRubyObject lineno() { 765 return getRuntime().newFixnum(line); 766 } 767 768 public IRubyObject readline() throws IOException { 769 IRubyObject dst = gets(new IRubyObject[0]); 770 if (dst.isNil()) { 771 throw getRuntime().newEOFError(); 772 } 773 return dst; 774 } 775 776 public IRubyObject internalGets(IRubyObject[] args) throws IOException { 777 String sep = ((RubyString)getRuntime().getGlobalVariables().get("$/")).getValue().toString(); 778 if (args.length > 0) { 779 sep = args[0].toString(); 780 } 781 return internalSepGets(sep); 782 } 783 784 private IRubyObject internalSepGets(String sep) throws IOException { 785 StringBuffer result = new StringBuffer (); 786 char ce = (char) io.read(); 787 while (ce != -1 && sep.indexOf(ce) == -1) { 788 result.append((char) ce); 789 ce = (char) io.read(); 790 } 791 line++; 792 return getRuntime().newString(result.append(sep).toString()); 793 } 794 795 public IRubyObject gets(IRubyObject[] args) throws IOException { 796 IRubyObject result = internalGets(args); 797 if (!result.isNil()) { 798 getRuntime().getCurrentContext().setLastline(result); 799 } 800 return result; 801 } 802 803 private final static int BUFF_SIZE = 4096; 804 public IRubyObject read(IRubyObject[] args) throws IOException { 805 if (args.length == 0 || args[0].isNil()) { 806 ByteList val = new ByteList(10); 807 byte[] buffer = new byte[BUFF_SIZE]; 808 int read = io.read(buffer); 809 while (read != -1) { 810 val.append(buffer,0,read); 811 read = io.read(buffer); 812 } 813 return RubyString.newString(getRuntime(),val); 814 } 815 816 int len = RubyNumeric.fix2int(args[0]); 817 if (len < 0) { 818 throw getRuntime().newArgumentError("negative length " + len + " given"); 819 } else if (len > 0) { 820 byte[] buffer = new byte[len]; 821 int toRead = len; 822 int offset = 0; 823 int read = 0; 824 while (toRead > 0) { 825 read = io.read(buffer,offset,toRead); 826 if (read == -1) { 827 break; 828 } 829 toRead -= read; 830 offset += read; 831 } return RubyString.newString(getRuntime(),new ByteList(buffer,0,len-toRead,false)); 833 } 834 835 return getRuntime().newString(""); 836 } 837 838 public IRubyObject set_lineno(RubyNumeric lineArg) { 839 line = RubyNumeric.fix2int(lineArg); 840 return lineArg; 841 } 842 843 public IRubyObject pos() { 844 return RubyFixnum.zero(getRuntime()); 845 } 846 847 public IRubyObject readchar() throws IOException { 848 int value = io.read(); 849 if (value == -1) { 850 throw getRuntime().newEOFError(); 851 } 852 return getRuntime().newFixnum(value); 853 } 854 855 public IRubyObject getc() throws IOException { 856 int value = io.read(); 857 return value == -1 ? getRuntime().getNil() : getRuntime().newFixnum(value); 858 } 859 860 private boolean isEof() throws IOException { 861 return ((GZIPInputStream )io).available() != 1; 862 } 863 864 public IRubyObject close() throws IOException { 865 if (!closed) { 866 io.close(); 867 } 868 this.closed = true; 869 return getRuntime().getNil(); 870 } 871 872 public IRubyObject eof() throws IOException { 873 return isEof() ? getRuntime().getTrue() : getRuntime().getFalse(); 874 } 875 876 public IRubyObject eof_p() throws IOException { 877 return eof(); 878 } 879 880 public IRubyObject unused() { 881 return getRuntime().getNil(); 882 } 883 884 public IRubyObject tell() { 885 return getRuntime().getNil(); 886 } 887 888 public IRubyObject each(IRubyObject[] args, Block block) throws IOException { 889 String sep = ((RubyString)getRuntime().getGlobalVariables().get("$/")).getValue().toString(); 890 891 if (args.length > 0 && !args[0].isNil()) { 892 sep = args[0].toString(); 893 } 894 895 ThreadContext context = getRuntime().getCurrentContext(); 896 while (!isEof()) { 897 context.yield(internalSepGets(sep), block); 898 } 899 900 return getRuntime().getNil(); 901 } 902 903 public IRubyObject ungetc(RubyNumeric arg) { 904 return getRuntime().getNil(); 905 } 906 907 public IRubyObject readlines(IRubyObject[] args) throws IOException { 908 List array = new ArrayList (); 909 910 if (args.length != 0 && args[0].isNil()) { 911 array.add(read(new IRubyObject[0])); 912 } else { 913 String seperator = ((RubyString)getRuntime().getGlobalVariables().get("$/")).getValue().toString(); 914 if (args.length > 0) { 915 seperator = args[0].toString(); 916 } 917 while (!isEof()) { 918 array.add(internalSepGets(seperator)); 919 } 920 } 921 return getRuntime().newArray(array); 922 } 923 924 public IRubyObject each_byte(Block block) throws IOException { 925 int value = io.read(); 926 927 ThreadContext context = getRuntime().getCurrentContext(); 928 while (value != -1) { 929 context.yield(getRuntime().newFixnum(value), block); 930 value = io.read(); 931 } 932 933 return getRuntime().getNil(); 934 } 935 } 936 937 public static class RubyGzipWriter extends RubyGzipFile { 938 protected static ObjectAllocator GZIPWRITER_ALLOCATOR = new ObjectAllocator() { 939 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 940 return new RubyGzipWriter(runtime, klass); 941 } 942 }; 943 944 private static RubyGzipWriter newGzipWriter(IRubyObject recv, IRubyObject[] args, Block block) { 945 RubyClass klass = (RubyClass)recv; 946 947 RubyGzipWriter result = (RubyGzipWriter)klass.allocate(); 948 result.callInit(args, block); 949 return result; 950 } 951 952 public static IRubyObject open(IRubyObject recv, IRubyObject[] args, Block block) throws IOException { 953 Ruby runtime = recv.getRuntime(); 954 IRubyObject level = runtime.getNil(); 955 IRubyObject strategy = runtime.getNil(); 956 957 if (args.length > 1) { 958 level = args[1]; 959 if (args.length > 2) strategy = args[2]; 960 } 961 962 IRubyObject proc = block.isGiven() ? runtime.newProc(false, block) : runtime.getNil(); 963 RubyGzipWriter io = newGzipWriter( 964 recv, 965 new IRubyObject[]{ runtime.getClass("File").callMethod( 966 runtime.getCurrentContext(), 967 "open", 968 new IRubyObject[]{args[0],runtime.newString("wb")}),level,strategy},block); 969 970 return RubyGzipFile.wrap(recv, io, proc, null); 971 } 972 973 public RubyGzipWriter(Ruby runtime, RubyClass type) { 974 super(runtime, type); 975 } 976 977 private GZIPOutputStream io; 978 public IRubyObject initialize2(IRubyObject[] args, Block unusedBlock) throws IOException { 979 realIo = (RubyObject)args[0]; 980 this.io = new GZIPOutputStream (new IOOutputStream(args[0])); 981 982 return this; 983 } 984 985 public IRubyObject close() throws IOException { 986 if (!closed) { 987 io.close(); 988 } 989 this.closed = true; 990 991 return getRuntime().getNil(); 992 } 993 994 public IRubyObject append(IRubyObject p1) throws IOException { 995 this.write(p1); 996 return this; 997 } 998 999 public IRubyObject printf(IRubyObject[] args) throws IOException { 1000 write(RubyKernel.sprintf(this, args)); 1001 return getRuntime().getNil(); 1002 } 1003 1004 public IRubyObject print(IRubyObject[] args) throws IOException { 1005 if (args.length != 0) { 1006 for (int i = 0, j = args.length; i < j; i++) { 1007 write(args[i]); 1008 } 1009 } 1010 1011 IRubyObject sep = getRuntime().getGlobalVariables().get("$\\"); 1012 if (!sep.isNil()) { 1013 write(sep); 1014 } 1015 1016 return getRuntime().getNil(); 1017 } 1018 1019 public IRubyObject pos() { 1020 return getRuntime().getNil(); 1021 } 1022 1023 public IRubyObject set_orig_name(RubyString ignored) { 1024 return getRuntime().getNil(); 1025 } 1026 1027 public IRubyObject set_comment(RubyString ignored) { 1028 return getRuntime().getNil(); 1029 } 1030 1031 public IRubyObject putc(RubyNumeric p1) throws IOException { 1032 io.write(RubyNumeric.fix2int(p1)); 1033 return p1; 1034 } 1035 1036 public IRubyObject puts(IRubyObject[] args) throws IOException { 1037 RubyStringIO sio = (RubyStringIO)getRuntime().getClass("StringIO").newInstance(new IRubyObject[0], Block.NULL_BLOCK); 1038 sio.puts(args); 1039 write(sio.string()); 1040 1041 return getRuntime().getNil(); 1042 } 1043 1044 public IRubyObject finish() throws IOException { 1045 if (!finished) { 1046 io.finish(); 1047 } 1048 finished = true; 1049 return realIo; 1050 } 1051 1052 public IRubyObject flush(IRubyObject[] args) throws IOException { 1053 if (args.length == 0 || args[0].isNil() || RubyNumeric.fix2int(args[0]) != 0) { io.flush(); 1055 } 1056 return getRuntime().getNil(); 1057 } 1058 1059 public IRubyObject set_mtime(IRubyObject ignored) { 1060 return getRuntime().getNil(); 1061 } 1062 1063 public IRubyObject tell() { 1064 return getRuntime().getNil(); 1065 } 1066 1067 public IRubyObject write(IRubyObject p1) throws IOException { 1068 byte[] bs = p1.convertToString().getBytes(); 1069 io.write(bs); 1070 return getRuntime().newFixnum(bs.length); 1071 } 1072 } 1073} 1074 | Popular Tags |