예제 #1
0
        // TODO: Use specialized versions for smaller tables.
        internal 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++;
                }
                // TODO: uncomment when codeLengths is reused.
                // 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:
                default:
                {
                    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[CodeLengthCodes];
                int   space    = 32;
                int   numCodes = 0;
                for (int i = simpleCodeOrSkip; i < CodeLengthCodes && space > 0; i++)
                {
                    int codeLenIdx = CodeLengthCodeOrder[i];
                    BitReader.FillBitWindow(br);
                    int p = (int)((long)(((ulong)br._accumulator) >> br._bitOffset)) & 15;
                    // TODO: Demultiplex FIXED_TABLE.
                    br._bitOffset += FixedTable[p] >> 16;
                    int v = FixedTable[p] & unchecked ((int)(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, HuffmanTableBits, codeLengths, alphabetSize);
        }
예제 #2
0
        private static void ReadHuffmanCodeLengths(int[] codeLengthCodeLengths, int numSymbols,
                                                   int[] codeLengths, BitReader br)
        {
            int symbol        = 0;
            int prevCodeLen   = DefaultCodeLength;
            int repeat        = 0;
            int repeatCodeLen = 0;
            int space         = 32768;

            int[] table = new int[32];
            Huffman.BuildHuffmanTable(table, 0, 5, codeLengthCodeLengths, CodeLengthCodes);
            while (symbol < numSymbols && space > 0)
            {
                BitReader.ReadMoreInput(br);
                BitReader.FillBitWindow(br);
                int p = (int)(((long)(((ulong)br._accumulator) >> br._bitOffset))) & 31;
                br._bitOffset += table[p] >> 16;
                int codeLen = table[p] & unchecked ((int)(0xFFFF));
                if (codeLen < CodeLengthRepeatCode)
                {
                    repeat = 0;
                    codeLengths[symbol++] = codeLen;
                    if (codeLen != 0)
                    {
                        prevCodeLen = codeLen;
                        space      -= 32768 >> codeLen;
                    }
                }
                else
                {
                    int extraBits = codeLen - 14;
                    int newLen    = 0;
                    if (codeLen == CodeLengthRepeatCode)
                    {
                        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);
        }