private static int Codes(BitStream bitStream, Huffman lencode, Huffman distcode, bool lastBlock) { int symbol; do { symbol = Decode(bitStream, lencode); if (symbol < 0) { throw new ArgumentOutOfRangeException("invalid symbol."); } if (symbol < 256) { bitStream.OutBuffer.Add((byte)symbol); //bitStream.OutBufferWithHeader.Add((byte)symbol); //if (bitStream.OutBuffer.Count() % 65535 == 0) //{ // Console.WriteLine("blocked"); // var blocks = bitStream.OutBuffer.Count() / 65535; // bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader(65535, false)); //} } else if (symbol > 256) { symbol -= 257; if (symbol >= 29) { throw new Exception("Invalid fixed code."); } var len = lens[symbol] + bitStream.GetNextBitsReverse(lext[symbol]); symbol = Decode(bitStream, distcode); if (symbol < 0) { throw new ArgumentOutOfRangeException("invalid symbol."); } var dist = dists[symbol] + bitStream.GetNextBitsReverse(dext[symbol]); // copy length bytes from distance bytes back. for (int i = 0; i < len; i++) { bitStream.OutBuffer.Add(bitStream.OutBuffer[bitStream.OutBuffer.Count() - dist]); //bitStream.OutBufferWithHeader.Add(bitStream.OutBuffer[bitStream.OutBuffer.Count() - dist]); //if (bitStream.OutBuffer.Count() % 65535 == 0) //{ // Console.WriteLine("blocked"); // var blocks = bitStream.OutBuffer.Count() / 65535; // bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader(65535, false)); //} } } } while (symbol != 256); //if (lastBlock) //{ // var blocks = bitStream.OutBuffer.Count() / 65535; // bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader((ushort)(bitStream.OutBuffer.Count() % 65535), true)); //} return(0); }
public static int ParseDynamic(BitStream bitStream, bool lastBlock) { short[] lengths = new short[MAXCODES]; int nlen = bitStream.GetNextBitsReverse(5) + 257; int ndist = bitStream.GetNextBitsReverse(5) + 1; int ncode = bitStream.GetNextBitsReverse(4) + 4; if (nlen > MAXLCODES || ndist > MAXDCODES) { throw new Exception("bad counts"); } for (int i = 0; i < ncode; i++) { lengths[order[i]] = (short)bitStream.GetNextBitsReverse(3); } for (int i = ncode; i < 19; i++) { lengths[order[i]] = 0; } //for (int i = 0; i < lengths.Length; i++) //{ // Console.WriteLine($"symbol {i} has a code length of {lengths[i]}"); //} var lencode = new Huffman(new short[MAXBITS + 1], new short[MAXLCODES]); var distcode = new Huffman(new short[MAXBITS + 1], new short[MAXDCODES]); var err = Construct(ref lencode, lengths, 19); if (err != 0) { throw new Exception("complete code set required here; code lengths codes incomplete."); } //for (int i = 0; i < lencode.count.Length; i++) //{ // Console.WriteLine($"{lencode.count[i]} symbols of length {i}"); //} var index = 0; while (index < nlen + ndist) { var symbol = Decode(bitStream, lencode); var len = 0; if (symbol < 0) { throw new ArgumentOutOfRangeException("invalid symbol"); } if (symbol < 16) { lengths[index++] = (short)symbol; } else { if (symbol == 16) { if (index == 0) { throw new ArgumentOutOfRangeException("no preceeding length to reference!"); } len = lengths[index - 1]; symbol = 3 + bitStream.GetNextBitsReverse(2); } else if (symbol == 17) { symbol = 3 + bitStream.GetNextBitsReverse(3); } else { symbol = 11 + bitStream.GetNextBitsReverse(7); } if (index + symbol > nlen + ndist) { throw new ArgumentOutOfRangeException("too many lengths!"); } while (symbol-- > 0) { lengths[index++] = (short)len; } } } if (lengths[256] == 0) { throw new Exception("no end of block code"); } err = Construct(ref lencode, lengths, nlen); if (err != 0 & (err < 0 || nlen != lencode.count[0] + lencode.count[1])) { throw new ArgumentException("incomplete code ok only for single length 1 code."); } var _lengths = new short[MAXDCODES]; Array.Copy(lengths, nlen, _lengths, 0, MAXDCODES); err = Construct(ref distcode, _lengths, ndist); if (err != 0 & (err < 0 || nlen != distcode.count[0] + distcode.count[1])) { throw new ArgumentException("incomplete code ok only for single length 1 code."); } return(Codes(bitStream, lencode, distcode, lastBlock)); }