예제 #1
0
        public void Finish()
        {
            if (_valueIndex != 0)
            {
                FinishBlock();
            }

            _bitWriter.Write(0, 32);
            _bitWriter.Flush();
        }
예제 #2
0
        /// <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!
        }