diff dynamin/lodepng/zlib_codec.d @ 0:aa4efef0f0b1

Initial commit of code.
author Jordan Miner <jminer7@gmail.com>
date Mon, 15 Jun 2009 22:10:48 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/lodepng/zlib_codec.d	Mon Jun 15 22:10:48 2009 -0500
@@ -0,0 +1,146 @@
+// Written in the D programming language
+// www.digitalmars.com/d/
+
+/// wraps zlib
+module dynamin.lodepng.zlib_codec;
+pragma(lib, "zlib");
+
+version (Tango)
+{
+    import czlib = tango.io.compress.c.zlib;
+}
+else
+{
+    import czlib = etc.c.zlib;
+}
+
+import dynamin.lodepng.util;
+
+
+// buffered decompression of zlib streams, avoiding GC provocation where possible
+struct DecodeStream
+{
+    // TODO: should be scope class for releasing zlib resources on scope exit
+
+    // constructor: initialize with target, will be resized as needed
+    static DecodeStream create(ref ubyte[] dest)
+    {
+        DecodeStream result;
+        result.dest = dest;
+
+        result.zlibStream.next_out = dest.ptr;
+        result.zlibStream.avail_out = dest.length;
+        result.zlibStream.avail_out = dest.length; //Z_BINARY
+        result.zlibStream.data_type = czlib.Z_BINARY;
+
+        return result;
+    }
+
+    ubyte[] opCall()
+    {
+        return dest;
+    }
+
+    void opCall(in ubyte[] input)
+    {
+        zlibStream.next_in = input.ptr;
+        zlibStream.avail_in = input.length;
+
+        if (!isInit)
+        {
+            isInit = true;
+            msg = czlib.inflateInit(&zlibStream);
+	        if (msg)
+	        {
+	            czlib.inflateEnd(&zlibStream);
+	            throw new Exception("");// TODO: toString(msg));
+	        }
+        }
+
+        while(zlibStream.avail_in)
+        {
+            msg = czlib.inflate(&zlibStream, czlib.Z_NO_FLUSH);
+
+            if (msg == czlib.Z_STREAM_END)
+            {
+                czlib.inflateEnd(&zlibStream);
+                hasEnded = true;
+                dest.length = zlibStream.total_out;
+                return;
+            }
+            else if (msg != czlib.Z_OK)
+            {
+                czlib.inflateEnd(&zlibStream);
+                throw new Exception("");// TODO: toString(zlibStream.msg));
+            }
+            else if(zlibStream.avail_out == 0)
+            {
+                dest.length = dest.length * 2;
+                zlibStream.next_out = &dest[dest.length / 2];
+                zlibStream.avail_out = dest.length / 2;
+            }
+        }
+    }
+
+    bool isInit = false;
+    bool hasEnded = false;
+
+    private
+	{
+	    ubyte[] dest;
+	    int msg = 0;
+	    czlib.z_stream zlibStream;
+	}
+}
+
+struct Encoder
+{
+    static Encoder create(ubyte strategy = czlib.Z_RLE, uint clevel = 9)
+    {
+        Encoder result;
+        result.level = clevel;
+        result.strategy = strategy;
+        return result;
+    }
+    ubyte[] opCall(in ubyte[] source)
+    {
+        ubyte[] result;
+        return this.opCall(source, result);
+
+    }
+    ubyte[] opCall(in ubyte[] source, ref ubyte[] buffer)
+    {
+        if (source.length == 0)
+        {
+            buffer.length = 0;
+            return buffer;
+        }
+
+        buffer.length = source.length / 4;
+        czlib.z_stream stream;
+        stream.next_in = source.ptr;
+        stream.avail_in = source.length;
+        stream.next_out = buffer.ptr;
+        stream.avail_out = buffer.length;
+        stream.data_type = czlib.Z_BINARY;
+
+        czlib.deflateInit2(&stream, 9, czlib.Z_DEFLATED, 15, level, strategy);
+        auto msg = czlib.deflate(&stream, czlib.Z_FINISH);
+        while(msg != czlib.Z_STREAM_END)
+        {
+            buffer.length = buffer.length + buffer.length;
+            stream.next_out = &buffer[buffer.length / 2];
+            stream.avail_out = buffer.length / 2;
+            msg = czlib.deflate(&stream, czlib.Z_FINISH);
+        }
+
+        assert(msg == czlib.Z_STREAM_END);
+        buffer.length = stream.total_out;
+        czlib.deflateEnd(&stream);
+
+        return buffer;
+    }
+
+    private ubyte strategy = czlib.Z_RLE;
+    private ubyte level = 9;
+}