예제 #1
0
        public static void ReadHuffmanCode(int alphabetSize, int[] table, int offset, BitReader br)
        {
            bool ok = true;
            int  simpleCodeOrSkip;

            BitReader.ReadMoreInput(br);
            // TODO: Avoid allocation.
            int[] codeLengths = new int[alphabetSize];
            simpleCodeOrSkip = BitReader.ReadBits(br, 2);
            if (simpleCodeOrSkip == 1)
            { // Read symbols, codes & code lengths directly.
                int   maxBitsCounter = alphabetSize - 1;
                int   maxBits        = 0;
                int[] symbols        = new int[4];
                int   numSymbols     = BitReader.ReadBits(br, 2) + 1;
                while (maxBitsCounter != 0)
                {
                    maxBitsCounter >>= 1;
                    maxBits++;
                }
                Utils.FillWithZeroes(codeLengths, 0, alphabetSize);
                for (int i = 0; i < numSymbols; i++)
                {
                    symbols[i] = BitReader.ReadBits(br, maxBits) % alphabetSize;
                    codeLengths[symbols[i]] = 2;
                }
                codeLengths[symbols[0]] = 1;
                switch (numSymbols)
                {
                case 1:
                    break;

                case 2:
                    ok = symbols[0] != symbols[1];
                    codeLengths[symbols[1]] = 1;
                    break;

                case 3:
                    ok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[1] != symbols[2];
                    break;

                case 4:
                    ok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[0] != symbols[3] &&
                         symbols[1] != symbols[2] && symbols[1] != symbols[3] && symbols[2] != symbols[3];
                    if (BitReader.ReadBits(br, 1) == 1)
                    {
                        codeLengths[symbols[2]] = 3;
                        codeLengths[symbols[3]] = 3;
                    }
                    else
                    {
                        codeLengths[symbols[0]] = 2;
                    }
                    break;
                }
            }
            else
            { // Decode Huffman-coded code lengths.
                int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES];
                int   space    = 32;
                int   numCodes = 0;
                for (int i = simpleCodeOrSkip; i < CODE_LENGTH_CODES && space > 0; i++)
                {
                    int codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
                    BitReader.FillBitWindow(br);
                    int p = (int)((ulong)br.accumulator >> br.bitOffset) & 15;
                    // TODO: Demultiplex FIXED_TABLE.
                    br.bitOffset += FIXED_TABLE[p] >> 16;
                    int v = FIXED_TABLE[p] & 0xFFFF;
                    codeLengthCodeLengths[codeLenIdx] = v;
                    if (v != 0)
                    {
                        space -= (32 >> v);
                        numCodes++;
                    }
                }
                ok = (numCodes == 1 || space == 0);
                ReadHuffmanCodeLengths(codeLengthCodeLengths, alphabetSize, codeLengths, br);
            }
            if (!ok)
            {
                throw new BrotliRuntimeException("Can't readHuffmanCode"); // COV_NF_LINE
            }
            Huffman.BuildHuffmanTable(table, offset, HUFFMAN_TABLE_BITS, codeLengths, alphabetSize);
        }
예제 #2
0
        private static void ReadHuffmanCodeLengths(
            int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, BitReader br)
        {
            int symbol        = 0;
            int prevCodeLen   = DEFAULT_CODE_LENGTH;
            int repeat        = 0;
            int repeatCodeLen = 0;
            int space         = 32768;

            int[] table = new int[32];

            Huffman.BuildHuffmanTable(table, 0, 5, codeLengthCodeLengths, CODE_LENGTH_CODES);

            while (symbol < numSymbols && space > 0)
            {
                BitReader.ReadMoreInput(br);
                BitReader.FillBitWindow(br);
                int p = (int)(((ulong)br.accumulator >> br.bitOffset)) & 31;
                br.bitOffset += table[p] >> 16;
                int codeLen = table[p] & 0xFFFF;
                if (codeLen < CODE_LENGTH_REPEAT_CODE)
                {
                    repeat = 0;
                    codeLengths[symbol++] = codeLen;
                    if (codeLen != 0)
                    {
                        prevCodeLen = codeLen;
                        space      -= 32768 >> codeLen;
                    }
                }
                else
                {
                    int extraBits = codeLen - 14;
                    int newLen    = 0;
                    if (codeLen == CODE_LENGTH_REPEAT_CODE)
                    {
                        newLen = prevCodeLen;
                    }
                    if (repeatCodeLen != newLen)
                    {
                        repeat        = 0;
                        repeatCodeLen = newLen;
                    }
                    int oldRepeat = repeat;
                    if (repeat > 0)
                    {
                        repeat  -= 2;
                        repeat <<= extraBits;
                    }
                    repeat += BitReader.ReadBits(br, extraBits) + 3;
                    int repeatDelta = repeat - oldRepeat;
                    if (symbol + repeatDelta > numSymbols)
                    {
                        throw new BrotliRuntimeException("symbol + repeatDelta > numSymbols"); // COV_NF_LINE
                    }
                    for (int i = 0; i < repeatDelta; i++)
                    {
                        codeLengths[symbol++] = repeatCodeLen;
                    }
                    if (repeatCodeLen != 0)
                    {
                        space -= repeatDelta << (15 - repeatCodeLen);
                    }
                }
            }
            if (space != 0)
            {
                throw new BrotliRuntimeException("Unused space"); // COV_NF_LINE
            }
            // TODO: Pass max_symbol to Huffman table builder instead?
            Utils.FillWithZeroes(codeLengths, symbol, numSymbols - symbol);
        }