private ReadOnlySequence <byte> ConcactSequence(ref ReadOnlySequence <byte> first, ref ReadOnlySequence <byte> second) { SequenceSegment head = first.Start.GetObject() as SequenceSegment; SequenceSegment tail = first.End.GetObject() as SequenceSegment; if (head == null) { foreach (var segment in first) { if (head == null) { tail = head = SequenceSegment.CopyFrom(segment); } else { tail = tail.SetNext(SequenceSegment.CopyFrom(segment)); } } } if (!second.IsEmpty) { foreach (var segment in second) { tail = tail.SetNext(SequenceSegment.CopyFrom(segment)); } } return(new ReadOnlySequence <byte>(head, 0, tail, tail.Memory.Length)); }
public void GlobalSetup() { var sb = new StringBuilder(); for (var i = 0; i < S; i++) { while (true) { sb.Append(Guid.NewGuid().ToString().Replace("-", string.Empty)); if (sb.Length >= N) { var data = _encoding.GetBytes(sb.ToString(0, N)); var segment = new SequenceSegment(data, data.Length); if (_head == null) { _tail = _head = segment; } else { _tail = _tail.SetNext(segment); } sb.Clear(); break; } } } }
public SequenceBuffer(int length) { var bytes = this.GetBuffer(length); this.startSegment = new SequenceSegment <byte>(bytes); this.sequence = new ReadOnlySequence <byte>(this.startSegment, 0, this.startSegment, this.startSegment.Memory.Length); }
private void MoveNext() { var firstSegment = _firstSegment; _firstSegmentStartIndex += (int)_jsonReader.BytesConsumed; // release previous segments if possible if (!_keepBuffers) { while (firstSegment?.Memory.Length <= _firstSegmentStartIndex) { _firstSegmentStartIndex -= firstSegment.Memory.Length; firstSegment.Dispose(); firstSegment = (SequenceSegment?)firstSegment.Next; } } // create new segment var newSegment = new SequenceSegment(_bufferSize, _lastSegment); if (firstSegment != null) { _firstSegment = firstSegment; newSegment.Previous = _lastSegment; _lastSegment?.SetNext(newSegment); _lastSegment = newSegment; } else { _firstSegment = _lastSegment = newSegment; _firstSegmentStartIndex = 0; } // read data from stream _lastSegmentEndIndex = _stream.Read(newSegment.Buffer.Memory.Span); _isFinalBlock = _lastSegmentEndIndex < newSegment.Buffer.Memory.Length; _jsonReader = new Utf8JsonReader(new ReadOnlySequence <byte>(_firstSegment, _firstSegmentStartIndex, _lastSegment, _lastSegmentEndIndex), _isFinalBlock, _jsonReader.CurrentState); }
/// <summary> /// Advances the sequence to include the specified number of elements initialized into memory /// returned by a prior call to <see cref="GetMemory(int)"/>. /// </summary> /// <param name="count">The number of elements written into memory.</param> public void Advance(int count) { SequenceSegment last = this.last; Debug.Assert(last != null, "Cannot advance before acquiring memory."); last.Advance(count); }
/// <summary> /// Advances the sequence to include the specified number of elements initialized into memory /// returned by a prior call to <see cref="GetMemory(int)"/>. /// </summary> /// <param name="count">The number of elements written into memory.</param> public void Advance(int count) { SequenceSegment last = this.last; Verify.Operation(last != null, "Cannot advance before acquiring memory."); last.Advance(count); }
/// <summary> /// Advances the sequence to include the specified number of elements initialized into memory /// returned by a prior call to <see cref="GetMemory(int)"/>. /// </summary> /// <param name="count">The number of elements written into memory.</param> public void Advance(int count) { SequenceSegment last = this.last; Verify.Operation(last != null, "Cannot advance before acquiring memory."); last.Advance(count); this.ConsiderMinimumSizeIncrease(); }
private SequenceSegment RecycleAndGetNext(SequenceSegment segment) { Sequence <T> .SequenceSegment recycledSegment = segment; Sequence <T> .SequenceSegment nextSegment = segment.Next; recycledSegment.ResetMemory(this.arrayPool); this.segmentPool.Push(recycledSegment); return(nextSegment); }
private SequenceSegment RecycleAndGetNext(SequenceSegment segment) { var recycledSegment = segment; segment = segment.Next; recycledSegment.ResetMemory(); this.segmentPool.Push(recycledSegment); return(segment); }
public bool DeleteSequenceSegment(SequenceSegment sequencesegment) { if (_sequenceSegments.ContainsKey(sequencesegment.TrackSolutionID) && _sequenceSegments[sequencesegment.TrackSolutionID].ContainsKey(sequencesegment.ID)) { return(NativeMethods.mta_sequencesegment_delete(_nativeHandle, sequencesegment.ID)); } return(false); }
public SequenceSegment(int size, SequenceSegment previous) { Buffer = MemoryPool <byte> .Shared.Rent(size); Previous = previous; Memory = Buffer.Memory; RunningIndex = previous?.RunningIndex + previous?.Memory.Length ?? 0; }
/// <summary> /// Returns a string which represents specified SequenceSegment. /// </summary> /// <param name="segment">SequenceSegment instance.</param> /// <returns>Returns string.</returns> public static string GetSequenceSegment(SequenceSegment segment) { if (segment == null) { throw new ArgumentNullException("segment"); } return(segment.Current.ToString(CultureInfo.InvariantCulture) + SegmentDelim + segment.Count.ToString(CultureInfo.InvariantCulture)); }
/// <summary> /// Clears the entire sequence and recycles associated memory into pools. /// This invalidates any <see cref="ReadOnlySequence{T}"/> previously produced by this instance. /// </summary> public void Reset() { Sequence <T> .SequenceSegment current = this.first; while (current != null) { current = this.RecycleAndGetNext(current); } this.first = this.last = null; }
/// <summary> /// Clears the entire sequence and recycles associated memory into pools. /// This invalidates any <see cref="ReadOnlySequence{T}"/> previously produced by this instance. /// </summary> public void Reset() { var current = this.first; while (current != null) { current = this.RecycleAndGetNext(current); } this.first = this.last = null; }
public new async ValueTask SendAsync(ReadOnlyMemory <byte> data) { var package = new WebSocketPackage(); package.OpCode = OpCode.Binary; var sequenceElement = new SequenceSegment(data); package.Data = new ReadOnlySequence <byte>(sequenceElement, 0, sequenceElement, sequenceElement.Memory.Length); await SendAsync(_packageEncoder, package); }
/// <summary> /// Request a modifier to change a SequenceSegment configuration /// </summary> /// <param name="sequencesegment"> /// Instance to be updated/changed /// </param> /// <exception cref="MylapsException"> /// Throws an exception whenever it failes to create a SequenceSegmentModifier instance /// </exception> /// <remarks> /// To commit the changes, use MTA.CommitChanges() /// </remarks> public SequenceSegmentModifier UpdateSequenceSegment(SequenceSegment sequencesegment) { if (_sequenceSegments.ContainsKey(sequencesegment.TrackSolutionID) && _sequenceSegments[sequencesegment.TrackSolutionID].ContainsKey(sequencesegment.ID)) { var p = NativeMethods.mta_sequencesegment_update(_nativeHandle, sequencesegment.ID); return(AddSequenceSegmentModifier(p)); } throw new MylapsException("failed to create a SequenceSegmentModifier, sequencesegment ID:" + sequencesegment.ID + " in tracksolution ID:" + sequencesegment.TrackSolutionID + " is unknown"); }
public void TryParseFrame_ShouldReturnTrue_OnTwoCompleteMessage() { var firstFrame = _createMessage(150); var secondFrame = _createMessage(160); var firstSegment = new SequenceSegment(firstFrame); var secondSegment = firstSegment.Add(secondFrame); var fullFrame = new ReadOnlySequence <byte>( firstSegment, 0, secondSegment, 8); Assert.True(_frameParser.TryParseFrame(ref fullFrame, out var firstMessage)); Assert.True(_frameParser.TryParseFrame(ref fullFrame, out var secondMessage)); }
public Utf8JsonStreamReader(Stream stream, int bufferSize) { _stream = stream; _bufferSize = bufferSize; _firstSegment = null; _firstSegmentStartIndex = 0; _lastSegment = null; _lastSegmentEndIndex = -1; _jsonReader = default; _keepBuffers = false; _isFinalBlock = false; }
/// <summary> /// Removes all elements from the sequence from its beginning to the specified position, /// considering that data to have been fully processed. /// </summary> /// <param name="position"> /// The position of the first element that has not yet been processed. /// This is typically <see cref="ReadOnlySequence{T}.End"/> after reading all elements from that instance. /// </param> public void AdvanceTo(SequencePosition position) { var firstSegment = (SequenceSegment)position.GetObject(); int firstIndex = position.GetInteger(); // Before making any mutations, confirm that the block specified belongs to this sequence. var current = this.first; while (current != firstSegment && current != null) { current = current.Next; } if (current == null) { ThrowCurrentNull(); } void ThrowCurrentNull() => throw new ArgumentException("Position does not represent a valid position in this sequence.", nameof(position)); // Also confirm that the position is not a prior position in the block. if (firstIndex < current.Start) { ThrowEarlierPosition(); } void ThrowEarlierPosition() => throw new ArgumentException("Position must not be earlier than current position.", nameof(position)); // Now repeat the loop, performing the mutations. current = this.first; while (current != firstSegment) { var next = current.Next; current.ResetMemory(); current = next; } firstSegment.AdvanceTo(firstIndex); if (firstSegment.Length == 0) { firstSegment = this.RecycleAndGetNext(firstSegment); } this.first = firstSegment; if (this.first == null) { this.last = null; } }
private void MoveNext() { _firstSegmentStartIndex += (int)_jsonReader.BytesConsumed; // release previous segments if possible while (_firstSegmentStartIndex > 0 && _firstSegment?.Memory.Length <= _firstSegmentStartIndex) { var currFirstSegment = _firstSegment; _firstSegmentStartIndex -= _firstSegment.Memory.Length; _firstSegment = (SequenceSegment?)_firstSegment.Next; if (!_keepBuffers) { currFirstSegment.Dispose(); } } // create new segment var newSegment = new SequenceSegment(_bufferSize, _lastSegment); _lastSegment?.SetNext(newSegment); _lastSegment = newSegment; if (_firstSegment == null) { _firstSegment = newSegment; _firstSegmentStartIndex = 0; } // read data from stream _lastSegmentEndIndex = 0; int bytesRead; do { #if NET bytesRead = _stream.Read(newSegment.Buffer.Memory.Span.Slice(_lastSegmentEndIndex)); #else var bytes = newSegment.Buffer.Memory.Span.Slice(_lastSegmentEndIndex).ToArray(); bytesRead = _stream.Read(bytes, 0, bytes.Length); #endif _lastSegmentEndIndex += bytesRead; } while (bytesRead > 0 && _lastSegmentEndIndex < newSegment.Buffer.Memory.Length); _isFinalBlock = _lastSegmentEndIndex < newSegment.Buffer.Memory.Length; var data = new ReadOnlySequence <byte>(_firstSegment, _firstSegmentStartIndex, _lastSegment, _lastSegmentEndIndex); _jsonReader = new Utf8JsonReader(data, _isFinalBlock, _jsonReader.CurrentState); }
internal void ConcatSequence(ref ReadOnlySequence <byte> second) { if (Head == null) { (Head, Tail) = second.DestructSequence(); return; } if (!second.IsEmpty) { foreach (var segment in second) { Tail = Tail.SetNext(new SequenceSegment(segment)); } } }
private void Append(IMemoryOwner <T> array) { if (array == null) { ThrowNull(); } var segment = this.segmentPool.Count > 0 ? this.segmentPool.Pop() : new SequenceSegment(); segment.SetMemory(array, 0, 0); if (this.last == null) { this.first = this.last = segment; } else { if (this.last.Length > 0) { // Add a new block. this.last.SetNext(segment); } else { // The last block is completely unused. Replace it instead of appending to it. var current = this.first; if (this.first != this.last) { while (current.Next != this.last) { current = current.Next; } } else { this.first = segment; } current.SetNext(segment); this.RecycleAndGetNext(this.last); } this.last = segment; } void ThrowNull() => throw new ArgumentNullException(nameof(array)); }
internal void ConcatSequence(ref ReadOnlySequence <byte> second) { if (Head == null) { (Head, Tail) = second.DestructSequence(); Console.WriteLine($"Reset Head:{this.GetHashCode()}"); return; } if (!second.IsEmpty) { foreach (var segment in second) { Tail = Tail.SetNext(new SequenceSegment(segment)); } } }
/// <summary> /// Removes all elements from the sequence from its beginning to the specified position, /// considering that data to have been fully processed. /// </summary> /// <param name="position"> /// The position of the first element that has not yet been processed. /// This is typically <see cref="ReadOnlySequence{T}.End"/> after reading all elements from that instance. /// </param> public void AdvanceTo(SequencePosition position) { var firstSegment = (SequenceSegment)position.GetObject(); if (firstSegment == null) { // Emulate PipeReader behavior which is to just return for default(SequencePosition) return; } if (ReferenceEquals(firstSegment, SequenceSegment.Empty) && this.Length == 0) { // We were called with our own empty buffer segment. return; } int firstIndex = position.GetInteger(); // Before making any mutations, confirm that the block specified belongs to this sequence. Sequence <T> .SequenceSegment current = this.first; while (current != firstSegment && current != null) { current = current.Next; } Requires.Argument(current != null, nameof(position), "Position does not represent a valid position in this sequence."); // Also confirm that the position is not a prior position in the block. Requires.Argument(firstIndex >= current.Start, nameof(position), "Position must not be earlier than current position."); // Now repeat the loop, performing the mutations. current = this.first; while (current != firstSegment) { current = this.RecycleAndGetNext(current); } firstSegment.AdvanceTo(firstIndex); this.first = firstSegment.Length == 0 ? this.RecycleAndGetNext(firstSegment) : firstSegment; if (this.first == null) { this.last = null; } }
private void NotifySequenceSegments(IntPtr handle, MDP_NOTIFY_TYPE nType, IntPtr sequencsegmentearray, uint count, IntPtr context) { var sequenceSegments = SequenceSegment.FromNativePointerArray(sequencsegmentearray, count, _mta); switch (nType) { case MDP_NOTIFY_TYPE.MDP_NOTIFY_SELECT: case MDP_NOTIFY_TYPE.MDP_NOTIFY_INSERT: case MDP_NOTIFY_TYPE.MDP_NOTIFY_UPDATE: sequenceSegments.ForEach(sequenceSegment => { if (!_sequenceSegments.ContainsKey(sequenceSegment.TrackSolutionID)) { _sequenceSegments[sequenceSegment.TrackSolutionID] = new SortedDictionary <uint, SequenceSegment>(); } _sequenceSegments[sequenceSegment.TrackSolutionID][sequenceSegment.ID] = sequenceSegment; }); _allSequenceSegmentDataAvailable = true; break; case MDP_NOTIFY_TYPE.MDP_NOTIFY_DELETE: sequenceSegments.ForEach(sequenceSegment => { if (_sequenceSegments.ContainsKey(sequenceSegment.TrackSolutionID)) { _sequenceSegments[sequenceSegment.TrackSolutionID].Remove(sequenceSegment.ID); if (_sequenceSegments[sequenceSegment.TrackSolutionID].Count == 0) { _sequenceSegments.Remove(sequenceSegment.TrackSolutionID); } } }); break; case MDP_NOTIFY_TYPE.MDP_NOTIFY_CLEAR: _allSequenceSegmentDataAvailable = false; _sequenceSegments.Clear(); break; } if (NotifySequenceSegmentHandlers != null) { NotifySequenceSegmentHandlers(nType, sequenceSegments, _mta); } }
public void TryRead_ShouldReturnTrue_OnSegmentSplitted() { var buffer = _createBuffer(); var firstSegment = new SequenceSegment(buffer.Slice(0, 4)); var secondSegment = firstSegment.Add(buffer.Slice(4, 4)); var input = new ReadOnlySequence <byte>( firstSegment, 0, secondSegment, 4); var reader = new SequenceReader(input); reader.TryRead(BinaryPrimitives.ReadInt32LittleEndian, out var firstValue); reader.TryRead(BinaryPrimitives.ReadInt32LittleEndian, out var secondValue); Assert.Equal(_firstValue, firstValue); Assert.Equal(_secondValue, secondValue); }
public void Decode(WebSocketPackage package) { if (!package.RSV1) { return; } var data = package.Data; data = data.ConcatSequence(new SequenceSegment(LAST_FOUR_OCTETS_REVERSE, LAST_FOUR_OCTETS_REVERSE.Length, false)); SequenceSegment head = null; SequenceSegment tail = null; using (var stream = new DeflateStream(new ReadOnlySequenceStream(data), CompressionMode.Decompress)) { while (true) { var buffer = _arrayPool.Rent(_deflateBufferSize); var read = stream.Read(buffer, 0, buffer.Length); if (read == 0) { break; } var segment = new SequenceSegment(buffer, read); if (head == null) { tail = head = segment; } else { tail.SetNext(segment); } } } package.Data = new ReadOnlySequence <byte>(head, 0, tail, tail.Memory.Length); }
private void Append(SequenceSegment segment) { if (this.last == null) { this.first = this.last = segment; } else { if (this.last.Length > 0) { // Add a new block. this.last.SetNext(segment); } else { // The last block is completely unused. Replace it instead of appending to it. var current = this.first; if (current is null) { throw new NullReferenceException(nameof(this.first)); } if (this.first != this.last) { while (current.Next != this.last) { current = current.Next; } } else { this.first = segment; } current.SetNext(segment); this.RecycleAndGetNext(this.last); } this.last = segment; } }
private ReadOnlySequence <byte> CopySequence(ref ReadOnlySequence <byte> seq) { SequenceSegment head = null; SequenceSegment tail = null; foreach (var segment in seq) { var newSegment = SequenceSegment.CopyFrom(segment); if (head == null) { tail = head = newSegment; } else { tail = tail.SetNext(newSegment); } } return(new ReadOnlySequence <byte>(head, 0, tail, tail.Memory.Length)); }
private void DeserialisePost() { // release memory if possible var firstSegment = _firstSegment; var firstSegmentStartIndex = _firstSegmentStartIndex + (int)_jsonReader.BytesConsumed; while (firstSegment?.Memory.Length < firstSegmentStartIndex) { firstSegmentStartIndex -= firstSegment.Memory.Length; firstSegment.Dispose(); firstSegment = (SequenceSegment)firstSegment.Next; } if (firstSegment != _firstSegment) { _firstSegment = firstSegment; _firstSegmentStartIndex = firstSegmentStartIndex; var data = new ReadOnlySequence <byte>(_firstSegment, _firstSegmentStartIndex, _lastSegment, _lastSegmentEndIndex); _jsonReader = new Utf8JsonReader(data, _isFinalBlock, _jsonReader.CurrentState); } }