public void ReadOnlyFrontBytesEnumeration() { for (int i = 0; i < 7; i++) { var multibytes = Parse("A|CD|EFG"); multibytes = multibytes.Slice(0, i); { Collections.Sequences.Position position = multibytes.First; var length = 0; while (multibytes.TryGet(ref position, out ReadOnlyMemory <byte> segment)) { length += segment.Length; } Assert.Equal(i, length); } //{ // var length = 0; // foreach (var segment in multibytes) // { // length += segment.Length; // } // Assert.Equal(i, length); //} } }
public void ReadOnlyBytesEnumeration() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6 }; var bytes = new ReadOnlyBytes(buffer); Collections.Sequences.Position position = bytes.First; int length = 0; ReadOnlyMemory <byte> segment; while (bytes.TryGet(ref position, out segment)) { length += segment.Length; } Assert.Equal(buffer.Length, length); var multibytes = Parse("A|CD|EFG"); position = multibytes.First; length = 0; while (multibytes.TryGet(ref position, out segment)) { length += segment.Length; } Assert.Equal(6, length); }
public ReadWriteBytes(Collections.Sequences.Position first, Collections.Sequences.Position last) { (_start, _startIndex) = first.Get <object>(); (_end, _endIndex) = last.Get <object>(); Validate(); }
Collections.Sequences.Position? AdvanceToDelimiter(byte value) { var unread = Unread; var index = unread.IndexOf(value); if (index != -1) { _currentSpanIndex += index; var result = _currentSegmentPosition + _currentSpanIndex; _currentSpanIndex++; // skip delimiter return(result); } var nextPosition = _nextSegmentPosition; var currentPosition = _currentSegmentPosition; var previousPosition = _nextSegmentPosition; while (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory)) { var span = memory.Span; index = span.IndexOf(value); if (index != -1) { _currentSegmentPosition = previousPosition; _currentSpan = span; _currentSpanIndex = index + 1; return(_currentSegmentPosition + index); } previousPosition = _nextSegmentPosition; } _nextSegmentPosition = nextPosition; _currentSegmentPosition = currentPosition; return(null); }
public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemory <byte> item, bool advance = true) { var result = TryGet(ref position, out Memory <byte> memory, advance); item = memory; return(result); }
public int CopyTo(Span <byte> buffer) { int copied = 0; Collections.Sequences.Position position = default; var free = buffer; while (TryGet(ref position, out ReadOnlyMemory <byte> segment, true)) { if (segment.Length > free.Length) { segment.Span.Slice(0, free.Length).CopyTo(free); copied += free.Length; } else { segment.Span.CopyTo(free); copied += segment.Length; } free = buffer.Slice(copied); if (free.Length == 0) { break; } } return(copied); }
public BufferReader(ReadOnlySpan <byte> bytes) { _bytes = default; _nextSegmentPosition = default; _currentSegmentPosition = 0; _currentSpan = bytes; _currentSpanIndex = 0; }
public static bool TryParse <TSequence>(TSequence sequence, out int value, out Collections.Sequences.Position consumed) where TSequence : ISequence <ReadOnlyMemory <byte> > { if (!TryParse(sequence, out value, out int consumedBytes)) { consumed = default; return(false); } consumed = sequence.PositionAt(consumedBytes).GetValueOrDefault(); return(true); }
public static string Utf8ToString <TSequence>(this TSequence bytes) where TSequence : ISequence <ReadOnlyMemory <byte> > { var sb = new StringBuilder(); Collections.Sequences.Position position = bytes.First; while (bytes.TryGet(ref position, out ReadOnlyMemory <byte> segment)) { sb.Append(new Utf8Span(segment.Span).ToString()); } return(sb.ToString()); }
public static ReadOnlySpan <byte> ToSpan <T>(this T sequence) where T : ISequence <ReadOnlyMemory <byte> > { Collections.Sequences.Position position = sequence.First; ResizableArray <byte> array = new ResizableArray <byte>(1024); while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> buffer)) { array.AddAll(buffer.Span); } array.Resize(array.Count); return(array.Span.Slice(0, array.Count)); }
public void Advance(Collections.Sequences.Position position) { _currentSegmentPosition = position; _nextSegmentPosition = position; if (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory)) { _currentSpan = memory.Span; } else { _currentSpan = default; } _currentSpanIndex = 0; }
// TODO: should there be a ctor that takes sequence + position? // TODO: should there be a type that is sequence + position? public BufferReader(TSequence bytes) { _bytes = bytes; _nextSegmentPosition = bytes.First; _currentSegmentPosition = _nextSegmentPosition; if (_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory <byte> memory)) { _currentSpan = memory.Span; } else { _currentSpan = ReadOnlySpan <byte> .Empty; } _currentSpanIndex = 0; }
public bool TryGet(ref Collections.Sequences.Position position, out Memory <byte> item, bool advance = true) { if (position == default) { item = default; return(false); } var(list, index) = position.Get <MemoryList>(); item = list._data.Slice(index); if (advance) { position = Collections.Sequences.Position.Create(list._next); } return(true); }
public ReadWriteBytes Slice(Collections.Sequences.Position position) { var kind = Kind; switch (kind) { case Type.Array: var(array, index) = position.Get <byte[]>(); return(new ReadWriteBytes(array, index, array.Length - index)); case Type.MemoryList: return(Slice(position, Collections.Sequences.Position.Create((IMemoryList <byte>)_end, _endIndex))); default: throw new NotImplementedException(); } }
// TODO: this cannot be an extension method (as I would like it to be). // If I make it an extensions method, the compiler complains Span<T> cannot // be used as a type parameter. public static long IndexOf <TSequence>(TSequence sequence, byte value) where TSequence : ISequence <ReadOnlyMemory <byte> > { Collections.Sequences.Position position = sequence.First; int totalIndex = 0; while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory)) { var index = memory.Span.IndexOf(value); if (index != -1) { return(index + totalIndex); } totalIndex += memory.Length; } return(-1); }
public bool TryGet(ref Collections.Sequences.Position position, out Memory <byte> item, bool advance = true) { if (position == default) { item = default; return(false); } var array = _start as byte[]; if (array != null) { var start = _startIndex + (int)position; var length = _endIndex - _startIndex - (int)position; item = new Memory <byte>(array, start, length); if (advance) { position = default; } return(true); } if (Kind == Type.MemoryList) { var(node, index) = position.Get <IMemoryList <byte> >(); item = node.Memory.Slice(index); if (ReferenceEquals(node, _end)) { item = item.Slice(0, _endIndex - index); if (advance) { position = default; } } else { if (advance) { position = Collections.Sequences.Position.Create(node.Next); } } return(true); } throw new NotImplementedException(); }
public static int Copy <TSequence>(TSequence sequence, Collections.Sequences.Position from, Span <byte> buffer) where TSequence : ISequence <ReadOnlyMemory <byte> > { int copied = 0; while (sequence.TryGet(ref from, out ReadOnlyMemory <byte> memory, true)) { var span = memory.Span; var toCopy = Math.Min(span.Length, buffer.Length - copied); span.Slice(0, toCopy).CopyTo(buffer.Slice(copied)); copied += toCopy; if (copied >= buffer.Length) { break; } } return(copied); }
public static string ToString <TSequence>(this TSequence bytes, SymbolTable symbolTable) where TSequence : ISequence <ReadOnlyMemory <byte> > { var sb = new StringBuilder(); if (symbolTable == SymbolTable.InvariantUtf8) { Collections.Sequences.Position position = bytes.First; while (bytes.TryGet(ref position, out ReadOnlyMemory <byte> segment)) { sb.Append(new Utf8Span(segment.Span).ToString()); } } else { throw new NotImplementedException(); } return(sb.ToString()); }
public ReadWriteBytes Slice(Collections.Sequences.Position start, Collections.Sequences.Position end) { var kind = Kind; switch (kind) { case Type.Array: var(array, index) = start.Get <byte[]>(); return(new ReadWriteBytes(array, index, (int)end - index)); case Type.MemoryList: var(startList, startIndex) = start.Get <IMemoryList <byte> >(); var(endList, endIndex) = end.Get <IMemoryList <byte> >(); return(new ReadWriteBytes(startList, startIndex, endList, endIndex)); default: throw new NotImplementedException(); } }
public static long IndexOf <TSequence>(TSequence sequence, byte v1, byte v2) where TSequence : ISequence <ReadOnlyMemory <byte> > { Collections.Sequences.Position position = sequence.First; int totalIndex = 0; while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory)) { var span = memory.Span; var index = span.IndexOf(v1); if (index != -1) { if (span.Length > index + 1) { if (span[index + 1] == v2) { return(index + totalIndex); } else { throw new NotImplementedException(); // need to check farther in the span } } else { if (sequence.TryGet(ref position, out var next, false)) { var nextSpan = next.Span; if (nextSpan.Length > 0) { if (next.Span[0] == v2) { return(totalIndex + index); } } } } } totalIndex += memory.Length; } return(-1); }
public static Collections.Sequences.Position?PositionOf <TSequence>(this TSequence sequence, byte value) where TSequence : ISequence <ReadOnlyMemory <byte> > { if (sequence == null) { return(null); } Collections.Sequences.Position position = sequence.First; Collections.Sequences.Position result = position; while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory)) { var index = MemoryExtensions.IndexOf(memory.Span, value); if (index != -1) { result += index; return(result); } result = position; } return(null); }
public static Collections.Sequences.Position?PositionAt <TSequence>(this TSequence sequence, long index) where TSequence : ISequence <ReadOnlyMemory <byte> > { if (sequence == null) { return(null); } Collections.Sequences.Position position = sequence.First; Collections.Sequences.Position result = position; while (sequence.TryGet(ref position, out ReadOnlyMemory <byte> memory)) { var span = memory.Span; if (span.Length > index) { result += (int)index; return(result); } index -= span.Length; result = position; } return(null); }
public static void Pipe(this IBufferOperation transformation, ReadOnlyBytes source, IOutput destination) { int afterMergeSlice = 0; // Assign 'remainder' to something formally stack-referring. // The default classification is "returnable, not referring to stack", we want the opposite in this case. ReadOnlySpan <byte> remainder = stackalloc byte[0]; Span <byte> stackSpan = stackalloc byte[stackLength]; Collections.Sequences.Position poisition = default; while (source.TryGet(ref poisition, out var sourceBuffer)) { Span <byte> outputSpan = destination.GetSpan(); ReadOnlySpan <byte> sourceSpan = sourceBuffer.Span; if (!remainder.IsEmpty) { int leftOverBytes = remainder.Length; remainder.CopyTo(stackSpan); int amountToCopy = Math.Min(sourceSpan.Length, stackSpan.Length - leftOverBytes); sourceSpan.Slice(0, amountToCopy).CopyTo(stackSpan.Slice(leftOverBytes)); int amountOfData = leftOverBytes + amountToCopy; Span <byte> spanToTransform = stackSpan.Slice(0, amountOfData); TryTransformWithRemainder: OperationStatus status = transformation.Execute(spanToTransform, outputSpan, out int bytesConsumed, out int bytesWritten); if (status != OperationStatus.Done) { destination.Advance(bytesWritten); spanToTransform = spanToTransform.Slice(bytesConsumed); if (status == OperationStatus.DestinationTooSmall) { destination.Enlarge(); // output buffer is too small outputSpan = destination.GetSpan(); if (outputSpan.Length - bytesWritten < 3) { return; // no more output space, user decides what to do. } goto TryTransformWithRemainder; } else { if (status == OperationStatus.InvalidData) { continue; // source buffer contains invalid bytes, user decides what to do for fallback } // at this point, status = TransformationStatus.NeedMoreSourceData // left over bytes in stack span remainder = spanToTransform; } continue; } else // success { afterMergeSlice = bytesConsumed - remainder.Length; remainder = Span <byte> .Empty; destination.Advance(bytesWritten); outputSpan = destination.GetSpan(); } } TryTransform: OperationStatus result = transformation.Execute(sourceSpan.Slice(afterMergeSlice), outputSpan, out int consumed, out int written); afterMergeSlice = 0; destination.Advance(written); sourceSpan = sourceSpan.Slice(consumed); if (result == OperationStatus.Done) { continue; } // Not successful if (result == OperationStatus.DestinationTooSmall) { destination.Enlarge(); // output buffer is too small outputSpan = destination.GetSpan(); if (outputSpan.Length - written < 3) { return; // no more output space, user decides what to do. } goto TryTransform; } else { if (result == OperationStatus.InvalidData) { continue; // source buffer contains invalid bytes, user decides what to do for fallback } // at this point, result = TransformationStatus.NeedMoreSourceData // left over bytes in source span remainder = sourceSpan; } } return; }
public PositionRange(Collections.Sequences.Position start, Collections.Sequences.Position end) { Start = start; End = end; }