diff --git a/Merlin/External/Languages/IronRuby/mspec/ironruby-tags/library/zlib/gzipwriter/wrap_tags.txt b/Merlin/External/Languages/IronRuby/mspec/ironruby-tags/library/zlib/gzipwriter/wrap_tags.txt new file mode 100644 index 0000000000..300bebf122 --- /dev/null +++ b/Merlin/External/Languages/IronRuby/mspec/ironruby-tags/library/zlib/gzipwriter/wrap_tags.txt @@ -0,0 +1 @@ +fails:Zlib::GzipWriter.wrap can be called without a block with a non-writable object diff --git a/Merlin/External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb b/Merlin/External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb index 179a1512eb..3b5a0c6847 100644 --- a/Merlin/External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb +++ b/Merlin/External/Languages/IronRuby/mspec/rubyspec/fixtures/class.rb @@ -85,6 +85,35 @@ def self.example_class_method class L; end class M < L; end + + class StubWriter + def write s + return s.size if s + 0 + end + end + + class StubWriterWithClose < StubWriter + def close *args + end + end + + class StubReader + def initialize s + @s = s + end + + def read size=2048 + s = @s + @s = nil + s + end + end + + class StubReaderWithClose < StubReader + def close *args + end + end end class Class diff --git a/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/fixtures/classes.rb b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/fixtures/classes.rb new file mode 100644 index 0000000000..0ab5789b6c --- /dev/null +++ b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/fixtures/classes.rb @@ -0,0 +1,5 @@ +module GzipReaderSpecs + UncompressedContents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." + + GzippedContents = "\037\213\b\000\325\374\262I\000\vM\221AN\0031\fE\367\234\302\a@\250,@b\311\262\022H\\\301\223q;Q\023'\212\235\016s{\376\244 \272\213e\373\377\347\237c\265\236)\032Y\3145m4\367\2347r\371v*'\362E\250\266\250\036\365L\2543\371V\305\304G\035u\356\346m{\242\207\217\322$\323qh-l4\211\350X\376\233\201\276c\237\333|\357 Wi0\326 c\370\371\345p\260GZ\027,\263R\327\213\226Uo\000\030\364R.\304t\346\224d\et\200\031T\026\032\347)\311L\3211F\231/h\334\372V%\304\f\305\t\353@=\372 \264\336\256\361\212\r-\270Tq\371\t%\005Q\357-\n0\246\356\304\311\312@K\302\025\307@[\222\004oEc\270\017\343\221\020\000G\335s\0213\250D`n\270!,\254g\231o\316+\234k\251=q\213\266\343\336Rz~{=\030\255\321\227Q6x\260\311~\342\207x\303\323\311\026\0217\nE\375\327\346>\363\312f|\336\251\36782:\020\331o\001\302\220\235\305.^*\325>\245h\313\276o\345\344+c2E\244\365\236\360Q\364\005\221O\204\327@\026R\237\3679\374\221\305\2426p\376=\237~\000\003\357\321!:\002\000\000" +end diff --git a/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/wrap_spec.rb b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/wrap_spec.rb new file mode 100644 index 0000000000..5652ed3586 --- /dev/null +++ b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipreader/wrap_spec.rb @@ -0,0 +1,58 @@ +require "zlib" +require File.dirname(__FILE__) + '/../../../spec_helper' +require File.dirname(__FILE__) + '/../../../fixtures/class' +require File.dirname(__FILE__) + '/fixtures/classes' + +describe "Zlib::GzipReader.wrap" do + before :each do + @io = ClassSpecs::StubReaderWithClose.new GzipReaderSpecs::GzippedContents + end + + it "can be called without a block" do + Zlib::GzipReader.wrap(@io).should be_kind_of(Zlib::GzipReader) + end + + it "raises NoMethodError if argument does not have a write method" do + lambda { Zlib::GzipReader.wrap(nil) { } }.should raise_error(NoMethodError) + lambda { Zlib::GzipReader.wrap(mock("dummy")) { } }.should raise_error(NoMethodError) + end + + it "invokes the block with an instance of GzipReader" do + Zlib::GzipReader.wrap(@io) do |gz| + ScratchPad.record gz + end + ScratchPad.recorded.should be_kind_of(Zlib::GzipReader) + end + + it "returns the instance of GzipReader" do + ret = Zlib::GzipReader.wrap(@io) do |gz| + ScratchPad.record gz + end + ret.should equal(ScratchPad.recorded) + end + + it "allows the GzipReader instance to be closed in the block" do + ScratchPad.clear + ret = Zlib::GzipReader.wrap(@io) do |gz| + gz.close + ScratchPad.record :after_close + end + ScratchPad.recorded.should == :after_close + end + + it "calls io#close once for a trivial block" do + @io.should_receive(:close) + Zlib::GzipReader.wrap(@io) { } + end + + it "allows IO objects without a close method" do + io = mock("io") + io.should_receive(:read).any_number_of_times.and_return(GzipReaderSpecs::GzippedContents, nil) + Zlib::GzipReader.wrap(io) { |gz| gz.read } + end + + it "propagates Exceptions thrown from the block after calling io#close" do + @io.should_receive(:close) + lambda { Zlib::GzipReader.wrap(@io) { raise "error from block" } }.should raise_error(RuntimeError, "error from block") + end +end diff --git a/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/wrap_spec.rb b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/wrap_spec.rb new file mode 100644 index 0000000000..b4c1a6044f --- /dev/null +++ b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/wrap_spec.rb @@ -0,0 +1,66 @@ +require "zlib" +require File.dirname(__FILE__) + '/../../../spec_helper' +require File.dirname(__FILE__) + '/../../../fixtures/class' + +describe "Zlib::GzipWriter.wrap" do + before :each do + @io = ClassSpecs::StubWriterWithClose.new + end + + it "can be called without a block" do + @io.should_not_receive :write + @io.should_not_receive :close + Zlib::GzipWriter.wrap(@io).should be_kind_of(Zlib::GzipWriter) + end + + ruby_bug "Causes segmentation fault", "1.8" do + it "can be called without a block with a non-writable object" do + Zlib::GzipWriter.wrap(nil).should be_kind_of(Zlib::GzipWriter) + end + end + + it "raises NoMethodError if argument does not have a write method" do + lambda { Zlib::GzipWriter.wrap(mock("dummy")) { } }.should raise_error(NoMethodError) + end + + it "invokes the block with an instance of GzipWriter" do + Zlib::GzipWriter.wrap(@io) do |gz| + ScratchPad.record gz + end + ScratchPad.recorded.should be_kind_of(Zlib::GzipWriter) + end + + it "returns the instance of GzipWriter" do + ret = Zlib::GzipWriter.wrap(@io) do |gz| + ScratchPad.record gz + end + ret.should equal(ScratchPad.recorded) + end + + it "allows the GzipWriter instance to be closed in the block" do + ScratchPad.clear + @io.should_receive :close + Zlib::GzipWriter.wrap(@io) do |gz| + gz.close + ScratchPad.record :after_gzipwriter_close + end + ScratchPad.recorded.should == :after_gzipwriter_close + end + + it "calls io#close once for a trivial block" do + ScratchPad.record [] + @io.should_receive :close + Zlib::GzipWriter.wrap(@io) { } + end + + it "allows IO objects without a close method" do + io = ClassSpecs::StubWriter.new + io.should_receive(:write).any_number_of_times + Zlib::GzipWriter.wrap(io) { |gz| gz << "Hello" } + end + + it "propagates Exceptions thrown from the block after calling close" do + @io.should_receive :close + lambda { Zlib::GzipWriter.wrap(@io) { raise "error from block" } }.should raise_error(RuntimeError, "error from block") + end +end diff --git a/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/write_spec.rb b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/write_spec.rb index 09536aec13..85c2c95ce7 100644 --- a/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/write_spec.rb +++ b/Merlin/External/Languages/IronRuby/mspec/rubyspec/library/zlib/gzipwriter/write_spec.rb @@ -10,6 +10,14 @@ @io = StringIO.new end + it "writes some compressed data that can be uncompressed" do + Zlib::GzipWriter.wrap @io do |gzio| + gzio.write @data + end + + Zlib::GzipReader.new(StringIO.new(@io.string, "r")).read().should == @data + end + it "writes some compressed data" do Zlib::GzipWriter.wrap @io do |gzio| gzio.write @data diff --git a/Merlin/Main/Config/Unsigned/App.config b/Merlin/Main/Config/Unsigned/App.config index 812f81c2ab..665b4f86de 100644 --- a/Merlin/Main/Config/Unsigned/App.config +++ b/Merlin/Main/Config/Unsigned/App.config @@ -12,7 +12,7 @@ - + diff --git a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/IoOps.cs b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/IoOps.cs index 77fb2985ff..c59fe7fdde 100644 --- a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/IoOps.cs +++ b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/IoOps.cs @@ -982,7 +982,7 @@ public class RubyIOOps { public static IOWrapper/*!*/ CreateIOWrapper(RespondToStorage/*!*/ respondToStorage, RubyContext/*!*/ context, object io, FileAccess access) { - bool canRead, canWrite, canSeek; + bool canRead, canWrite, canSeek, canBeClosed; if (access == FileAccess.Read || access == FileAccess.ReadWrite) { canRead = Protocols.RespondTo(respondToStorage, context, io, "read"); @@ -997,8 +997,9 @@ public class RubyIOOps { } canSeek = Protocols.RespondTo(respondToStorage, context, io, "seek") && Protocols.RespondTo(respondToStorage, context, io, "tell"); + canBeClosed = Protocols.RespondTo(respondToStorage, context, io, "close"); - return new IOWrapper(context, io, canRead, canWrite, canSeek); + return new IOWrapper(context, io, canRead, canWrite, canSeek, canBeClosed); } } } diff --git a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs index 1575837752..2d2dbcdaf3 100644 --- a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs +++ b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Initializers.Generated.cs @@ -75,16 +75,16 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia new System.Action(IronRuby.Builtins.RubyStructOps.AllocatorUndefined) ); ExtendModule(typeof(System.Collections.Generic.IDictionary), LoadSystem__Collections__Generic__IDictionary_Instance, null, null, def21); - IronRuby.Builtins.RubyModule def35 = ExtendModule(typeof(System.Collections.IEnumerable), LoadSystem__Collections__IEnumerable_Instance, null, null, def21); + IronRuby.Builtins.RubyModule def36 = ExtendModule(typeof(System.Collections.IEnumerable), LoadSystem__Collections__IEnumerable_Instance, null, null, def21); ExtendModule(typeof(System.Collections.IList), LoadSystem__Collections__IList_Instance, null, null, def21); - ExtendModule(typeof(System.IComparable), LoadSystem__IComparable_Instance, null, null, def30); + IronRuby.Builtins.RubyModule def35 = ExtendModule(typeof(System.IComparable), LoadSystem__IComparable_Instance, null, null, def30); DefineGlobalClass("Array", typeof(IronRuby.Builtins.RubyArray), false, Context.ObjectClass, LoadArray_Instance, LoadArray_Class, null, new IronRuby.Builtins.RubyModule[] {def21}, new System.Func(IronRuby.Builtins.ArrayOps.CreateArray), new System.Func>, IronRuby.Runtime.BlockParam, IronRuby.Builtins.RubyClass, System.Object, System.Object>(IronRuby.Builtins.ArrayOps.CreateArray), new System.Func(IronRuby.Builtins.ArrayOps.CreateArray) ); DefineGlobalClass("Binding", typeof(IronRuby.Builtins.Binding), false, Context.ObjectClass, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray); - DefineGlobalClass("ClrString", typeof(System.String), false, Context.ObjectClass, LoadClrString_Instance, null, null, new IronRuby.Builtins.RubyModule[] {def35}); + DefineGlobalClass("ClrString", typeof(System.String), false, Context.ObjectClass, LoadClrString_Instance, null, null, new IronRuby.Builtins.RubyModule[] {def35, def36}); DefineGlobalClass("Dir", typeof(IronRuby.Builtins.RubyDir), true, Context.ObjectClass, LoadDir_Instance, LoadDir_Class, null, new IronRuby.Builtins.RubyModule[] {def21}); #if !SILVERLIGHT DefineGlobalClass("Encoding", typeof(IronRuby.Builtins.RubyEncoding), false, Context.ObjectClass, LoadEncoding_Instance, LoadEncoding_Class, null, IronRuby.Builtins.RubyModule.EmptyArray); @@ -6485,43 +6485,90 @@ public sealed class ZlibLibraryInitializer : IronRuby.Builtins.LibraryInitialize IronRuby.Builtins.RubyModule def1 = DefineGlobalModule("Zlib", typeof(IronRuby.StandardLibrary.Zlib.Zlib), true, null, null, LoadZlib_Constants, IronRuby.Builtins.RubyModule.EmptyArray); - IronRuby.Builtins.RubyClass def4 = DefineClass("Zlib::Error", typeof(IronRuby.StandardLibrary.Zlib.Zlib.Error), true, classRef0, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, + IronRuby.Builtins.RubyClass def5 = DefineClass("Zlib::Error", typeof(IronRuby.StandardLibrary.Zlib.Zlib.Error), true, classRef0, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, new System.Func(ZlibLibraryInitializer.ExceptionFactory__Zlib__Error)); - IronRuby.Builtins.RubyClass def5 = DefineClass("Zlib::GzipFile", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile), true, classRef1, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray); - IronRuby.Builtins.RubyClass def6 = DefineClass("Zlib::GzipFile::Error", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile.Error), true, classRef2, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray); - IronRuby.Builtins.RubyClass def9 = DefineClass("Zlib::ZStream", typeof(IronRuby.StandardLibrary.Zlib.Zlib.ZStream), true, classRef1, LoadZlib__ZStream_Instance, null, null, IronRuby.Builtins.RubyModule.EmptyArray); - IronRuby.Builtins.RubyClass def2 = DefineClass("Zlib::BufError", typeof(IronRuby.StandardLibrary.Zlib.Zlib.BufError), true, def4, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, + IronRuby.Builtins.RubyClass def6 = DefineClass("Zlib::GzipFile", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile), true, classRef1, LoadZlib__GzipFile_Instance, LoadZlib__GzipFile_Class, null, IronRuby.Builtins.RubyModule.EmptyArray); + IronRuby.Builtins.RubyClass def7 = DefineClass("Zlib::GzipFile::Error", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile.Error), true, classRef2, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray); + IronRuby.Builtins.RubyClass def11 = DefineClass("Zlib::ZStream", typeof(IronRuby.StandardLibrary.Zlib.Zlib.ZStream), true, classRef1, LoadZlib__ZStream_Instance, null, null, IronRuby.Builtins.RubyModule.EmptyArray); + IronRuby.Builtins.RubyClass def2 = DefineClass("Zlib::BufError", typeof(IronRuby.StandardLibrary.Zlib.Zlib.BufError), true, def5, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, new System.Func(ZlibLibraryInitializer.ExceptionFactory__Zlib__BufError)); - IronRuby.Builtins.RubyClass def3 = DefineClass("Zlib::DataError", typeof(IronRuby.StandardLibrary.Zlib.Zlib.DataError), true, def4, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, + IronRuby.Builtins.RubyClass def3 = DefineClass("Zlib::DataError", typeof(IronRuby.StandardLibrary.Zlib.Zlib.DataError), true, def5, null, null, null, IronRuby.Builtins.RubyModule.EmptyArray, new System.Func(ZlibLibraryInitializer.ExceptionFactory__Zlib__DataError)); - IronRuby.Builtins.RubyClass def7 = DefineClass("Zlib::GzipReader", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader), true, def5, LoadZlib__GzipReader_Instance, LoadZlib__GzipReader_Class, LoadZlib__GzipReader_Constants, IronRuby.Builtins.RubyModule.EmptyArray, - new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Create), + IronRuby.Builtins.RubyClass def4 = DefineClass("Zlib::Deflate", typeof(IronRuby.StandardLibrary.Zlib.Zlib.Deflate), true, def11, LoadZlib__Deflate_Instance, LoadZlib__Deflate_Class, null, IronRuby.Builtins.RubyModule.EmptyArray); + IronRuby.Builtins.RubyClass def8 = DefineClass("Zlib::GzipReader", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader), true, def6, LoadZlib__GzipReader_Instance, LoadZlib__GzipReader_Class, LoadZlib__GzipReader_Constants, IronRuby.Builtins.RubyModule.EmptyArray, new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Create) ); - IronRuby.Builtins.RubyClass def8 = DefineClass("Zlib::Inflate", typeof(IronRuby.StandardLibrary.Zlib.Zlib.Inflate), true, def9, LoadZlib__Inflate_Instance, LoadZlib__Inflate_Class, null, IronRuby.Builtins.RubyModule.EmptyArray); - def1.SetConstant("Error", def4); - def1.SetConstant("GzipFile", def5); - def5.SetConstant("Error", def6); - def1.SetConstant("ZStream", def9); + IronRuby.Builtins.RubyClass def9 = DefineClass("Zlib::GzipWriter", typeof(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter), true, def6, LoadZlib__GzipWriter_Instance, null, null, IronRuby.Builtins.RubyModule.EmptyArray, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter.Create) + ); + IronRuby.Builtins.RubyClass def10 = DefineClass("Zlib::Inflate", typeof(IronRuby.StandardLibrary.Zlib.Zlib.Inflate), true, def11, LoadZlib__Inflate_Instance, LoadZlib__Inflate_Class, null, IronRuby.Builtins.RubyModule.EmptyArray); + def1.SetConstant("Error", def5); + def1.SetConstant("GzipFile", def6); + def6.SetConstant("Error", def7); + def1.SetConstant("ZStream", def11); def1.SetConstant("BufError", def2); def1.SetConstant("DataError", def3); - def1.SetConstant("GzipReader", def7); - def1.SetConstant("Inflate", def8); + def1.SetConstant("Deflate", def4); + def1.SetConstant("GzipReader", def8); + def1.SetConstant("GzipWriter", def9); + def1.SetConstant("Inflate", def10); } private static void LoadZlib_Constants(IronRuby.Builtins.RubyModule/*!*/ module) { + module.SetConstant("ASCII", IronRuby.StandardLibrary.Zlib.Zlib.ASCII); + module.SetConstant("BEST_COMPRESSION", IronRuby.StandardLibrary.Zlib.Zlib.BEST_COMPRESSION); + module.SetConstant("BEST_SPEED", IronRuby.StandardLibrary.Zlib.Zlib.BEST_SPEED); + module.SetConstant("BINARY", IronRuby.StandardLibrary.Zlib.Zlib.BINARY); + module.SetConstant("DEFAULT_COMPRESSION", IronRuby.StandardLibrary.Zlib.Zlib.DEFAULT_COMPRESSION); + module.SetConstant("DEFAULT_STRATEGY", IronRuby.StandardLibrary.Zlib.Zlib.DEFAULT_STRATEGY); + module.SetConstant("FILTERED", IronRuby.StandardLibrary.Zlib.Zlib.FILTERED); + module.SetConstant("FINISH", IronRuby.StandardLibrary.Zlib.Zlib.FINISH); module.SetConstant("FIXLCODES", IronRuby.StandardLibrary.Zlib.Zlib.FIXLCODES); + module.SetConstant("FULL_FLUSH", IronRuby.StandardLibrary.Zlib.Zlib.FULL_FLUSH); + module.SetConstant("HUFFMAN_ONLY", IronRuby.StandardLibrary.Zlib.Zlib.HUFFMAN_ONLY); module.SetConstant("MAX_WBITS", IronRuby.StandardLibrary.Zlib.Zlib.MAX_WBITS); module.SetConstant("MAXBITS", IronRuby.StandardLibrary.Zlib.Zlib.MAXBITS); module.SetConstant("MAXCODES", IronRuby.StandardLibrary.Zlib.Zlib.MAXCODES); module.SetConstant("MAXDCODES", IronRuby.StandardLibrary.Zlib.Zlib.MAXDCODES); module.SetConstant("MAXLCODES", IronRuby.StandardLibrary.Zlib.Zlib.MAXLCODES); + module.SetConstant("NO_COMPRESSION", IronRuby.StandardLibrary.Zlib.Zlib.NO_COMPRESSION); + module.SetConstant("NO_FLUSH", IronRuby.StandardLibrary.Zlib.Zlib.NO_FLUSH); + module.SetConstant("SYNC_FLUSH", IronRuby.StandardLibrary.Zlib.Zlib.SYNC_FLUSH); + module.SetConstant("UNKNOWN", IronRuby.StandardLibrary.Zlib.Zlib.UNKNOWN); module.SetConstant("VERSION", IronRuby.StandardLibrary.Zlib.Zlib.VERSION); module.SetConstant("Z_DEFLATED", IronRuby.StandardLibrary.Zlib.Zlib.Z_DEFLATED); module.SetConstant("ZLIB_VERSION", IronRuby.StandardLibrary.Zlib.Zlib.ZLIB_VERSION); } + private static void LoadZlib__Deflate_Instance(IronRuby.Builtins.RubyModule/*!*/ module) { + module.DefineLibraryMethod("deflate", 0x11, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.Deflate.DeflateString) + ); + + } + + private static void LoadZlib__Deflate_Class(IronRuby.Builtins.RubyModule/*!*/ module) { + module.DefineLibraryMethod("deflate", 0x21, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.Deflate.DeflateString) + ); + + } + + private static void LoadZlib__GzipFile_Instance(IronRuby.Builtins.RubyModule/*!*/ module) { + module.DefineLibraryMethod("closed?", 0x11, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile.IsClosed) + ); + + } + + private static void LoadZlib__GzipFile_Class(IronRuby.Builtins.RubyModule/*!*/ module) { + module.DefineLibraryMethod("wrap", 0x21, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipFile.Wrap) + ); + + } + private static void LoadZlib__GzipReader_Constants(IronRuby.Builtins.RubyModule/*!*/ module) { module.SetConstant("OSES", IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.OSES); @@ -6529,13 +6576,17 @@ public sealed class ZlibLibraryInitializer : IronRuby.Builtins.LibraryInitialize private static void LoadZlib__GzipReader_Instance(IronRuby.Builtins.RubyModule/*!*/ module) { module.DefineLibraryMethod("close", 0x11, - new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Close) + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Close) ); module.DefineLibraryMethod("comment", 0x11, new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Comment) ); + module.DefineLibraryMethod("finish", 0x11, + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Close) + ); + module.DefineLibraryMethod("open", 0x12, new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Open) ); @@ -6556,8 +6607,27 @@ public sealed class ZlibLibraryInitializer : IronRuby.Builtins.LibraryInitialize private static void LoadZlib__GzipReader_Class(IronRuby.Builtins.RubyModule/*!*/ module) { module.DefineLibraryMethod("open", 0x21, - new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Open), - new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Open) + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Open), + new System.Func(IronRuby.StandardLibrary.Zlib.Zlib.GZipReader.Open) + ); + + } + + private static void LoadZlib__GzipWriter_Instance(IronRuby.Builtins.RubyModule/*!*/ module) { + module.DefineLibraryMethod("<<", 0x11, + new System.Func, IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter, System.Object, IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter>(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter.Output) + ); + + module.DefineLibraryMethod("close", 0x11, + new System.Action(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter.Close) + ); + + module.DefineLibraryMethod("finish", 0x11, + new System.Action(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter.Close) + ); + + module.DefineLibraryMethod("write", 0x11, + new System.Func, IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter, System.Object, System.Int32>(IronRuby.StandardLibrary.Zlib.Zlib.GzipWriter.Write) ); } diff --git a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Zlib/zlib.cs b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Zlib/zlib.cs index 14deee0f9b..b75dc8824e 100644 --- a/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Zlib/zlib.cs +++ b/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Zlib/zlib.cs @@ -21,6 +21,10 @@ using IronRuby.Runtime; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Generation; +using System.IO.Compression; +using System.Diagnostics; +using System.Text; +using System.Runtime.InteropServices; namespace IronRuby.StandardLibrary.Zlib { @@ -29,6 +33,18 @@ public static class Zlib { #region Constants + [RubyConstant("NO_FLUSH")] + public const int NO_FLUSH = 0; + + [RubyConstant("SYNC_FLUSH")] + public const int SYNC_FLUSH = 2; + + [RubyConstant("FULL_FLUSH")] + public const int FULL_FLUSH = 3; + + [RubyConstant("FINISH")] + public const int FINISH = 4; + [RubyConstant("ZLIB_VERSION")] public static string ZLIB_VERSION = "1.2.3"; @@ -56,6 +72,36 @@ public static class Zlib { [RubyConstant("Z_DEFLATED")] public const int Z_DEFLATED = 8; + [RubyConstant("BINARY")] + public const int BINARY = 0; + + [RubyConstant("ASCII")] + public const int ASCII = 1; + + [RubyConstant("UNKNOWN")] + public const int UNKNOWN = 2; + + [RubyConstant("NO_COMPRESSION")] + public const int NO_COMPRESSION = 0; + + [RubyConstant("BEST_SPEED")] + public const int BEST_SPEED = 1; + + [RubyConstant("BEST_COMPRESSION")] + public const int BEST_COMPRESSION = 9; + + [RubyConstant("DEFAULT_COMPRESSION")] + public const int DEFAULT_COMPRESSION = -1; + + [RubyConstant("FILTERED")] + public const int FILTERED = 1; + + [RubyConstant("HUFFMAN_ONLY")] + public const int HUFFMAN_ONLY = 2; + + [RubyConstant("DEFAULT_STRATEGY")] + public const int DEFAULT_STRATEGY = 0; + #endregion #region ZStream class @@ -531,12 +577,16 @@ private sealed class HuffmanTree { [RubyClass("GzipFile")] public class GZipFile { + protected IOWrapper/*!*/ _ioWrapper; protected List/*!*/ _inputBuffer; protected List/*!*/ _outputBuffer; protected int _outPos; protected int _inPos; + protected bool _isClosed; - public GZipFile() { + public GZipFile(IOWrapper/*!*/ ioWrapper) { + Debug.Assert(ioWrapper != null); + _ioWrapper = ioWrapper; _inputBuffer = new List(); _outputBuffer = new List(); _outPos = -1; @@ -551,6 +601,60 @@ public Error(string message) } // TODO: missing NoFooter, LengthError, CRCError constants + + [RubyMethod("wrap", RubyMethodAttributes.PublicSingleton)] + public static GZipFile/*!*/ Wrap(BinaryOpStorage/*!*/ newStorage, UnaryOpStorage/*!*/ closedStorage, UnaryOpStorage/*!*/ closeStorage, BlockParam block, RubyClass/*!*/ self, object io) { + var newSite = newStorage.GetCallSite("new"); + GZipFile gzipFile = (GZipFile)newSite.Target(newSite, self.Context, self, io); + + if (block == null) { + return gzipFile; + } + + try { + object blockResult; + block.Yield(gzipFile, out blockResult); + } finally { + CloseFile(closedStorage, closeStorage, self, gzipFile); + } + + return gzipFile; + } + + private static void CloseFile(UnaryOpStorage/*!*/ closedStorage, UnaryOpStorage/*!*/ closeStorage, RubyClass self, GZipFile gzipFile) { + var closedSite = closedStorage.GetCallSite("closed?"); + bool isClosed = Protocols.IsTrue(closedSite.Target(closedSite, self.Context, gzipFile)); + + if (!isClosed) { + var closeSite = closeStorage.GetCallSite("close"); + closeSite.Target(closeSite, self.Context, gzipFile); + } + } + + internal static void Close(CallWithoutArgsStorage/*!*/ closeStorage, RubyContext/*!*/ context, GZipFile/*!*/ self) { + if (self._ioWrapper.CanBeClosed) { + var site = closeStorage.GetCallSite("close"); + site.Target(site, context, self._ioWrapper.UnderlyingObject); + } + + self._isClosed = true; + } + + + [RubyMethod("closed?")] + public static bool IsClosed(GZipFile/*!*/ self) { + return self._isClosed; + } + + // comment() + // crc() + // level() + // mtime() + // orig_name() + // os_code() + // sync() + // sync = flag + // to_io } #endregion @@ -605,25 +709,18 @@ public class GZipReader : GZipFile { return ((b & (1 << bit)) == (1 << bit)); } - [RubyConstructor] - public static GZipReader/*!*/ Create(RubyClass/*!*/ self, [NotNull]RubyIO/*!*/ io) { - using (BinaryReader reader = io.GetBinaryReader()) { - return new GZipReader(reader); - } - } - [RubyConstructor] public static GZipReader/*!*/ Create(RespondToStorage/*!*/ respondToStorage, RubyClass/*!*/ self, object io) { - Stream stream = null; + IOWrapper stream = null; if (io != null) { stream = RubyIOOps.CreateIOWrapper(respondToStorage, self.Context, io, FileAccess.Read); } if (stream == null || !stream.CanRead) { - throw RubyExceptions.CreateTypeError("instance of IO needed"); + throw RubyExceptions.CreateMethodMissing(self.Context, io, "read"); } using (BinaryReader reader = new BinaryReader(stream)) { - return new GZipReader(reader); + return new GZipReader(stream, reader); } } @@ -663,8 +760,8 @@ public class GZipReader : GZipFile { return MutableString.CreateBinary(result); } - public GZipReader(BinaryReader/*!*/ reader) - : base() { + private GZipReader(IOWrapper/*!*/ ioWrapper, BinaryReader/*!*/ reader) + : base(ioWrapper) { // TODO: should all of this code be moved to open()? if (ReadUInt16LE(reader) != 0x8b1f) { @@ -723,20 +820,22 @@ public GZipReader(BinaryReader/*!*/ reader) } [RubyMethod("open", RubyMethodAttributes.PublicSingleton)] - public static GZipReader/*!*/ Open(RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ path) { - return Create(self, new RubyFile(self.Context, path.ConvertToString(), RubyFileMode.RDONLY)); + public static GZipReader/*!*/ Open(RespondToStorage/*!*/ respondToStorage, RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ path) { + return Create(respondToStorage, self, new RubyFile(self.Context, path.ConvertToString(), RubyFileMode.RDONLY)); } [RubyMethod("open", RubyMethodAttributes.PublicSingleton)] - public static object Open([NotNull]BlockParam/*!*/ block, RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ path) { - GZipReader reader = Open(self, path); + public static object Open(RespondToStorage/*!*/ respondToStorage, [NotNull]BlockParam/*!*/ block, RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ path) { + GZipReader reader = Open(respondToStorage, self, path); object blockResult; block.Yield(reader, out blockResult); return blockResult; } [RubyMethod("close")] - public static GZipReader/*!*/ Close(GZipReader/*!*/ self) { + [RubyMethod("finish")] + public static GZipReader/*!*/ Close(CallWithoutArgsStorage/*!*/ closeStorage, RubyContext/*!*/ context, GZipReader/*!*/ self) { + GZipFile.Close(closeStorage, context, self); return self; } } @@ -782,5 +881,110 @@ protected BufError(System.Runtime.Serialization.SerializationInfo info, System.R } #endregion + + #region Deflate class + + [RubyClass("Deflate")] + public class Deflate : ZStream { + + public Deflate() { + } + + [RubyMethod("deflate")] + public static MutableString/*!*/ DeflateString(Deflate/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ str, int flush) { + if (str.IsEmpty) { + throw new BufError("buffer error"); + } + + if (flush != FINISH) { + throw new NotImplementedError("flush can only be FINISH"); + } + + MemoryStream ms = new MemoryStream(); + // Use the newly created memory stream for the compressed data. + DeflateStream compressedzipStream = new DeflateStream(ms, CompressionMode.Compress, true); + byte[] inputData = str.ToByteArray(); + compressedzipStream.Write(inputData, 0, inputData.Length); + compressedzipStream.Close(); + return MutableString.CreateBinary(ms.GetBuffer()); + } + + [RubyMethod("deflate", RubyMethodAttributes.PublicSingleton)] + public static MutableString/*!*/ DeflateString(RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ str) { + return DeflateString(new Deflate(), str, FINISH); + } + } + + #endregion + + #region GzipWriter class + + [RubyClass("GzipWriter")] + public class GzipWriter : GZipFile { + private int _level; + private int _strategy; + private GZipStream/*!*/ _gzipStream; + + private GzipWriter(RespondToStorage/*!*/ respondToStorage, RubyContext/*!*/ context, IOWrapper/*!*/ ioWrapper, int level, int strategy) + : base(ioWrapper) { + _level = level; + _strategy = strategy; + _gzipStream = new GZipStream(ioWrapper, CompressionMode.Compress, true); + } + + [RubyConstructor] + public static GzipWriter/*!*/ Create( + RespondToStorage/*!*/ respondToStorage, + RubyClass/*!*/ self, + object io, + [DefaultParameterValue(0)]int level, + [DefaultParameterValue(0)]int strategy) { + + IOWrapper ioWrapper = RubyIOOps.CreateIOWrapper(respondToStorage, self.Context, io, FileAccess.Write); + if (ioWrapper == null || !ioWrapper.CanWrite) { + throw RubyExceptions.CreateMethodMissing(self.Context, io, "write"); + } + + return new GzipWriter(respondToStorage, self.Context, ioWrapper, level, strategy); + } + + // Zlib::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... } + + [RubyMethod("<<")] + public static GzipWriter Output(ConversionStorage/*!*/ tosStorage, RubyContext/*!*/ context, GzipWriter/*!*/ self, object value) { + Write(tosStorage, context, self, value); + return self; + } + + [RubyMethod("close")] + [RubyMethod("finish")] + public static void Close(CallWithoutArgsStorage/*!*/ closeStorage, RubyContext/*!*/ context, GzipWriter/*!*/ self) { + self._gzipStream.Close(); + self._ioWrapper.Flush(); + GZipFile.Close(closeStorage, context, self); + } + + // comment=(p1) + // flush(flush=nil) + // mtime=(p1) + // orig_name=(p1) + // pos() + // print(...) + // printf(...) + // putc(p1) + // puts(...) + // tell() + [RubyMethod("write")] + public static int Write(ConversionStorage/*!*/ tosStorage, RubyContext/*!*/ context, GzipWriter/*!*/ self, object obj) { + MutableString str = Protocols.ConvertToString(tosStorage, context, obj); + byte[] bytes = str.ToByteArray(); + + self._gzipStream.Write(bytes, 0, bytes.Length); + + return bytes.Length; + } + } + + #endregion } } diff --git a/Merlin/Main/Languages/Ruby/Ruby/Runtime/IOWrapper.cs b/Merlin/Main/Languages/Ruby/Ruby/Runtime/IOWrapper.cs index 35a8480efe..815a3ef04b 100644 --- a/Merlin/Main/Languages/Ruby/Ruby/Runtime/IOWrapper.cs +++ b/Merlin/Main/Languages/Ruby/Ruby/Runtime/IOWrapper.cs @@ -50,6 +50,7 @@ public class IOWrapper : Stream { private readonly bool _canRead; private readonly bool _canWrite; private readonly bool _canSeek; + private readonly bool _canBeClosed; private readonly byte[]/*!*/ _buffer; private int _writePos; private int _readPos; @@ -57,7 +58,7 @@ public class IOWrapper : Stream { private const int _bufferSize = 0x1000; - public IOWrapper(RubyContext/*!*/ context, object io, bool canRead, bool canWrite, bool canSeek) { + public IOWrapper(RubyContext/*!*/ context, object io, bool canRead, bool canWrite, bool canSeek, bool canBeClosed) { Assert.NotNull(context); _context = context; @@ -66,12 +67,17 @@ public class IOWrapper : Stream { _canRead = canRead; _canWrite = canWrite; _canSeek = canSeek; + _canBeClosed = canBeClosed; _buffer = new byte[_bufferSize]; _writePos = 0; _readPos = 0; _readLen = 0; } + public object UnderlyingObject { + get { return _obj; } + } + public override bool CanRead { get { return _canRead; } } @@ -80,6 +86,10 @@ public class IOWrapper : Stream { get { return _canSeek; } } + public bool CanBeClosed { + get { return _canBeClosed; } + } + public override bool CanWrite { get { return _canWrite; } } diff --git a/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs b/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs index d8b2a6efc6..e7b6587215 100644 --- a/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs +++ b/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyUtils.cs @@ -58,6 +58,18 @@ public class UnaryOpStorage : CallSiteStorage> { + public CallSite>/*!*/ GetCallSite(string/*!*/ methodName) { + return GetCallSite(methodName, 1); + } + } + + public class CallWithoutArgsStorage : CallSiteStorage> { + public CallSite>/*!*/ GetCallSite(string/*!*/ methodName) { + return GetCallSite(methodName, 0); + } + } + public class RespondToStorage : CallSiteStorage> { public CallSite>/*!*/ GetCallSite() { return GetCallSite("respond_to?", 1);