internal void Append(ReadableBuffer buffer) { if (buffer.IsEmpty) { return; // nothing to do } EnsureAlloc(); var clonedBegin = BufferSegment.Clone(buffer.Start, buffer.End, out BufferSegment clonedEnd); if (_writingHead == null) { // No active write lock (_sync) { if (_commitHead == null) { // No allocated buffers yet, not locking as _readHead will be null _commitHead = clonedBegin; } else { Debug.Assert(_commitHead.Next == null); // Allocated buffer, append as next segment _commitHead.SetNext(clonedBegin); } } } else { Debug.Assert(_writingHead.Next == null); // Active write, append as next segment _writingHead.SetNext(clonedBegin); } // Move write head to end of buffer _writingHead = clonedEnd; _currentWriteLength += buffer.Length; }
/// <summary> /// Checks to see if the <see cref="ReadableBuffer"/> is Equal to the specified <see cref="Span{Byte}"/>. /// </summary> /// <param name="value">The <see cref="Span{Byte}"/> to compare to</param> /// <returns>True if the bytes are equal, false if not</returns> public static bool EqualsTo(this ReadableBuffer buffer, Span <byte> value) { if (value.Length != buffer.Length) { return(false); } if (buffer.IsSingleSpan) { return(buffer.First.Span.SequenceEqual(value)); } foreach (var memory in buffer) { var compare = value.Slice(0, memory.Length); if (!memory.Span.SequenceEqual(compare)) { return(false); } value = value.Slice(memory.Length); } return(true); }
/// <summary> /// This transfers ownership of the buffer from the <see cref="IPipelineReader"/> to the caller of this method. Preserved buffers must be disposed to avoid /// memory leaks. /// </summary> public PreservedBuffer Preserve() { var buffer = new ReadableBuffer(ref this); return(new PreservedBuffer(ref buffer)); }
/// <summary> /// Searches for a byte in the <see cref="ReadableBuffer"/> and returns a sliced <see cref="ReadableBuffer"/> that /// contains all data up to and excluding the byte, and a <see cref="ReadCursor"/> that points to the byte. /// </summary> /// <param name="b1">The first byte to search for</param> /// <param name="slice">A <see cref="ReadableBuffer"/> slice that contains all data up to and excluding the first byte.</param> /// <param name="cursor">A <see cref="ReadCursor"/> that points to the second byte</param> /// <returns>True if the byte sequence was found, false if not found</returns> public bool TrySliceTo(byte b1, out ReadableBuffer slice, out ReadCursor cursor) { if (IsEmpty) { slice = default(ReadableBuffer); cursor = default(ReadCursor); return(false); } var byte0Vector = CommonVectors.GetVector(b1); var seek = 0; foreach (var memory in this) { var currentSpan = memory.Span; var found = false; if (Vector.IsHardwareAccelerated) { while (currentSpan.Length >= VectorWidth) { var data = currentSpan.Read <Vector <byte> >(); var byte0Equals = Vector.Equals(data, byte0Vector); if (byte0Equals.Equals(Vector <byte> .Zero)) { currentSpan = currentSpan.Slice(VectorWidth); seek += VectorWidth; } else { var index = FindFirstEqualByte(ref byte0Equals); seek += index; found = true; break; } } } if (!found) { // Slow search for (int i = 0; i < currentSpan.Length; i++) { if (currentSpan[i] == b1) { found = true; break; } seek++; } } if (found) { cursor = _start.Seek(seek); slice = Slice(_start, cursor); return(true); } } slice = default(ReadableBuffer); cursor = default(ReadCursor); return(false); }
/// <summary> /// Appends the <see cref="ReadableBuffer"/> to the <see cref="WritableBuffer"/> in-place without copies. /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to append</param> public void Append(ReadableBuffer buffer) { Pipe.Append(buffer); }
public ReadableBufferSequence(ReadableBuffer buffer) : this() { _buffer = buffer; }
/// <summary> /// Searches for 2 sequential bytes in the <see cref="ReadableBuffer"/> and returns a sliced <see cref="ReadableBuffer"/> that /// contains all data up to and excluding the first byte, and a <see cref="ReadCursor"/> that points to the second byte. /// </summary> /// <param name="b1">The first byte to search for</param> /// <param name="b2">The second byte to search for</param> /// <param name="slice">A <see cref="ReadableBuffer"/> slice that contains all data up to and excluding the first byte.</param> /// <param name="cursor">A <see cref="ReadCursor"/> that points to the second byte</param> /// <returns>True if the byte sequence was found, false if not found</returns> public static unsafe bool TrySliceTo(this ReadableBuffer buffer, byte b1, byte b2, out ReadableBuffer slice, out ReadCursor cursor) { // use address of ushort rather than stackalloc as the inliner won't inline functions with stackalloc ushort twoBytes; byte * byteArray = (byte *)&twoBytes; byteArray[0] = b1; byteArray[1] = b2; return(buffer.TrySliceTo(new Span <byte>(byteArray, 2), out slice, out cursor)); }
public ReadableBufferReader(ReadableBuffer buffer) : this(buffer.Start, buffer.End) { }
internal PreservedBuffer(ref ReadableBuffer buffer) { _buffer = buffer; }
protected abstract Task WriteAsync(ReadableBuffer buffer);
/// <summary> /// Appends the <see cref="ReadableBuffer"/> to the <see cref="WritableBuffer"/> in-place without copies. /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to append</param> public void Append(ReadableBuffer buffer) { _output.Append(buffer); }