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); } }
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); }
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); }
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; } }
private static void Consume(ulong bits, BitSource b) { b.availableLocalBits -= bits; b.currentBit += bits; b.localBits >>= (int)bits; }