1
2
3
4
5
6 using System;
7 using System.IO;
8
9 namespace System.IO.Compression
10 {
11 public enum CompressionMode : int
12 {
13 compress = 0, decompress = 1
14 }
15
16 public const int defaultDeflateCompressionLevel = -1;
17 public const int noDeflateCompression = 0;
18 public const int fastestDeflateCompression = 1;
19 public const int optimalDeflateCompression = 9;
20 public const int Z_NO_FLUSH = 0;
21 public const int Z_STREAM_END = 1;
22 public const int Z_FINISH = 4;
23 public const int Z_STREAM_ERROR = -2;
24
25 public nothrow string ExpandDeflateError(const string& message, int errorCode)
26 {
27 string expandedMessage = message;
28 expandedMessage.Append(" error ").Append(RtRetvalStrZlib(errorCode)).Append(" code ").Append(ToString(errorCode));
29 return expandedMessage;
30 }
31
32 public class DeflateException : Exception
33 {
34 public nothrow DeflateException(const string& message_, int errorCode_) : base(ExpandDeflateError(message_, errorCode_)), errorCode(errorCode_)
35 {
36 }
37 public inline nothrow int ErrorCode() const
38 {
39 return errorCode;
40 }
41 private int errorCode;
42 }
43
44 public class DeflateStream : ByteStream
45 {
46 public DeflateStream(const SharedPtr<ByteStream>& underlyingStream_, int compressionLevel_) : this(underlyingStream_, compressionLevel_, 16384)
47 {
48 }
49 public DeflateStream(const SharedPtr<ByteStream>& underlyingStream_, int compressionLevel_, long bufferSize_) :
50 underlyingStream(underlyingStream_), mode(CompressionMode.compress), handle(null), inAvail(0u), bufferSize(bufferSize_),
51 in(bufferSize), outAvail(0u), outPos(0), outHave(0u), endOfInput(false), endOfStream(false), out(bufferSize)
52 {
53 int ret = RtInitZlib(mode, compressionLevel_, &handle);
54 if (ret < 0)
55 {
56 throw DeflateException("Could not create DeflateStream", ret);
57 }
58 }
59 public DeflateStream(const SharedPtr<ByteStream>& underlyingStream_, CompressionMode mode_) : this(underlyingStream_, mode_, 16384)
60 {
61 }
62 public DeflateStream(const SharedPtr<ByteStream>& underlyingStream_, CompressionMode mode_, long bufferSize_) :
63 underlyingStream(underlyingStream_), mode(mode_), handle(null), inAvail(0u), bufferSize(bufferSize_),
64 in(bufferSize), outAvail(0u), outPos(0), outHave(0u), endOfInput(false), endOfStream(false), out(bufferSize)
65 {
66 int ret = RtInitZlib(mode, defaultDeflateCompressionLevel, &handle);
67 if (ret < 0)
68 {
69 throw DeflateException("Could not create DeflateStream", ret);
70 }
71 }
72 suppress DeflateStream(DeflateStream&&);
73 suppress void operator=(DeflateStream&&);
74 suppress DeflateStream(const DeflateStream&);
75 suppress void operator=(const DeflateStream&);
76 public inline nothrow CompressionMode Mode() const
77 {
78 return mode;
79 }
80 public ~DeflateStream()
81 {
82 if (handle != null)
83 {
84 try
85 {
86 if (mode == CompressionMode.compress)
87 {
88 Finish();
89 }
90 }
91 catch (const Exception& ex)
92 {
93
94 }
95 RtDoneZlib(mode, handle);
96 }
97 }
98 public override int ReadByte()
99 {
100 byte x = 0u;
101 long bytesRead = this->Read(&x, 1);
102 if (bytesRead == 0)
103 {
104 return -1;
105 }
106 return x;
107 }
108 public override long Read(byte* buf, long count)
109 {
110 if (mode != CompressionMode.decompress)
111 {
112 throw DeflateException("Cannot read from DeflateStream in CompressionMode.compress", Z_STREAM_ERROR);
113 }
114 long bytesRead = 0;
115 do
116 {
117 if (inAvail == 0u && !endOfInput)
118 {
119 inAvail = cast<uint>(underlyingStream->Read(cast<byte*>(in.Mem()), bufferSize));
120 if (inAvail == 0u)
121 {
122 endOfInput = true;
123 }
124 RtSetInputZlib(in.Mem(), inAvail, handle);
125 }
126 do
127 {
128 if (outHave == 0u && !endOfStream)
129 {
130 int ret = RtInflateZlib(out.Mem(), cast<uint>(bufferSize), &outHave, &outAvail, &inAvail, handle);
131 if (ret < 0)
132 {
133 throw DeflateException("DeflateStream could not decompress", ret);
134 }
135 if (ret == Z_STREAM_END)
136 {
137 endOfStream = true;
138 }
139 outPos = 0;
140 }
141 while (count > 0 && outHave > 0u)
142 {
143 *buf++ = out[outPos++];
144 --count;
145 --outHave;
146 ++bytesRead;
147 }
148 }
149 while (count > 0 && outAvail == 0u);
150 }
151 while (count > 0 && !endOfStream && !endOfInput);
152 if (endOfInput && !endOfStream)
153 {
154 throw DeflateException("DeflateStream unexpected end of input", Z_STREAM_ERROR);
155 }
156 return bytesRead;
157 }
158 public override void Write(byte x)
159 {
160 this->Write(&x, 1);
161 }
162 public override void Write(byte* buf, long count)
163 {
164 if (mode != CompressionMode.compress)
165 {
166 throw DeflateException("Cannot write to DeflateStream in CompressionMode.decompress", Z_STREAM_ERROR);
167 }
168 while (count > 0)
169 {
170 byte* inP = cast<byte*>(in.Mem());
171 inAvail = 0u;
172 while (count > 0 && inAvail < cast<uint>(bufferSize))
173 {
174 *inP++ = *buf++;
175 --count;
176 ++inAvail;
177 }
178 RtSetInputZlib(in.Mem(), inAvail, handle);
179 do
180 {
181 uint have = 0u;
182 int ret = RtDeflateZlib(out.Mem(), cast<uint>(bufferSize), &have, &outAvail, handle, Z_NO_FLUSH);
183 if (ret < 0)
184 {
185 throw DeflateException("DeflateStream could not compress", ret);
186 }
187 underlyingStream->Write(cast<byte*>(out.Mem()), cast<long>(have));
188 }
189 while (outAvail == 0u);
190 }
191 }
192 private void Finish()
193 {
194 do
195 {
196 uint have = 0u;
197 int ret = RtDeflateZlib(out.Mem(), cast<uint>(bufferSize), &have, &outAvail, handle, Z_FINISH);
198 if (ret < 0)
199 {
200 throw DeflateException("DeflateStream could not compress", ret);
201 }
202 underlyingStream->Write(cast<byte*>(out.Mem()), cast<long>(have));
203 }
204 while (outAvail == 0);
205 }
206 private SharedPtr<ByteStream> underlyingStream;
207 private CompressionMode mode;
208 private long bufferSize;
209 private uint inAvail;
210 private IOBuffer in;
211 private uint outAvail;
212 private long outPos;
213 private uint outHave;
214 private bool endOfInput;
215 private bool endOfStream;
216 private IOBuffer out;
217 private void* handle;
218 }
219 }