Beispiel #1
0
            public static unsafe void ProduceLengths(
                BitSource data,
                ushort *tree,
                ushort literalLengthCodeCount,
                byte distanceCodeCount,
                byte *literalLengths,
                byte *distanceLengths)
            {
                var valuesToProduce = literalLengthCodeCount + distanceCodeCount;

                var  valuesProduced    = 0;
                byte lastValueProduced = 0;

                while (valuesProduced < valuesToProduce)
                {
                    byte codeLength = 0;

                    uint branch = 0;
                    while (true)
                    {
                        var bit = data.CurrentBitValue();
                        branch = tree[branch * 2 + bit];

                        if (branch >= TreeNode.Threshold)
                        {
                            // Take lower bits
                            codeLength = (byte)branch;
                            break;
                        }
                    }

                    //0 - 15: Represent code lengths of 0 - 15
                    //    16: Copy the previous code length 3 - 6 times.
                    //        The next 2 bits indicate repeat length
                    //              (0 = 3, ... , 3 = 6)
                    //           Example: Codes 8, 16(+2 bits 11),
                    //                     16(+2 bits 10) will expand to
                    //                     12 code lengths of 8(1 + 6 + 5)
                    //    17: Repeat a code length of 0 for 3 - 10 times.
                    //        (3 bits of length)
                    //    18: Repeat a code length of 0 for 11 - 138 times
                    //        (7 bits of length)

                    if (codeLength == 18)
                    {
                        ProduceRepeat(0, 11, bitsAsRepeat: 7);
                    }
                    else if (codeLength == 17)
                    {
                        ProduceRepeat(0, 3, bitsAsRepeat: 3);
                    }
                    else if (codeLength == 16)
                    {
                        ProduceRepeat(lastValueProduced, 3, bitsAsRepeat: 2);
                    }
                    else
                    {
                        ProduceValue(codeLength);
                    }
                }
Beispiel #2
0
        private ushort TraverseTree(ushort *tree, BitSource bitsource)
        {
            uint  branch        = 0;
            uint  availableBits = 0;
            ulong bits          = 0;

            while (branch < TreeNode.Threshold)
            {
                ulong consumed = 0;
                availableBits = (uint)bitsource.AvailableBits();
                bits          = bitsource.PeekBits();

                while (availableBits > consumed && branch < TreeNode.Threshold)
                {
                    var bit = bits & 1;
                    bits >>= 1;
                    branch = tree[branch * 2 + bit];
                    consumed++;
                }

                bitsource.Consume(consumed);

                if (branch < TreeNode.Threshold)
                {
                    var bit = bitsource.CurrentBitValue();
                    branch = tree[branch * 2 + bit];
                }
            }

            return((ushort)branch);
        }
Beispiel #3
0
        public HuffmanTree(BitSource data)
        {
            this.data = data;

            // Read 5 bits for LiteralLengthCodeCount
            this.LiteralLengthCodeCount = (ushort)(data.ReadBitsAsUshort(5) + 257);

            // Read 5 bits for DistanceCodeCount
            this.DistanceCodeCount = (byte)(data.ReadBitsAsUshort(5) + 1);

            // Read 4 bits for CodeLengthCodeCount
            this.CodeLengthCodeCount = (byte)(data.ReadBitsAsUshort(4) + 4);

            // Read code length intermediate tree data

            byte *codeLengthCodes = stackalloc byte[19];
            byte *literalLengths  = stackalloc byte[AlphabetSize];
            byte *distanceLengths = stackalloc byte[DistanceValuesSize];

            for (var i = 0; i < this.CodeLengthCodeCount; i++)
            {
                codeLengthCodes[CodeLengthMapping[i]] = (byte)data.ReadBitsAsUshort(3);
            }

            // Generate intermediate tree
            uint *intermediateTree = stackalloc uint[19];

            GenerateTree(codeLengthCodes, (ushort *)intermediateTree, 19);
            CodeLengthHuffmanTree.ProduceLengths(
                data,
                (ushort *)intermediateTree,
                this.LiteralLengthCodeCount,
                this.DistanceCodeCount,
                literalLengths,
                distanceLengths);

            this.literalLengthTree         = NodePool.Rent(GetTreeLength(AlphabetSize), out var lenTreePtr);
            this.literalLengthTreeAsUshort = (ushort *)lenTreePtr;
            GenerateTree(
                literalLengths,
                this.literalLengthTreeAsUshort,
                AlphabetSize,
                DeflateConstants.LengthExtraBits,
                257);

            this.distanceTree         = NodePool.Rent(GetTreeLength(DistanceValuesSize), out var distTreePtr);
            this.distanceTreeAsUshort = (ushort *)distTreePtr;
            GenerateTree(
                distanceLengths,
                this.distanceTreeAsUshort,
                DistanceValuesSize,
                DeflateConstants.DistanceExtraBits);
        }
Beispiel #4
0
        public DeflateBlock(BitSource data)
        {
            this.Compressed = data;

            this.IsFinal = data.IsSet();

            this.Type = (BlockType)data.ReadBitsAsUshort(2);

            if (this.Type == BlockType.DynamicHuffmanCodes)
            {
                this.HuffmanTree = new HuffmanTree(data);
            }
            else if (this.Type == BlockType.FixedHuffmanCodes)
            {
                this.HuffmanTree = HuffmanTree.Fixed;
            }
            else
            {
                this.HuffmanTree = null;
            }
        }
Beispiel #5
0
 private static void Consume(ulong bits, BitSource b)
 {
     b.availableLocalBits -= bits;
     b.currentBit         += bits;
     b.localBits         >>= (int)bits;
 }