comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:aa4efef0f0b1
1 // Written in the D programming language
2 // www.digitalmars.com/d/
3
4 /// wraps zlib
5 module dynamin.lodepng.zlib_codec;
6 pragma(lib, "zlib");
7
8 version (Tango)
9 {
10 import czlib = tango.io.compress.c.zlib;
11 }
12 else
13 {
14 import czlib = etc.c.zlib;
15 }
16
17 import dynamin.lodepng.util;
18
19
20 // buffered decompression of zlib streams, avoiding GC provocation where possible
21 struct DecodeStream
22 {
23 // TODO: should be scope class for releasing zlib resources on scope exit
24
25 // constructor: initialize with target, will be resized as needed
26 static DecodeStream create(ref ubyte[] dest)
27 {
28 DecodeStream result;
29 result.dest = dest;
30
31 result.zlibStream.next_out = dest.ptr;
32 result.zlibStream.avail_out = dest.length;
33 result.zlibStream.avail_out = dest.length; //Z_BINARY
34 result.zlibStream.data_type = czlib.Z_BINARY;
35
36 return result;
37 }
38
39 ubyte[] opCall()
40 {
41 return dest;
42 }
43
44 void opCall(in ubyte[] input)
45 {
46 zlibStream.next_in = input.ptr;
47 zlibStream.avail_in = input.length;
48
49 if (!isInit)
50 {
51 isInit = true;
52 msg = czlib.inflateInit(&zlibStream);
53 if (msg)
54 {
55 czlib.inflateEnd(&zlibStream);
56 throw new Exception("");// TODO: toString(msg));
57 }
58 }
59
60 while(zlibStream.avail_in)
61 {
62 msg = czlib.inflate(&zlibStream, czlib.Z_NO_FLUSH);
63
64 if (msg == czlib.Z_STREAM_END)
65 {
66 czlib.inflateEnd(&zlibStream);
67 hasEnded = true;
68 dest.length = zlibStream.total_out;
69 return;
70 }
71 else if (msg != czlib.Z_OK)
72 {
73 czlib.inflateEnd(&zlibStream);
74 throw new Exception("");// TODO: toString(zlibStream.msg));
75 }
76 else if(zlibStream.avail_out == 0)
77 {
78 dest.length = dest.length * 2;
79 zlibStream.next_out = &dest[dest.length / 2];
80 zlibStream.avail_out = dest.length / 2;
81 }
82 }
83 }
84
85 bool isInit = false;
86 bool hasEnded = false;
87
88 private
89 {
90 ubyte[] dest;
91 int msg = 0;
92 czlib.z_stream zlibStream;
93 }
94 }
95
96 struct Encoder
97 {
98 static Encoder create(ubyte strategy = czlib.Z_RLE, uint clevel = 9)
99 {
100 Encoder result;
101 result.level = clevel;
102 result.strategy = strategy;
103 return result;
104 }
105 ubyte[] opCall(in ubyte[] source)
106 {
107 ubyte[] result;
108 return this.opCall(source, result);
109
110 }
111 ubyte[] opCall(in ubyte[] source, ref ubyte[] buffer)
112 {
113 if (source.length == 0)
114 {
115 buffer.length = 0;
116 return buffer;
117 }
118
119 buffer.length = source.length / 4;
120 czlib.z_stream stream;
121 stream.next_in = source.ptr;
122 stream.avail_in = source.length;
123 stream.next_out = buffer.ptr;
124 stream.avail_out = buffer.length;
125 stream.data_type = czlib.Z_BINARY;
126
127 czlib.deflateInit2(&stream, 9, czlib.Z_DEFLATED, 15, level, strategy);
128 auto msg = czlib.deflate(&stream, czlib.Z_FINISH);
129 while(msg != czlib.Z_STREAM_END)
130 {
131 buffer.length = buffer.length + buffer.length;
132 stream.next_out = &buffer[buffer.length / 2];
133 stream.avail_out = buffer.length / 2;
134 msg = czlib.deflate(&stream, czlib.Z_FINISH);
135 }
136
137 assert(msg == czlib.Z_STREAM_END);
138 buffer.length = stream.total_out;
139 czlib.deflateEnd(&stream);
140
141 return buffer;
142 }
143
144 private ubyte strategy = czlib.Z_RLE;
145 private ubyte level = 9;
146 }