mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-24 05:10:42 -04:00
78 lines
2.2 KiB
C#
78 lines
2.2 KiB
C#
// Originally copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
|
// All rights reserved.
|
|
// See license.txt, section Ionic.Zlib license
|
|
#if __MonoCS__
|
|
using System;
|
|
using System.IO;
|
|
using ClassicalSharp;
|
|
|
|
namespace Ionic.Zlib {
|
|
|
|
internal class DeflateStream : ReadOnlyStream {
|
|
|
|
ZlibCodec z;
|
|
bool _leaveOpen;
|
|
byte[] workBuffer;
|
|
Stream _stream;
|
|
|
|
public DeflateStream(Stream stream, bool leaveOpen) {
|
|
_stream = stream;
|
|
_leaveOpen = leaveOpen;
|
|
workBuffer = new byte[16384]; // TODO: 1024 bytes?
|
|
z = new ZlibCodec();
|
|
}
|
|
|
|
public override void Close() {
|
|
z.EndInflate();
|
|
z = null;
|
|
|
|
if (!_leaveOpen)
|
|
_stream.Dispose();
|
|
_stream = null;
|
|
}
|
|
|
|
public override void Flush() { }
|
|
|
|
public override int Read(byte[] buffer, int offset, int count) {
|
|
// According to MS documentation, any implementation of the IO.Stream.Read function must:
|
|
// (a) throw an exception if offset & count reference an invalid part of the buffer,
|
|
// or if count < 0, or if buffer is null
|
|
// (b) return 0 only upon EOF, or if count = 0
|
|
// (c) if not EOF, then return at least 1 byte, up to <count> bytes
|
|
|
|
if (count == 0) return 0;
|
|
int rc = 0;
|
|
|
|
// set up the output of the deflate/inflate codec:
|
|
z.OutputBuffer = buffer;
|
|
z.NextOut = offset;
|
|
z.AvailableBytesOut = count;
|
|
z.InputBuffer = workBuffer;
|
|
bool endOfInput = false;
|
|
|
|
do {
|
|
// need data in _workingBuffer in order to deflate/inflate. Here, we check if we have any.
|
|
if (z.AvailableBytesIn == 0 && !endOfInput) {
|
|
// No data available, so try to Read data from the captive stream.
|
|
z.NextIn = 0;
|
|
z.AvailableBytesIn = _stream.Read(workBuffer, 0, workBuffer.Length);
|
|
if (z.AvailableBytesIn == 0)
|
|
endOfInput = true;
|
|
}
|
|
rc = z.Inflate();
|
|
|
|
if (endOfInput && rc == RCode.BufferError)
|
|
return 0;
|
|
|
|
if (rc != RCode.Okay && rc != RCode.StreamEnd)
|
|
throw new InvalidDataException("inflating: rc=" + rc);
|
|
|
|
if ((endOfInput || rc == RCode.StreamEnd) && z.AvailableBytesOut == count)
|
|
break; // nothing more to read
|
|
} while (z.AvailableBytesOut > 0 && !endOfInput && rc == RCode.Okay);
|
|
|
|
return count - z.AvailableBytesOut;
|
|
}
|
|
}
|
|
}
|
|
#endif |