예제 #1
0
        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);
        }
예제 #2
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));
        }