private int ReadTimeStamp(BitsBuffer bitsBuffer) { if (_bitsPosisition == 0) { _previousTimeStamp = (int)bitsBuffer.ReadValue(ref _bitsPosisition, BitsForFirstTimestamp); _previousTimeStampDelta = DefaultDelta; return(_previousTimeStamp); } var type = bitsBuffer.FindTheFirstZeroBit(ref _bitsPosisition, TimestampEncodingDetails.MaxControlBitLength); if (type > 0) { var index = type - 1; ref var encoding = ref TimestampEncodingDetails.Encodings[index]; long decodedValue = (long)bitsBuffer.ReadValue(ref _bitsPosisition, encoding.BitsForValue); // [0, 255] becomes [-128, 127] decodedValue -= encoding.MaxValueForEncoding; if (decodedValue >= 0) { // [-128, 127] becomes [-128, 128] without the zero in the middle decodedValue++; } _previousTimeStampDelta += (int)decodedValue; }
private void ReadValues(Span <StatefulTimeStampValue> values, ref BitsBuffer bitsBuffer) { for (int i = 0; i < values.Length; i++) { var nonZero = bitsBuffer.ReadValue(ref _bitsPosisition, 1); if (nonZero == 0) { continue; // no change since last time } var usePreviousBlockInfo = bitsBuffer.ReadValue(ref _bitsPosisition, 1); long xorValue; if (usePreviousBlockInfo == 1) { xorValue = (long)bitsBuffer.ReadValue(ref _bitsPosisition, 64 - values[i].LeadingZeroes - values[i].TrailingZeroes); xorValue <<= values[i].TrailingZeroes; } else { int leadingZeros = (int)bitsBuffer.ReadValue(ref _bitsPosisition, LeadingZerosLengthBits); int blockSize = (int)bitsBuffer.ReadValue(ref _bitsPosisition, BlockSizeLengthBits) + BlockSizeAdjustment; int trailingZeros = 64 - blockSize - leadingZeros; xorValue = (long)bitsBuffer.ReadValue(ref _bitsPosisition, blockSize); xorValue <<= trailingZeros; values[i].TrailingZeroes = (byte)trailingZeros; values[i].LeadingZeroes = (byte)leadingZeros; } values[i].LongValue = values[i].LongValue ^ xorValue; } }
private static void AddValue(ref StatefulTimeStampValue prev, ref BitsBuffer bitsBuffer, double dblVal) { long val = BitConverter.DoubleToInt64Bits(dblVal); ulong xorWithPrevious = (ulong)(prev.LongValue ^ val); if (xorWithPrevious == 0) { // It's the same value. bitsBuffer.AddValue(0, 1); return; } bitsBuffer.AddValue(1, 1); var leadingZeroes = Bits.LeadingZeroes(xorWithPrevious); var trailingZeroes = Bits.TrailingZeroesInBytes(xorWithPrevious); if (leadingZeroes > MaxLeadingZerosLength) { leadingZeroes = MaxLeadingZerosLength; } var useful = 64 - leadingZeroes - trailingZeroes; var prevUseful = 64 - prev.LeadingZeroes - prev.TrailingZeroes; var expectedSize = LeadingZerosLengthBits + BlockSizeLengthBits + useful; if (leadingZeroes >= prev.LeadingZeroes && trailingZeroes >= prev.TrailingZeroes && prevUseful < expectedSize) { // Control bit saying we should use the previous block information bitsBuffer.AddValue(1, 1); // Write the parts of the value that changed. ulong blockValue = xorWithPrevious >> prev.TrailingZeroes; bitsBuffer.AddValue(blockValue, prevUseful); } else { bitsBuffer.AddValue(0, 1); bitsBuffer.AddValue((ulong)leadingZeroes, LeadingZerosLengthBits); bitsBuffer.AddValue((ulong)(useful - BlockSizeAdjustment), BlockSizeLengthBits); ulong blockValue = xorWithPrevious >> trailingZeroes; bitsBuffer.AddValue(blockValue, useful); prev.LeadingZeroes = (byte)leadingZeroes; prev.TrailingZeroes = (byte)trailingZeroes; } prev.DoubleValue = dblVal; }
public bool Append(int deltaFromStart, Span <double> vals, Span <byte> tag) { if (vals.Length != Header->NumberOfValues) { ThrowInvalidNumberOfValues(vals); } var actualBitsBuffer = GetBitsBuffer(); var maximumSize = sizeof(BitsBufferHeader) + sizeof(int) + // max timestamp sizeof(double) * vals.Length + tag.Length + 1 + 1 + // alignment to current buffer 8; // extra buffer that should never be used var tempBuffer = stackalloc byte[maximumSize]; var tempHeader = stackalloc SegmentHeader[1]; *tempHeader = *Header; var tempBitsBuffer = new BitsBuffer(tempBuffer, maximumSize); var prevs = new Span <StatefulTimeStampValue>(_buffer + sizeof(SegmentHeader), Header->NumberOfValues); AddTimeStamp(deltaFromStart, ref tempBitsBuffer, tempHeader); for (int i = 0; i < vals.Length; i++) { AddValue(ref prevs[i], ref tempBitsBuffer, vals[i]); } WriteTag(tag, ref tempBitsBuffer, tempHeader, actualBitsBuffer.NumberOfBits); Debug.Assert(tempBitsBuffer.NumberOfBits / 8 < maximumSize - 8, "Wrote PAST END OF BUFFER!"); tempHeader->PreviousTimeStamp = deltaFromStart; tempHeader->NumberOfEntries++; if (actualBitsBuffer.AddBits(tempBitsBuffer) == false) { return(false); } *Header = *tempHeader; return(true); }
internal bool AddBits(BitsBuffer tempBitsBuffer) { if (HasAdditionalBits(tempBitsBuffer.NumberOfBits) == false) { return(false); } int read = 0; while (read < tempBitsBuffer.NumberOfBits) { var toRead = Math.Min(64, tempBitsBuffer.NumberOfBits - read); var result = tempBitsBuffer.ReadValue(ref read, toRead); AddValue(result, toRead); } return(true); }
private static void AddTimeStamp(int deltaFromStart, ref BitsBuffer bitsBuffer, SegmentHeader *tempHeader) { if (tempHeader->NumberOfEntries == 0) { bitsBuffer.AddValue((ulong)deltaFromStart, BitsForFirstTimestamp); tempHeader->PreviousDelta = DefaultDelta; return; } int delta = deltaFromStart - tempHeader->PreviousTimeStamp; int deltaOfDelta = delta - tempHeader->PreviousDelta; if (deltaOfDelta == 0) { bitsBuffer.AddValue(0, 1); return; } if (deltaOfDelta > 0) { // There are no zeros. Shift by one to fit in x number of bits deltaOfDelta--; } int absValue = Math.Abs(deltaOfDelta); foreach (var timestampEncoding in TimestampEncodingDetails.Encodings) { if (absValue < timestampEncoding.MaxValueForEncoding) { bitsBuffer.AddValue((ulong)timestampEncoding.ControlValue, timestampEncoding.ControlValueBitLength); // Make this value between [0, 2^timestampEncodings[i].bitsForValue - 1] long encodedValue = deltaOfDelta + timestampEncoding.MaxValueForEncoding; bitsBuffer.AddValue((ulong)encodedValue, timestampEncoding.BitsForValue); break; } } tempHeader->PreviousTimeStamp = deltaFromStart; tempHeader->PreviousDelta = delta; }
public TagEnumerator(BitsBuffer bitsBuffer, int previousTagPos) { _bitsBuffer = bitsBuffer; _previousTagPos = previousTagPos; }
private void WriteTag(Span <byte> tag, ref BitsBuffer tempBitsBuffer, SegmentHeader *tempHeader, int baseNumberOfBits) { if (tag.Length > byte.MaxValue) { ThrowInvalidTagLength(); } var actualBitsBuffer = GetBitsBuffer(); int a = 136; var r = actualBitsBuffer.ReadValue(ref a, 11); var tagEnum = new TagEnumerator(actualBitsBuffer /* need to read the previous values */, tempHeader->PreviousTagPosition); if (tagEnum.TryGetPrevious(out var prevTag, out var previousIndex)) { if (prevTag.SequenceEqual(tag)) { tempBitsBuffer.AddValue(0, 1); // reuse previous buffer return; } // go back a maximum of 8 tags, to avoid N**2 operations // after 8 tags, we'll just write the tag again for (int i = 0; i < 8; i++) { if (tagEnum.TryGetPrevious(out prevTag, out previousIndex) == false) { break; } if (prevTag.SequenceEqual(tag)) { tempBitsBuffer.AddValue(1, 1); tempBitsBuffer.AddValue((ulong)previousIndex, BitsForTagLen); if (previousIndex != 0) { // re-arrange the previous pointer for the previous value // to point to the current one actualBitsBuffer.SetBits( (previousIndex + 1 + tag.Length) * 8, tempHeader->PreviousTagPosition, BitsForTagLen ); tempHeader->PreviousTagPosition = (ushort)previousIndex; } return; } } } tempBitsBuffer.AddValue(1, 1); int currentBitPosition = baseNumberOfBits + tempBitsBuffer.NumberOfBits + BitsForTagLen; int currentTagPosition = GetByteIndex(currentBitPosition); var bitsToSkip = ToByteAlignment(currentBitPosition); tempBitsBuffer.AddValue((ulong)currentTagPosition, BitsForTagLen); tempBitsBuffer.Header->BitsPosition += (ushort)bitsToSkip; tempBitsBuffer.AddValue((ulong)tag.Length, 8); for (int i = 0; i < tag.Length; i++) { tempBitsBuffer.AddValue(tag[i], 8); } tempBitsBuffer.AddValue(tempHeader->PreviousTagPosition, BitsForTagLen); tempHeader->PreviousTagPosition = (ushort)(currentTagPosition); }