public void Finish() { if (_valueIndex != 0) { FinishBlock(); } _bitWriter.Write(0, 32); _bitWriter.Flush(); }
/// <summary> /// Will write everything to the given Stream/Writer. Call "Compress" first! /// </summary> public void Write() //Bug: Actually, finding all blocks and then writing all blocks is pretty stupid. By doing this we first have a CPU / RAM bottleneck, and here we get a Harddrive bottleneck. Doesn't matter if master weed does good parallel stuff though { var currentBlockIndex = 0; var valueCount = Values.Count; var blockCount = Blocks.Count; var nextStop = blockCount == 0 ? valueCount : Blocks[currentBlockIndex].Index; var hasExponent = !Metadata.NoExponent; var huffmanWriter = _huffman?.CreateWriter(Metadata.MaxNeededBitsExponent, _writer); var shouldUseHuffman = hasExponent && huffmanWriter != null && huffmanWriter.IsBetterThanDefault(valueCount - _totalPostCompressionOptimisationBlockValues, _huffman); // Writing global header Metadata.Write(_writer); shouldUseHuffman = false; //debug _writer.WriteByte(shouldUseHuffman ? (byte)1 : (byte)0, 1); if (shouldUseHuffman) { huffmanWriter.WriteDictionary(); } for (var i = 0; i < valueCount;) { for (; nextStop > i; i++) // writing values until the next block is here { var value = Values[i]; //Todo: is the loop below really nessecary with the new changes? while (value.NeededBitsNumber > Metadata.MaxNeededBitsNumber) //Todo: check how often this case appears. (This is a "bug" created by the blockfinding, which "corrects" the value to fit with the exp of a block that might get created ... { value.Number /= 10; value.Exponent++; value.NeededBitsNumber = value.Number.GetNeededBits(); } _writer.WriteByte(0, 1); if (!Metadata.IsAbsolute) { _writer.WriteByte((byte)(value.IsNegative ? 1 : 0), 1); } _writer.Write((ulong)value.Number, Metadata.MaxNeededBitsNumber); if (hasExponent) { _writer.WriteByte((byte)(value.Exponent < 0 ? 1 : 0), 1); if (shouldUseHuffman) { huffmanWriter.Write((ushort)Math.Abs(value.Exponent)); } else { _writer.Write((ulong)Math.Abs(value.Exponent), Metadata.MaxNeededBitsExponent); } } } if (++currentBlockIndex < blockCount) { // Console.WriteLine(Blocks[currentBlockIndex - 1]); Blocks[currentBlockIndex - 1].Method.Write(_writer, Blocks[currentBlockIndex - 1], ref i); nextStop = Blocks[currentBlockIndex].Index; } else { nextStop = valueCount; } } _writer.Flush(); // This is nessecary. Will write the last buffered byte may only be partially complete! }