ReadBits() public method

public ReadBits ( int count ) : int
count int
return int
Beispiel #1
0
        // Decode a code using huffman table h.
        static int Decode(Huffman h, BitReader br)
        {
            int   code  = 0;          // len bits being decoded
            int   first = 0;          // first code of length len
            int   index = 0;          // index of first code of length len in symbol table
            short next  = 1;

            while (true)
            {
                code |= br.ReadBits(1) ^ 1;                 // invert code
                int count = h.Count[next++];
                if (code < first + count)
                {
                    return(h.Symbol[index + (code - first)]);
                }

                index  += count;
                first  += count;
                first <<= 1;
                code  <<= 1;
            }
        }
Beispiel #2
0
        // Decode PKWare Compression Library stream.
        public static byte[] Decompress(byte[] src)
        {
            BitReader br = new BitReader(src);

            // Are literals coded?
            int coded = br.ReadBits(8);

            if (coded < 0 || coded > 1)
            {
                throw new NotImplementedException("Invalid datastream");
            }
            bool EncodedLiterals = (coded == 1);

            // log2(dictionary size) - 6
            int dict = br.ReadBits(8);

            if (dict < 4 || dict > 6)
            {
                throw new InvalidDataException("Invalid dictionary size");
            }

            // output state
            ushort next  = 0;                    // index of next write location in out[]
            bool   first = true;                 // true to check distances (for first 4K)

            byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window
            var    ms        = new MemoryStream();

            // decode literals and length/distance pairs
            do
            {
                // length/distance pair
                if (br.ReadBits(1) == 1)
                {
                    // Length
                    int symbol = Decode(lencode, br);
                    int len    = lengthbase[symbol] + br.ReadBits(extra[symbol]);
                    if (len == 519)                     // Magic number for "done"
                    {
                        for (int i = 0; i < next; i++)
                        {
                            ms.WriteByte(outBuffer[i]);
                        }
                        break;
                    }

                    // Distance
                    symbol = len == 2 ? 2 : dict;
                    int dist = Decode(distcode, br) << symbol;
                    dist += br.ReadBits(symbol);
                    dist++;

                    if (first && dist > next)
                    {
                        throw new InvalidDataException("Attempt to jump before data");
                    }

                    // copy length bytes from distance bytes back
                    do
                    {
                        int dest   = next;
                        int source = dest - dist;

                        int copy = MAXWIN;
                        if (next < dist)
                        {
                            source += copy;
                            copy    = dist;
                        }

                        copy -= next;
                        if (copy > len)
                        {
                            copy = len;
                        }

                        len  -= copy;
                        next += (ushort)copy;

                        // copy with old-fashioned memcpy semantics
                        // in case of overlapping ranges. this is NOT
                        // the same as Array.Copy()
                        while (copy-- > 0)
                        {
                            outBuffer[dest++] = outBuffer[source++];
                        }

                        // Flush window to outstream
                        if (next == MAXWIN)
                        {
                            for (int i = 0; i < next; i++)
                            {
                                ms.WriteByte(outBuffer[i]);
                            }
                            next  = 0;
                            first = false;
                        }
                    } while (len != 0);
                }
                else                 // literal value
                {
                    int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
                    outBuffer[next++] = (byte)symbol;
                    if (next == MAXWIN)
                    {
                        for (int i = 0; i < next; i++)
                        {
                            ms.WriteByte(outBuffer[i]);
                        }
                        next  = 0;
                        first = false;
                    }
                }
            } while (true);

            return(ms.ToArray());
        }
Beispiel #3
0
        /// <summary>PKWare Compression Library stream.</summary>
        /// <param name="input">Compressed input stream.</param>
        /// <param name="output">Stream to write the decompressed output.</param>
        /// <param name="onProgress">Progress callback, invoked with (read bytes, written bytes).</param>
        public static void Decompress(Stream input, Stream output, Action <long, long> onProgress = null)
        {
            var br = new BitReader(input);

            // Are literals coded?
            var coded = br.ReadBits(8);

            if (coded < 0 || coded > 1)
            {
                throw new NotImplementedException("Invalid data stream");
            }
            var encodedLiterals = coded == 1;

            // log2(dictionary size) - 6
            var dict = br.ReadBits(8);

            if (dict < 4 || dict > 6)
            {
                throw new InvalidDataException("Invalid dictionary size");
            }

            // output state
            ushort next      = 0;                // index of next write location in out[]
            var    first     = true;             // true to check distances (for first 4K)
            var    outBuffer = new byte[MAXWIN]; // output buffer and sliding window

            var inputStart  = input.Position;
            var outputStart = output.Position;

            // decode literals and length/distance pairs
            do
            {
                // length/distance pair
                if (br.ReadBits(1) == 1)
                {
                    // Length
                    var symbol = Decode(lencode, br);
                    var len    = lengthbase[symbol] + br.ReadBits(extra[symbol]);

                    // Magic number for "done"
                    if (len == 519)
                    {
                        for (var i = 0; i < next; i++)
                        {
                            output.WriteByte(outBuffer[i]);
                        }

                        if (onProgress != null)
                        {
                            onProgress(input.Position - inputStart, output.Position - outputStart);
                        }
                        break;
                    }

                    // Distance
                    symbol = len == 2 ? 2 : dict;
                    var dist = Decode(distcode, br) << symbol;
                    dist += br.ReadBits(symbol);
                    dist++;

                    if (first && dist > next)
                    {
                        throw new InvalidDataException("Attempt to jump before data");
                    }

                    // copy length bytes from distance bytes back
                    do
                    {
                        var dest   = next;
                        var source = dest - dist;

                        var copy = MAXWIN;
                        if (next < dist)
                        {
                            source += copy;
                            copy    = dist;
                        }

                        copy -= next;
                        if (copy > len)
                        {
                            copy = len;
                        }

                        len  -= copy;
                        next += (ushort)copy;

                        // copy with old-fashioned memcpy semantics
                        // in case of overlapping ranges. this is NOT
                        // the same as Array.Copy()
                        while (copy-- > 0)
                        {
                            outBuffer[dest++] = outBuffer[source++];
                        }

                        // Flush window to outstream
                        if (next == MAXWIN)
                        {
                            for (var i = 0; i < next; i++)
                            {
                                output.WriteByte(outBuffer[i]);
                            }
                            next  = 0;
                            first = false;

                            if (onProgress != null)
                            {
                                onProgress(input.Position - inputStart, output.Position - outputStart);
                            }
                        }
                    } while (len != 0);
                }
                else
                {
                    // literal value
                    var symbol = encodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
                    outBuffer[next++] = (byte)symbol;
                    if (next == MAXWIN)
                    {
                        for (var i = 0; i < next; i++)
                        {
                            output.WriteByte(outBuffer[i]);
                        }
                        next  = 0;
                        first = false;

                        if (onProgress != null)
                        {
                            onProgress(input.Position - inputStart, output.Position - outputStart);
                        }
                    }
                }
            } while (true);
        }