Permalink
Browse files

Add primitive Zlib::GzipWriter

  • Loading branch information...
1 parent 0869a6e commit 2b18de29d078f48fe666f609cadc130108bab549 @drbrain drbrain committed Dec 7, 2007
Showing with 216 additions and 1 deletion.
  1. +2 −1 .gitignore
  2. +15 −0 Rakefile
  3. +5 −0 lib/ext/zlib/build.rb
  4. +30 −0 lib/ext/zlib/zlib.c
  5. +164 −0 lib/zlib.rb.in
View
@@ -34,13 +34,14 @@ runtime/pristine*
attic/externals/syd-parser/pkg
-
kernel/.load_order.txt
kernel/core/dir.rb
kernel/core/dir_entry.rb
+
lib/etc.rb
lib/kernel.rb
lib/rbconfig.rb
+lib/zlib.rb
native/sexp
native/translation
View
@@ -256,6 +256,10 @@ Rake::StructGeneratorTask.new do |t|
t.dest = "lib/etc.rb"
end
+Rake::StructGeneratorTask.new do |t|
+ t.dest = 'lib/zlib.rb'
+end
+
AllPreCompiled = Core.output + Bootstrap.output + Platform.output + Compiler.output
AllPreCompiled << "runtime/loader.rbc"
@@ -508,6 +512,7 @@ task :extensions => %w[
extension:digest_md5
extension:fcntl
extension:syck
+ extension:zlib
]
namespace :extension do
@@ -544,6 +549,16 @@ namespace :extension do
sh "./shotgun/rubinius compile lib/ext/syck"
end
+ task :zlib => %W[lib/ext/zlib/zlib.#{$dlext} lib/zlib.rb]
+
+ file "lib/ext/zlib/zlib.#{$dlext}" => FileList[
+ 'shotgun/lib/subtend/ruby.h',
+ 'lib/ext/zlib/build.rb',
+ 'lib/ext/zlib/*.c'
+ ] do
+ sh "./shotgun/rubinius compile lib/ext/zlib"
+ end
+
end
desc "Build task for CruiseControl"
@@ -0,0 +1,5 @@
+extension do |e|
+ e.name 'zlib'
+ e.files '*.c'
+ e.includes '.'
+end
View
@@ -0,0 +1,30 @@
+#include "zlib.h"
+#include "ruby.h"
+#include <stdio.h>
+
+z_streamp rbx_Zlib_z_stream_Alloc() {
+ z_streamp strm;
+
+ strm = (z_streamp)calloc(1, sizeof(z_stream));
+ strm->next_in = Z_NULL;
+ strm->opaque = Z_NULL;
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+
+ return strm;
+}
+
+int rbx_Zlib_deflateInit2(z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy) {
+ return deflateInit2(strm, level, method, windowBits, memLevel, strategy);
+}
+
+Init_zlib() {
+ VALUE mZlib;
+
+ mZlib = rb_define_module("Zlib");
+
+ rb_define_const(mZlib, "ZLIB_VERSION", rb_str_new2(ZLIB_VERSION));
+ rb_define_const(mZlib, "STREAM_SIZE", INT2NUM(sizeof(z_stream)));
+}
+
View
@@ -0,0 +1,164 @@
+require 'ext/zlib/zlib'
+
+module Zlib
+
+ class Stream < FFI::Struct
+ @@@
+ name "struct z_stream_s"
+ include "zlib.h"
+ field :next_in, :string
+ field :avail_in, :uint
+ field :total_in, :ulong
+ field :next_out, :string
+ field :avail_out, :uint
+ field :total_out, :ulong
+ field :msg, :string
+ @@@
+ end
+
+ attach_function 'rbx_Zlib_z_stream_Alloc', :z_stream_Alloc, [], :pointer
+
+ attach_function 'rbx_Zlib_deflateInit2', :deflateInit2, [
+ :pointer, # z_streamp strm
+ :int, # int level
+ :int, # int method
+ :int, # int windowBits
+ :int, # int memLeel
+ :int, # int strategy
+ ], :int
+
+ attach_function 'deflate', :deflate, [:pointer, :int], :int
+
+ attach_function 'deflateEnd', :deflateEnd, [:pointer], :int
+
+ #--
+ # From zlib.h
+ #++
+
+ NO_FLUSH = 0
+ PARTIAL_FLUSH = 1
+ SYNC_FLUSH = 2
+ FULL_FLUSH = 3
+ FINISH = 4
+ BLOCK = 5
+
+ OK = 0
+ STREAM_END = 1
+ NEED_DICT = 2
+ ERRNO = -1
+ STREAM_ERROR = -2
+ DATA_ERROR = -3
+ MEM_ERROR = -4
+ BUF_ERROR = -5
+ VERSION_ERROR = -6
+
+ NO_COMPRESSION = 0
+ BEST_SPEED = 1
+ BEST_COMPRESSION = 9
+ DEFAULT_COMPRESSION = -1
+
+ FILTERED = 1
+ HUFFMAN_ONLY = 2
+ RLE = 3
+ FIXED = 4
+ DEFAULT_STRATEGY = 0
+
+ DEFLATED = 8
+
+ #--
+ # HACK from zconf.h
+ #++
+
+ MAX_WBITS = 15
+ MAX_MEM_LEVEL = 9
+ DEF_MEM_LEVEL = 9
+
+ #--
+ # HACK from zlib.c
+ #--
+
+ GZ_EXTRAFLAG_FAST = 0x4
+ GZ_EXTRAFLAG_SLOW = 0x2
+
+ class Deflate
+ def self.deflate(data)
+ Compression::ZLib.new.deflate data
+ end
+ end
+
+ class GzipWriter # HACK use a buffer class
+
+ CHUNK = 1024
+
+ def initialize(io, level = Zlib::DEFAULT_COMPRESSION,
+ strategy = Zlib::DEFAULT_STRATEGY)
+ @stream_p = Zlib.z_stream_Alloc
+ @stream = Zlib::Stream.new @stream_p
+
+ @level = level
+ @method = Zlib::DEFLATED
+ @window_bits = Zlib::MAX_WBITS + 16 # gzip header
+ @mem_level = Zlib::DEF_MEM_LEVEL
+ @strategy = strategy
+
+ err = Zlib.deflateInit2(@stream_p, @level, @method, @window_bits,
+ @mem_level, @strategy)
+
+ err == 0
+ raise "Zlib error #{err}" unless err == Zlib::OK # HACK
+
+ @io = io
+
+ @buffer = ''
+ end
+
+ def close
+ finish
+ @io.close
+ nil
+ end
+
+ def finish
+ until @buffer.empty? do
+ chunk = @buffer.slice! 0, CHUNK
+ flush = @buffer.empty? ? Zlib::NO_FLUSH : Zlib::FINISH
+
+ @stream[:next_in] = chunk
+ @stream[:avail_in] = chunk.length
+
+ @stream[:next_out] = "\000" * CHUNK
+ @stream[:avail_out] = CHUNK
+
+ err = Zlib.deflate @stream_p, flush
+
+ if err == Zlib::OK or err == Zlib::STREAM_END then
+ @io.write @stream[:next_out][0, @stream[:avail_out]]
+ else
+ raise "Zlib error #{err}"
+ end
+ end
+
+ Zlib.deflateEnd @stream_p
+
+ @io
+ end
+
+ def flush
+ true
+ end
+
+ def write(data)
+ @buffer << data
+ data.length
+ end
+
+ end
+
+ class Inflate
+ def self.inflate(data)
+ Compression::ZLib.new.inflate data
+ end
+ end
+
+end
+

0 comments on commit 2b18de2

Please sign in to comment.