Mercurial > repos > SharpZipLib
comparison Zip/Compression/Streams/InflaterInputStream.cs @ 1:94e25b786321
Re #311: can't read ZIP file packed by Linux app Archive Manager/File Roller
Initial commit of clean SharpZipLib 0860 source. Only change is build paths.
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 30 Oct 2010 14:03:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d16ef17fa7bb | 1:94e25b786321 |
---|---|
1 // InflaterInputStream.cs | |
2 // | |
3 // Copyright (C) 2001 Mike Krueger | |
4 // Copyright (C) 2004 John Reilly | |
5 // | |
6 // This file was translated from java, it was part of the GNU Classpath | |
7 // Copyright (C) 2001 Free Software Foundation, Inc. | |
8 // | |
9 // This program is free software; you can redistribute it and/or | |
10 // modify it under the terms of the GNU General Public License | |
11 // as published by the Free Software Foundation; either version 2 | |
12 // of the License, or (at your option) any later version. | |
13 // | |
14 // This program is distributed in the hope that it will be useful, | |
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 // GNU General Public License for more details. | |
18 // | |
19 // You should have received a copy of the GNU General Public License | |
20 // along with this program; if not, write to the Free Software | |
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 // | |
23 // Linking this library statically or dynamically with other modules is | |
24 // making a combined work based on this library. Thus, the terms and | |
25 // conditions of the GNU General Public License cover the whole | |
26 // combination. | |
27 // | |
28 // As a special exception, the copyright holders of this library give you | |
29 // permission to link this library with independent modules to produce an | |
30 // executable, regardless of the license terms of these independent | |
31 // modules, and to copy and distribute the resulting executable under | |
32 // terms of your choice, provided that you also meet, for each linked | |
33 // independent module, the terms and conditions of the license of that | |
34 // module. An independent module is a module which is not derived from | |
35 // or based on this library. If you modify this library, you may extend | |
36 // this exception to your version of the library, but you are not | |
37 // obligated to do so. If you do not wish to do so, delete this | |
38 // exception statement from your version. | |
39 | |
40 // HISTORY | |
41 // 11-08-2009 GeoffHart T9121 Added Multi-member gzip support | |
42 | |
43 using System; | |
44 using System.IO; | |
45 | |
46 #if !NETCF_1_0 | |
47 using System.Security.Cryptography; | |
48 #endif | |
49 | |
50 namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams | |
51 { | |
52 | |
53 /// <summary> | |
54 /// An input buffer customised for use by <see cref="InflaterInputStream"/> | |
55 /// </summary> | |
56 /// <remarks> | |
57 /// The buffer supports decryption of incoming data. | |
58 /// </remarks> | |
59 public class InflaterInputBuffer | |
60 { | |
61 #region Constructors | |
62 /// <summary> | |
63 /// Initialise a new instance of <see cref="InflaterInputBuffer"/> with a default buffer size | |
64 /// </summary> | |
65 /// <param name="stream">The stream to buffer.</param> | |
66 public InflaterInputBuffer(Stream stream) : this(stream , 4096) | |
67 { | |
68 } | |
69 | |
70 /// <summary> | |
71 /// Initialise a new instance of <see cref="InflaterInputBuffer"/> | |
72 /// </summary> | |
73 /// <param name="stream">The stream to buffer.</param> | |
74 /// <param name="bufferSize">The size to use for the buffer</param> | |
75 /// <remarks>A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB.</remarks> | |
76 public InflaterInputBuffer(Stream stream, int bufferSize) | |
77 { | |
78 inputStream = stream; | |
79 if ( bufferSize < 1024 ) { | |
80 bufferSize = 1024; | |
81 } | |
82 rawData = new byte[bufferSize]; | |
83 clearText = rawData; | |
84 } | |
85 #endregion | |
86 | |
87 /// <summary> | |
88 /// Get the length of bytes bytes in the <see cref="RawData"/> | |
89 /// </summary> | |
90 public int RawLength | |
91 { | |
92 get { | |
93 return rawLength; | |
94 } | |
95 } | |
96 | |
97 /// <summary> | |
98 /// Get the contents of the raw data buffer. | |
99 /// </summary> | |
100 /// <remarks>This may contain encrypted data.</remarks> | |
101 public byte[] RawData | |
102 { | |
103 get { | |
104 return rawData; | |
105 } | |
106 } | |
107 | |
108 /// <summary> | |
109 /// Get the number of useable bytes in <see cref="ClearText"/> | |
110 /// </summary> | |
111 public int ClearTextLength | |
112 { | |
113 get { | |
114 return clearTextLength; | |
115 } | |
116 } | |
117 | |
118 /// <summary> | |
119 /// Get the contents of the clear text buffer. | |
120 /// </summary> | |
121 public byte[] ClearText | |
122 { | |
123 get { | |
124 return clearText; | |
125 } | |
126 } | |
127 | |
128 /// <summary> | |
129 /// Get/set the number of bytes available | |
130 /// </summary> | |
131 public int Available | |
132 { | |
133 get { return available; } | |
134 set { available = value; } | |
135 } | |
136 | |
137 /// <summary> | |
138 /// Call <see cref="Inflater.SetInput(byte[], int, int)"/> passing the current clear text buffer contents. | |
139 /// </summary> | |
140 /// <param name="inflater">The inflater to set input for.</param> | |
141 public void SetInflaterInput(Inflater inflater) | |
142 { | |
143 if ( available > 0 ) { | |
144 inflater.SetInput(clearText, clearTextLength - available, available); | |
145 available = 0; | |
146 } | |
147 } | |
148 | |
149 /// <summary> | |
150 /// Fill the buffer from the underlying input stream. | |
151 /// </summary> | |
152 public void Fill() | |
153 { | |
154 rawLength = 0; | |
155 int toRead = rawData.Length; | |
156 | |
157 while (toRead > 0) { | |
158 int count = inputStream.Read(rawData, rawLength, toRead); | |
159 if ( count <= 0 ) { | |
160 break; | |
161 } | |
162 rawLength += count; | |
163 toRead -= count; | |
164 } | |
165 | |
166 #if !NETCF_1_0 | |
167 if ( cryptoTransform != null ) { | |
168 clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0); | |
169 } | |
170 else | |
171 #endif | |
172 { | |
173 clearTextLength = rawLength; | |
174 } | |
175 | |
176 available = clearTextLength; | |
177 } | |
178 | |
179 /// <summary> | |
180 /// Read a buffer directly from the input stream | |
181 /// </summary> | |
182 /// <param name="buffer">The buffer to fill</param> | |
183 /// <returns>Returns the number of bytes read.</returns> | |
184 public int ReadRawBuffer(byte[] buffer) | |
185 { | |
186 return ReadRawBuffer(buffer, 0, buffer.Length); | |
187 } | |
188 | |
189 /// <summary> | |
190 /// Read a buffer directly from the input stream | |
191 /// </summary> | |
192 /// <param name="outBuffer">The buffer to read into</param> | |
193 /// <param name="offset">The offset to start reading data into.</param> | |
194 /// <param name="length">The number of bytes to read.</param> | |
195 /// <returns>Returns the number of bytes read.</returns> | |
196 public int ReadRawBuffer(byte[] outBuffer, int offset, int length) | |
197 { | |
198 if ( length < 0 ) { | |
199 throw new ArgumentOutOfRangeException("length"); | |
200 } | |
201 | |
202 int currentOffset = offset; | |
203 int currentLength = length; | |
204 | |
205 while ( currentLength > 0 ) { | |
206 if ( available <= 0 ) { | |
207 Fill(); | |
208 if (available <= 0) { | |
209 return 0; | |
210 } | |
211 } | |
212 int toCopy = Math.Min(currentLength, available); | |
213 System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy); | |
214 currentOffset += toCopy; | |
215 currentLength -= toCopy; | |
216 available -= toCopy; | |
217 } | |
218 return length; | |
219 } | |
220 | |
221 /// <summary> | |
222 /// Read clear text data from the input stream. | |
223 /// </summary> | |
224 /// <param name="outBuffer">The buffer to add data to.</param> | |
225 /// <param name="offset">The offset to start adding data at.</param> | |
226 /// <param name="length">The number of bytes to read.</param> | |
227 /// <returns>Returns the number of bytes actually read.</returns> | |
228 public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length) | |
229 { | |
230 if ( length < 0 ) { | |
231 throw new ArgumentOutOfRangeException("length"); | |
232 } | |
233 | |
234 int currentOffset = offset; | |
235 int currentLength = length; | |
236 | |
237 while ( currentLength > 0 ) { | |
238 if ( available <= 0 ) { | |
239 Fill(); | |
240 if (available <= 0) { | |
241 return 0; | |
242 } | |
243 } | |
244 | |
245 int toCopy = Math.Min(currentLength, available); | |
246 Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy); | |
247 currentOffset += toCopy; | |
248 currentLength -= toCopy; | |
249 available -= toCopy; | |
250 } | |
251 return length; | |
252 } | |
253 | |
254 /// <summary> | |
255 /// Read a <see cref="byte"/> from the input stream. | |
256 /// </summary> | |
257 /// <returns>Returns the byte read.</returns> | |
258 public int ReadLeByte() | |
259 { | |
260 if (available <= 0) { | |
261 Fill(); | |
262 if (available <= 0) { | |
263 throw new ZipException("EOF in header"); | |
264 } | |
265 } | |
266 byte result = rawData[rawLength - available]; | |
267 available -= 1; | |
268 return result; | |
269 } | |
270 | |
271 /// <summary> | |
272 /// Read an <see cref="short"/> in little endian byte order. | |
273 /// </summary> | |
274 /// <returns>The short value read case to an int.</returns> | |
275 public int ReadLeShort() | |
276 { | |
277 return ReadLeByte() | (ReadLeByte() << 8); | |
278 } | |
279 | |
280 /// <summary> | |
281 /// Read an <see cref="int"/> in little endian byte order. | |
282 /// </summary> | |
283 /// <returns>The int value read.</returns> | |
284 public int ReadLeInt() | |
285 { | |
286 return ReadLeShort() | (ReadLeShort() << 16); | |
287 } | |
288 | |
289 /// <summary> | |
290 /// Read a <see cref="long"/> in little endian byte order. | |
291 /// </summary> | |
292 /// <returns>The long value read.</returns> | |
293 public long ReadLeLong() | |
294 { | |
295 return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); | |
296 } | |
297 | |
298 #if !NETCF_1_0 | |
299 /// <summary> | |
300 /// Get/set the <see cref="ICryptoTransform"/> to apply to any data. | |
301 /// </summary> | |
302 /// <remarks>Set this value to null to have no transform applied.</remarks> | |
303 public ICryptoTransform CryptoTransform | |
304 { | |
305 set { | |
306 cryptoTransform = value; | |
307 if ( cryptoTransform != null ) { | |
308 if ( rawData == clearText ) { | |
309 if ( internalClearText == null ) { | |
310 internalClearText = new byte[rawData.Length]; | |
311 } | |
312 clearText = internalClearText; | |
313 } | |
314 clearTextLength = rawLength; | |
315 if ( available > 0 ) { | |
316 cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available); | |
317 } | |
318 } else { | |
319 clearText = rawData; | |
320 clearTextLength = rawLength; | |
321 } | |
322 } | |
323 } | |
324 #endif | |
325 | |
326 #region Instance Fields | |
327 int rawLength; | |
328 byte[] rawData; | |
329 | |
330 int clearTextLength; | |
331 byte[] clearText; | |
332 #if !NETCF_1_0 | |
333 byte[] internalClearText; | |
334 #endif | |
335 | |
336 int available; | |
337 | |
338 #if !NETCF_1_0 | |
339 ICryptoTransform cryptoTransform; | |
340 #endif | |
341 Stream inputStream; | |
342 #endregion | |
343 } | |
344 | |
345 /// <summary> | |
346 /// This filter stream is used to decompress data compressed using the "deflate" | |
347 /// format. The "deflate" format is described in RFC 1951. | |
348 /// | |
349 /// This stream may form the basis for other decompression filters, such | |
350 /// as the <see cref="ICSharpCode.SharpZipLib.GZip.GZipInputStream">GZipInputStream</see>. | |
351 /// | |
352 /// Author of the original java version : John Leuner. | |
353 /// </summary> | |
354 public class InflaterInputStream : Stream | |
355 { | |
356 #region Constructors | |
357 /// <summary> | |
358 /// Create an InflaterInputStream with the default decompressor | |
359 /// and a default buffer size of 4KB. | |
360 /// </summary> | |
361 /// <param name = "baseInputStream"> | |
362 /// The InputStream to read bytes from | |
363 /// </param> | |
364 public InflaterInputStream(Stream baseInputStream) | |
365 : this(baseInputStream, new Inflater(), 4096) | |
366 { | |
367 } | |
368 | |
369 /// <summary> | |
370 /// Create an InflaterInputStream with the specified decompressor | |
371 /// and a default buffer size of 4KB. | |
372 /// </summary> | |
373 /// <param name = "baseInputStream"> | |
374 /// The source of input data | |
375 /// </param> | |
376 /// <param name = "inf"> | |
377 /// The decompressor used to decompress data read from baseInputStream | |
378 /// </param> | |
379 public InflaterInputStream(Stream baseInputStream, Inflater inf) | |
380 : this(baseInputStream, inf, 4096) | |
381 { | |
382 } | |
383 | |
384 /// <summary> | |
385 /// Create an InflaterInputStream with the specified decompressor | |
386 /// and the specified buffer size. | |
387 /// </summary> | |
388 /// <param name = "baseInputStream"> | |
389 /// The InputStream to read bytes from | |
390 /// </param> | |
391 /// <param name = "inflater"> | |
392 /// The decompressor to use | |
393 /// </param> | |
394 /// <param name = "bufferSize"> | |
395 /// Size of the buffer to use | |
396 /// </param> | |
397 public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) | |
398 { | |
399 if (baseInputStream == null) { | |
400 throw new ArgumentNullException("baseInputStream"); | |
401 } | |
402 | |
403 if (inflater == null) { | |
404 throw new ArgumentNullException("inflater"); | |
405 } | |
406 | |
407 if (bufferSize <= 0) { | |
408 throw new ArgumentOutOfRangeException("bufferSize"); | |
409 } | |
410 | |
411 this.baseInputStream = baseInputStream; | |
412 this.inf = inflater; | |
413 | |
414 inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize); | |
415 } | |
416 | |
417 #endregion | |
418 | |
419 /// <summary> | |
420 /// Get/set flag indicating ownership of underlying stream. | |
421 /// When the flag is true <see cref="Close"/> will close the underlying stream also. | |
422 /// </summary> | |
423 /// <remarks> | |
424 /// The default value is true. | |
425 /// </remarks> | |
426 public bool IsStreamOwner | |
427 { | |
428 get { return isStreamOwner; } | |
429 set { isStreamOwner = value; } | |
430 } | |
431 | |
432 /// <summary> | |
433 /// Skip specified number of bytes of uncompressed data | |
434 /// </summary> | |
435 /// <param name ="count"> | |
436 /// Number of bytes to skip | |
437 /// </param> | |
438 /// <returns> | |
439 /// The number of bytes skipped, zero if the end of | |
440 /// stream has been reached | |
441 /// </returns> | |
442 /// <exception cref="ArgumentOutOfRangeException"> | |
443 /// <paramref name="count">The number of bytes</paramref> to skip is less than or equal to zero. | |
444 /// </exception> | |
445 public long Skip(long count) | |
446 { | |
447 if (count <= 0) { | |
448 throw new ArgumentOutOfRangeException("count"); | |
449 } | |
450 | |
451 // v0.80 Skip by seeking if underlying stream supports it... | |
452 if (baseInputStream.CanSeek) { | |
453 baseInputStream.Seek(count, SeekOrigin.Current); | |
454 return count; | |
455 } | |
456 else { | |
457 int length = 2048; | |
458 if (count < length) { | |
459 length = (int) count; | |
460 } | |
461 | |
462 byte[] tmp = new byte[length]; | |
463 int readCount = 1; | |
464 long toSkip = count; | |
465 | |
466 while ((toSkip > 0) && (readCount > 0) ) { | |
467 if (toSkip < length) { | |
468 length = (int)toSkip; | |
469 } | |
470 | |
471 readCount = baseInputStream.Read(tmp, 0, length); | |
472 toSkip -= readCount; | |
473 } | |
474 | |
475 return count - toSkip; | |
476 } | |
477 } | |
478 | |
479 /// <summary> | |
480 /// Clear any cryptographic state. | |
481 /// </summary> | |
482 protected void StopDecrypting() | |
483 { | |
484 #if !NETCF_1_0 | |
485 inputBuffer.CryptoTransform = null; | |
486 #endif | |
487 } | |
488 | |
489 /// <summary> | |
490 /// Returns 0 once the end of the stream (EOF) has been reached. | |
491 /// Otherwise returns 1. | |
492 /// </summary> | |
493 public virtual int Available | |
494 { | |
495 get { | |
496 return inf.IsFinished ? 0 : 1; | |
497 } | |
498 } | |
499 | |
500 /// <summary> | |
501 /// Fills the buffer with more data to decompress. | |
502 /// </summary> | |
503 /// <exception cref="SharpZipBaseException"> | |
504 /// Stream ends early | |
505 /// </exception> | |
506 protected void Fill() | |
507 { | |
508 // Protect against redundant calls | |
509 if (inputBuffer.Available <= 0) { | |
510 inputBuffer.Fill(); | |
511 if (inputBuffer.Available <= 0) { | |
512 throw new SharpZipBaseException("Unexpected EOF"); | |
513 } | |
514 } | |
515 inputBuffer.SetInflaterInput(inf); | |
516 } | |
517 | |
518 #region Stream Overrides | |
519 /// <summary> | |
520 /// Gets a value indicating whether the current stream supports reading | |
521 /// </summary> | |
522 public override bool CanRead | |
523 { | |
524 get { | |
525 return baseInputStream.CanRead; | |
526 } | |
527 } | |
528 | |
529 /// <summary> | |
530 /// Gets a value of false indicating seeking is not supported for this stream. | |
531 /// </summary> | |
532 public override bool CanSeek { | |
533 get { | |
534 return false; | |
535 } | |
536 } | |
537 | |
538 /// <summary> | |
539 /// Gets a value of false indicating that this stream is not writeable. | |
540 /// </summary> | |
541 public override bool CanWrite { | |
542 get { | |
543 return false; | |
544 } | |
545 } | |
546 | |
547 /// <summary> | |
548 /// A value representing the length of the stream in bytes. | |
549 /// </summary> | |
550 public override long Length { | |
551 get { | |
552 return inputBuffer.RawLength; | |
553 } | |
554 } | |
555 | |
556 /// <summary> | |
557 /// The current position within the stream. | |
558 /// Throws a NotSupportedException when attempting to set the position | |
559 /// </summary> | |
560 /// <exception cref="NotSupportedException">Attempting to set the position</exception> | |
561 public override long Position { | |
562 get { | |
563 return baseInputStream.Position; | |
564 } | |
565 set { | |
566 throw new NotSupportedException("InflaterInputStream Position not supported"); | |
567 } | |
568 } | |
569 | |
570 /// <summary> | |
571 /// Flushes the baseInputStream | |
572 /// </summary> | |
573 public override void Flush() | |
574 { | |
575 baseInputStream.Flush(); | |
576 } | |
577 | |
578 /// <summary> | |
579 /// Sets the position within the current stream | |
580 /// Always throws a NotSupportedException | |
581 /// </summary> | |
582 /// <param name="offset">The relative offset to seek to.</param> | |
583 /// <param name="origin">The <see cref="SeekOrigin"/> defining where to seek from.</param> | |
584 /// <returns>The new position in the stream.</returns> | |
585 /// <exception cref="NotSupportedException">Any access</exception> | |
586 public override long Seek(long offset, SeekOrigin origin) | |
587 { | |
588 throw new NotSupportedException("Seek not supported"); | |
589 } | |
590 | |
591 /// <summary> | |
592 /// Set the length of the current stream | |
593 /// Always throws a NotSupportedException | |
594 /// </summary> | |
595 /// <param name="value">The new length value for the stream.</param> | |
596 /// <exception cref="NotSupportedException">Any access</exception> | |
597 public override void SetLength(long value) | |
598 { | |
599 throw new NotSupportedException("InflaterInputStream SetLength not supported"); | |
600 } | |
601 | |
602 /// <summary> | |
603 /// Writes a sequence of bytes to stream and advances the current position | |
604 /// This method always throws a NotSupportedException | |
605 /// </summary> | |
606 /// <param name="buffer">Thew buffer containing data to write.</param> | |
607 /// <param name="offset">The offset of the first byte to write.</param> | |
608 /// <param name="count">The number of bytes to write.</param> | |
609 /// <exception cref="NotSupportedException">Any access</exception> | |
610 public override void Write(byte[] buffer, int offset, int count) | |
611 { | |
612 throw new NotSupportedException("InflaterInputStream Write not supported"); | |
613 } | |
614 | |
615 /// <summary> | |
616 /// Writes one byte to the current stream and advances the current position | |
617 /// Always throws a NotSupportedException | |
618 /// </summary> | |
619 /// <param name="value">The byte to write.</param> | |
620 /// <exception cref="NotSupportedException">Any access</exception> | |
621 public override void WriteByte(byte value) | |
622 { | |
623 throw new NotSupportedException("InflaterInputStream WriteByte not supported"); | |
624 } | |
625 | |
626 /// <summary> | |
627 /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. | |
628 /// </summary> | |
629 /// <param name="buffer">The buffer to write data from</param> | |
630 /// <param name="offset">Offset of first byte to write</param> | |
631 /// <param name="count">The maximum number of bytes to write</param> | |
632 /// <param name="callback">The method to be called when the asynchronous write operation is completed</param> | |
633 /// <param name="state">A user-provided object that distinguishes this particular asynchronous write request from other requests</param> | |
634 /// <returns>An <see cref="System.IAsyncResult">IAsyncResult</see> that references the asynchronous write</returns> | |
635 /// <exception cref="NotSupportedException">Any access</exception> | |
636 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) | |
637 { | |
638 throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); | |
639 } | |
640 | |
641 /// <summary> | |
642 /// Closes the input stream. When <see cref="IsStreamOwner"></see> | |
643 /// is true the underlying stream is also closed. | |
644 /// </summary> | |
645 public override void Close() | |
646 { | |
647 if ( !isClosed ) { | |
648 isClosed = true; | |
649 if ( isStreamOwner ) { | |
650 baseInputStream.Close(); | |
651 } | |
652 } | |
653 } | |
654 | |
655 /// <summary> | |
656 /// Reads decompressed data into the provided buffer byte array | |
657 /// </summary> | |
658 /// <param name ="buffer"> | |
659 /// The array to read and decompress data into | |
660 /// </param> | |
661 /// <param name ="offset"> | |
662 /// The offset indicating where the data should be placed | |
663 /// </param> | |
664 /// <param name ="count"> | |
665 /// The number of bytes to decompress | |
666 /// </param> | |
667 /// <returns>The number of bytes read. Zero signals the end of stream</returns> | |
668 /// <exception cref="SharpZipBaseException"> | |
669 /// Inflater needs a dictionary | |
670 /// </exception> | |
671 public override int Read(byte[] buffer, int offset, int count) | |
672 { | |
673 if (inf.IsNeedingDictionary) | |
674 { | |
675 throw new SharpZipBaseException("Need a dictionary"); | |
676 } | |
677 | |
678 int remainingBytes = count; | |
679 while (true) { | |
680 int bytesRead = inf.Inflate(buffer, offset, remainingBytes); | |
681 offset += bytesRead; | |
682 remainingBytes -= bytesRead; | |
683 | |
684 if (remainingBytes == 0 || inf.IsFinished) { | |
685 break; | |
686 } | |
687 | |
688 if ( inf.IsNeedingInput ) { | |
689 Fill(); | |
690 } | |
691 else if ( bytesRead == 0 ) { | |
692 throw new ZipException("Dont know what to do"); | |
693 } | |
694 } | |
695 return count - remainingBytes; | |
696 } | |
697 #endregion | |
698 | |
699 #region Instance Fields | |
700 /// <summary> | |
701 /// Decompressor for this stream | |
702 /// </summary> | |
703 protected Inflater inf; | |
704 | |
705 /// <summary> | |
706 /// <see cref="InflaterInputBuffer">Input buffer</see> for this stream. | |
707 /// </summary> | |
708 protected InflaterInputBuffer inputBuffer; | |
709 | |
710 /// <summary> | |
711 /// Base stream the inflater reads from. | |
712 /// </summary> | |
713 private Stream baseInputStream; | |
714 | |
715 /// <summary> | |
716 /// The compressed size | |
717 /// </summary> | |
718 protected long csize; | |
719 | |
720 /// <summary> | |
721 /// Flag indicating wether this instance has been closed or not. | |
722 /// </summary> | |
723 bool isClosed; | |
724 | |
725 /// <summary> | |
726 /// Flag indicating wether this instance is designated the stream owner. | |
727 /// When closing if this flag is true the underlying stream is closed. | |
728 /// </summary> | |
729 bool isStreamOwner = true; | |
730 #endregion | |
731 } | |
732 } |