Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
Removed PositionOf from reader
Browse files Browse the repository at this point in the history
  • Loading branch information
KrzysztofCwalina committed Jan 5, 2018
1 parent 10d32ad commit c0fe750
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 98 deletions.
68 changes: 68 additions & 0 deletions src/System.Buffers.Experimental/System/Buffers/BufferReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Sequences;

namespace System.Buffers
{
public static partial class BufferReaderExtensions
{
//public Position? PositionOf(byte value)
//{
// var unread = UnreadSegment;
// var index = unread.IndexOf(value);
// if (index != -1) return _currentPosition + (_index + index);

// var nextSegmentPosition = _nextPosition;
// var currentSegmentPosition = _nextPosition;
// while (_sequence.TryGet(ref nextSegmentPosition, out var memory, true))
// {
// var segment = memory.Span;
// index = segment.IndexOf(value);
// if (index != -1) return currentSegmentPosition + index;
// currentSegmentPosition = nextSegmentPosition;
// }
// return default;
//}

//public Position? PositionOf(ReadOnlySpan<byte> value)
//{
// var unread = UnreadSegment;
// var index = unread.IndexOf(value);
// if (index != -1) return _currentPosition + (_index + index);
// if (value.Length == 0) return default;

// Span<byte> temp = stackalloc byte[(value.Length - 1) * 2];
// var currentSegmentPosition = _currentPosition;
// var nextSegmentPosition = _nextPosition;
// var currentSegmentConsumedBytes = _index;

// while (true)
// {
// // Try Stitched Match
// int tempStartIndex = unread.Length - Math.Min(unread.Length, value.Length - 1);
// var candidatePosition = currentSegmentPosition + (currentSegmentConsumedBytes + tempStartIndex);
// int copied = CopyFromPosition(_sequence, candidatePosition, temp);
// if (copied < value.Length) return null;

// index = temp.Slice(0, copied).IndexOf(value);
// if (index < value.Length)
// {
// if (index != -1) return candidatePosition + index;
// }

// currentSegmentPosition = nextSegmentPosition;
// // Try Next Segment
// if (!_sequence.TryGet(ref nextSegmentPosition, out var memory, true))
// {
// return default;
// }
// currentSegmentConsumedBytes = 0;
// unread = memory.Span;

// index = unread.IndexOf(value);
// if (index != -1) return currentSegmentPosition + index;
// }
//}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,59 @@

namespace System.Buffers
{
// TODO: the TryReadUntill methods are very inneficient. We need to fix that.
public static partial class BufferReaderExtensions
{
public static bool TryReadUntill<TSequence>(ref this BufferReader<TSequence> reader, out ReadOnlyBuffer bytes, byte delimiter)
where TSequence : ISequence<ReadOnlyMemory<byte>>
{
var position = reader.PositionOf(delimiter);
if (position == null)
{
bytes = default;
return false;
var copy = reader;
var start = reader.Position;
while (!reader.End) {
Position end = reader.Position;
if(reader.Take() == delimiter)
{
bytes = new ReadOnlyBuffer(start, end);
return true;
}
}
bytes = new ReadOnlyBuffer(reader.Position, position.Value);
reader.SkipTo(position.Value);
reader.Skip(1);
return true;
reader = copy;
bytes = default;
return false;
}

public static bool TryReadUntill<TSequence>(ref this BufferReader<TSequence> reader, out ReadOnlyBuffer bytes, ReadOnlySpan<byte> delimiter)
where TSequence : ISequence<ReadOnlyMemory<byte>>
{
var position = reader.PositionOf(delimiter);
if(position == null)
if (delimiter.Length == 0)
{
bytes = ReadOnlyBuffer.Empty;
return true;
}

int matched = 0;
var copy = reader;
var start = reader.Position;
var end = reader.Position;
while (!reader.End)
{
bytes = default;
return false;
if (reader.Take() == delimiter[matched]) {
matched++;
}
else
{
end = reader.Position;
matched = 0;
}
if(matched >= delimiter.Length)
{
bytes = new ReadOnlyBuffer(start, end);
return true;
}
}
bytes = new ReadOnlyBuffer(reader.Position, position.Value);
reader.SkipTo(position.Value);
reader.Skip(delimiter.Length);
return true;
reader = copy;
bytes = default;
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace System.Buffers
internal readonly Position BufferStart;
internal readonly Position BufferEnd;

public static readonly ReadOnlyBuffer Empty = new ReadOnlyBuffer(new byte[0]);

/// <summary>
/// Length of the <see cref="ReadOnlyBuffer"/> in bytes.
/// </summary>
Expand Down
100 changes: 19 additions & 81 deletions src/System.Buffers.Primitives/System/Buffers/ReadOnlyBufferReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,97 +144,35 @@ public void SkipTo(Position position)
}
_index = 0;
}

public Position? PositionOf(byte value)
{
var unread = UnreadSegment;
var index = unread.IndexOf(value);
if (index != -1) return _currentPosition + (_index + index);

var nextSegmentPosition = _nextPosition;
var currentSegmentPosition = _nextPosition;
while (_sequence.TryGet(ref nextSegmentPosition, out var memory, true))
{
var segment = memory.Span;
index = segment.IndexOf(value);
if (index != -1) return currentSegmentPosition + index;
currentSegmentPosition = nextSegmentPosition;
}
return default;
}

public Position? PositionOf(ReadOnlySpan<byte> value)
{
var unread = UnreadSegment;
var index = unread.IndexOf(value);
if (index != -1) return _currentPosition + (_index + index);
if (value.Length == 0) return default;

Span<byte> temp = stackalloc byte[(value.Length - 1) * 2];
var currentSegmentPosition = _currentPosition;
var nextSegmentPosition = _nextPosition;
var currentSegmentConsumedBytes = _index;

while (true)
{
// Try Stitched Match
int tempStartIndex = unread.Length - Math.Min(unread.Length, value.Length - 1);
var candidatePosition = currentSegmentPosition + (currentSegmentConsumedBytes + tempStartIndex);
int copied = CopyFromPosition(_sequence, candidatePosition, temp);
if (copied < value.Length) return null;

index = temp.Slice(0, copied).IndexOf(value);
if (index < value.Length)
{
if (index != -1) return candidatePosition + index;
}

currentSegmentPosition = nextSegmentPosition;
// Try Next Segment
if (!_sequence.TryGet(ref nextSegmentPosition, out var memory, true))
{
return default;
}
currentSegmentConsumedBytes = 0;
unread = memory.Span;

index = unread.IndexOf(value);
if (index != -1) return currentSegmentPosition + index;
}
}

public static int CopyTo(BufferReader<TSequence> bytes, Span<byte> buffer)
public static int CopyTo(BufferReader<TSequence> bytes, Span<byte> destination)
{
var first = bytes.UnreadSegment;
if (first.Length > buffer.Length)
if (first.Length > destination.Length)
{
first.Slice(0, buffer.Length).CopyTo(buffer);
return buffer.Length;
first.Slice(0, destination.Length).CopyTo(destination);
return destination.Length;
}
else if (first.Length == buffer.Length)
else if (first.Length == destination.Length)
{
first.CopyTo(buffer);
return buffer.Length;
first.CopyTo(destination);
return destination.Length;
}
else
{
first.CopyTo(buffer);
return first.Length + CopyFromPosition(bytes._sequence, bytes._nextPosition, buffer.Slice(first.Length));
}
}

private static int CopyFromPosition(TSequence sequence, Position from, Span<byte> buffer)
{
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;
first.CopyTo(destination);
var next = bytes._nextPosition;
int copied = first.Length;
while (bytes._sequence.TryGet(ref next, out ReadOnlyMemory<byte> nextSegment, true))
{
var nextSpan = nextSegment.Span;
var toCopy = Math.Min(nextSpan.Length, destination.Length - copied);
nextSpan.Slice(0, toCopy).CopyTo(destination.Slice(copied));
copied += toCopy;
if (copied >= destination.Length) break;
}
return copied;
}
return copied;
}
}
}

0 comments on commit c0fe750

Please sign in to comment.