123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
-
- using System;
- using System.IO;
- namespace CommonMPQ.SharpZipLib.LZW
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class LzwInputStream : Stream
- {
-
-
-
-
-
-
-
- public bool IsStreamOwner
- {
- get { return isStreamOwner; }
- set { isStreamOwner = value; }
- }
-
-
-
-
-
-
- public LzwInputStream(Stream baseInputStream) {
- this.baseInputStream = baseInputStream;
- }
-
-
-
-
- public override int ReadByte() {
- int b = Read(one, 0, 1);
- if (b == 1)
- return (one[0] & 0xff);
- return -1;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public override int Read(byte[] buffer, int offset, int count) {
- if (!headerParsed) ParseHeader();
- if (eof) return 0;
- int start = offset;
-
- int[] lTabPrefix = tabPrefix;
- byte[] lTabSuffix = tabSuffix;
- byte[] lStack = stack;
- int lNBits = nBits;
- int lMaxCode = maxCode;
- int lMaxMaxCode = maxMaxCode;
- int lBitMask = bitMask;
- int lOldCode = oldCode;
- byte lFinChar = finChar;
- int lStackP = stackP;
- int lFreeEnt = freeEnt;
- byte[] lData = data;
- int lBitPos = bitPos;
-
- int sSize = lStack.Length - lStackP;
- if (sSize > 0) {
- int num = (sSize >= count) ? count : sSize;
- Array.Copy(lStack, lStackP, buffer, offset, num);
- offset += num;
- count -= num;
- lStackP += num;
- }
- if (count == 0) {
- stackP = lStackP;
- return offset - start;
- }
-
- MainLoop: do {
- if (end < EXTRA) {
- Fill();
- }
- int bitIn = (got > 0) ? (end - end % lNBits) << 3 :
- (end << 3) - (lNBits - 1);
- while (lBitPos < bitIn) {
- #region A
-
- if (count == 0) {
- nBits = lNBits;
- maxCode = lMaxCode;
- maxMaxCode = lMaxMaxCode;
- bitMask = lBitMask;
- oldCode = lOldCode;
- finChar = lFinChar;
- stackP = lStackP;
- freeEnt = lFreeEnt;
- bitPos = lBitPos;
-
- return offset - start;
- }
-
- if (lFreeEnt > lMaxCode) {
- int nBytes = lNBits << 3;
- lBitPos = (lBitPos - 1) +
- nBytes - (lBitPos - 1 + nBytes) % nBytes;
- lNBits++;
- lMaxCode = (lNBits == maxBits) ? lMaxMaxCode :
- (1 << lNBits) - 1;
- lBitMask = (1 << lNBits) - 1;
- lBitPos = ResetBuf(lBitPos);
- goto MainLoop;
- }
- #endregion
- #region B
-
- int pos = lBitPos >> 3;
- int code = (((lData[pos] & 0xFF) |
- ((lData[pos + 1] & 0xFF) << 8) |
- ((lData[pos + 2] & 0xFF) << 16)) >>
- (lBitPos & 0x7)) & lBitMask;
- lBitPos += lNBits;
-
- if (lOldCode == -1) {
- if (code >= 256) throw new LzwException("corrupt input: " + code + " > 255");
- lFinChar = (byte) (lOldCode = code);
- buffer[offset++] = lFinChar;
- count--;
- continue;
- }
-
- if (code == TBL_CLEAR && blockMode) {
- Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length);
- lFreeEnt = TBL_FIRST - 1;
- int nBytes = lNBits << 3;
- lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes;
- lNBits = LzwConstants.INIT_BITS;
- lMaxCode = (1 << lNBits) - 1;
- lBitMask = lMaxCode;
-
- lBitPos = ResetBuf(lBitPos);
- goto MainLoop;
- }
- #endregion
- #region C
-
- int inCode = code;
- lStackP = lStack.Length;
-
- if (code >= lFreeEnt) {
- if (code > lFreeEnt) {
- throw new LzwException("corrupt input: code=" + code +
- ", freeEnt=" + lFreeEnt);
- }
- lStack[--lStackP] = lFinChar;
- code = lOldCode;
- }
-
- while (code >= 256) {
- lStack[--lStackP] = lTabSuffix[code];
- code = lTabPrefix[code];
- }
- lFinChar = lTabSuffix[code];
- buffer[offset++] = lFinChar;
- count--;
-
- sSize = lStack.Length - lStackP;
- int num = (sSize >= count) ? count : sSize;
- Array.Copy(lStack, lStackP, buffer, offset, num);
- offset += num;
- count -= num;
- lStackP += num;
- #endregion
- #region D
-
- if (lFreeEnt < lMaxMaxCode) {
- lTabPrefix[lFreeEnt] = lOldCode;
- lTabSuffix[lFreeEnt] = lFinChar;
- lFreeEnt++;
- }
-
- lOldCode = inCode;
-
- if (count == 0) {
- nBits = lNBits;
- maxCode = lMaxCode;
- bitMask = lBitMask;
- oldCode = lOldCode;
- finChar = lFinChar;
- stackP = lStackP;
- freeEnt = lFreeEnt;
- bitPos = lBitPos;
- return offset - start;
- }
- #endregion
- }
- lBitPos = ResetBuf(lBitPos);
- } while (got > 0);
- nBits = lNBits;
- maxCode = lMaxCode;
- bitMask = lBitMask;
- oldCode = lOldCode;
- finChar = lFinChar;
- stackP = lStackP;
- freeEnt = lFreeEnt;
- bitPos = lBitPos;
- eof = true;
- return offset - start;
- }
-
-
-
-
-
-
- private int ResetBuf(int bitPosition) {
- int pos = bitPosition >> 3;
- Array.Copy(data, pos, data, 0, end - pos);
- end -= pos;
- return 0;
- }
- private void Fill() {
- got = baseInputStream.Read(data, end, data.Length - 1 - end);
- if (got > 0) {
- end += got;
- }
- }
- private void ParseHeader() {
- headerParsed = true;
- byte[] hdr = new byte[LzwConstants.HDR_SIZE];
- int result = baseInputStream.Read(hdr, 0, hdr.Length);
-
- if (result < 0)
- throw new LzwException("Failed to read LZW header");
- if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) {
- throw new LzwException(String.Format(
- "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}",
- hdr[0], hdr[1]));
- }
-
- blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0;
- maxBits = hdr[2] & LzwConstants.BIT_MASK;
- if (maxBits > LzwConstants.MAX_BITS) {
- throw new LzwException("Stream compressed with " + maxBits +
- " bits, but decompression can only handle " +
- LzwConstants.MAX_BITS + " bits.");
- }
- if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) {
- throw new LzwException("Unsupported bits set in the header.");
- }
-
- maxMaxCode = 1 << maxBits;
- nBits = LzwConstants.INIT_BITS;
- maxCode = (1 << nBits) - 1;
- bitMask = maxCode;
- oldCode = -1;
- finChar = 0;
- freeEnt = blockMode ? TBL_FIRST : 256;
- tabPrefix = new int[1 << maxBits];
- tabSuffix = new byte[1 << maxBits];
- stack = new byte[1 << maxBits];
- stackP = stack.Length;
- for (int idx = 255; idx >= 0; idx--)
- tabSuffix[idx] = (byte)idx;
- }
- #region Stream Overrides
-
-
-
- public override bool CanRead
- {
- get
- {
- return baseInputStream.CanRead;
- }
- }
-
-
-
- public override bool CanSeek
- {
- get
- {
- return false;
- }
- }
-
-
-
- public override bool CanWrite
- {
- get
- {
- return false;
- }
- }
-
-
-
- public override long Length
- {
- get
- {
- return got;
- }
- }
-
-
-
-
-
- public override long Position
- {
- get
- {
- return baseInputStream.Position;
- }
- set
- {
- throw new NotSupportedException("InflaterInputStream Position not supported");
- }
- }
-
-
-
- public override void Flush()
- {
- baseInputStream.Flush();
- }
-
-
-
-
-
-
-
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException("Seek not supported");
- }
-
-
-
-
-
-
- public override void SetLength(long value)
- {
- throw new NotSupportedException("InflaterInputStream SetLength not supported");
- }
-
-
-
-
-
-
-
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException("InflaterInputStream Write not supported");
- }
-
-
-
-
-
-
- public override void WriteByte(byte value)
- {
- throw new NotSupportedException("InflaterInputStream WriteByte not supported");
- }
-
-
-
-
-
-
-
-
-
-
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- throw new NotSupportedException("InflaterInputStream BeginWrite not supported");
- }
-
-
-
-
- public override void Close()
- {
- if (!isClosed)
- {
- isClosed = true;
- if (isStreamOwner)
- {
- baseInputStream.Close();
- }
- }
- }
- #endregion
- #region Instance Fields
- Stream baseInputStream;
-
-
-
-
- bool isStreamOwner = true;
-
-
-
- bool isClosed;
- readonly byte[] one = new byte[1];
- bool headerParsed;
-
- private const int TBL_CLEAR = 0x100;
- private const int TBL_FIRST = TBL_CLEAR + 1;
- private int[] tabPrefix;
- private byte[] tabSuffix;
- private readonly int[] zeros = new int[256];
- private byte[] stack;
-
- private bool blockMode;
- private int nBits;
- private int maxBits;
- private int maxMaxCode;
- private int maxCode;
- private int bitMask;
- private int oldCode;
- private byte finChar;
- private int stackP;
- private int freeEnt;
-
- private readonly byte[] data = new byte[1024 * 8];
- private int bitPos;
- private int end;
- int got;
- private bool eof;
- private const int EXTRA = 64;
- #endregion
- }
- }
|