public static bool TryReadUntill(ref BufferReader <ReadOnlyBytes> reader, out ReadOnlyBytes bytes, byte delimiter) { var copy = reader; var start = reader.Position; while (!reader.End) { Position end = reader.Position; if (reader.Take() == delimiter) { bytes = new ReadOnlyBytes(start, end); return(true); } } reader = copy; bytes = default; return(false); }
public static bool TryReadUntill <TSequence>(ref BufferReader <TSequence> reader, out ReadOnlyBuffer <byte> bytes, byte delimiter) where TSequence : ISequence <ReadOnlyMemory <byte> >, ISlicable { var copy = reader; var start = reader.Position; while (!reader.End) { SequencePosition end = reader.Position; if (reader.Read() == delimiter) { bytes = reader.Sequence.Slice(start, end); return(true); } } reader = copy; bytes = default; return(false); }
private bool TryReadToAnyInternal(out ReadOnlySequence <T> sequence, ReadOnlySpan <T> delimiters, bool advancePastDelimiter, int skip = 0) { BufferReader <T> copy = this; if (skip > 0) { Advance(skip); } ReadOnlySpan <T> remaining = CurrentSpanIndex == 0 ? CurrentSpan : UnreadSpan; while (!End) { int index = delimiters.Length == 2 ? remaining.IndexOfAny(delimiters[0], delimiters[1]) : remaining.IndexOfAny(delimiters); if (index != -1) { // Found one of the delimiters. Move to it, slice, then move past it. if (index > 0) { Advance(index); } sequence = Sequence.Slice(copy.Position, Position); if (advancePastDelimiter) { Advance(1); } return(true); } Advance(remaining.Length); remaining = CurrentSpan; } // Didn't find anything, reset our original state. this = copy; sequence = default; return(false); }
public static bool TryRead <TSequence>(ref BufferReader <TSequence> reader, out int value, bool littleEndian = false) where TSequence : ISequence <ReadOnlyMemory <byte> > { var unread = reader.UnreadSegment; if (littleEndian) { if (BinaryPrimitives.TryReadInt32LittleEndian(unread, out value)) { reader.Advance(sizeof(int)); return(true); } } else if (BinaryPrimitives.TryReadInt32BigEndian(unread, out value)) { reader.Advance(sizeof(int)); return(true); } Span <byte> tempSpan = stackalloc byte[4]; var copied = BufferReader.Peek(reader, tempSpan); if (copied < 4) { value = default; return(false); } if (littleEndian) { value = BinaryPrimitives.ReadInt32LittleEndian(tempSpan); } else { value = BinaryPrimitives.ReadInt32BigEndian(tempSpan); } reader.Advance(sizeof(int)); return(true); }
public static bool TryParse(ref ByteBufferReader reader, out ulong value) { var unread = reader.UnreadSegment; if (Utf8Parser.TryParse(unread, out value, out int consumed)) { if (unread.Length > consumed) { reader.Advance(consumed); return(true); } } Span <byte> tempSpan = stackalloc byte[30]; var copied = BufferReader.Peek(reader, tempSpan); if (Utf8Parser.TryParse(tempSpan.Slice(0, copied), out value, out consumed)) { reader.Advance(consumed); return(true); } return(false); }
/// <summary> /// Try to read data until the given <paramref name="delimiter"/> sequence. /// </summary> /// <param name="sequence">The read data, if any.</param> /// <param name="delimiter">The multi (T) delimiter.</param> /// <param name="advancePastDelimiter">True to move past the <paramref name="delimiter"/> sequence if found.</param> /// <returns>True if the <paramref name="delimiter"/> was found.</returns> public unsafe bool TryReadTo(out ReadOnlySequence <T> sequence, ReadOnlySpan <T> delimiter, bool advancePastDelimiter = true) { if (delimiter.Length == 0) { sequence = default; return(true); } BufferReader <T> copy = this; Span <T> peekBuffer; if (delimiter.Length * sizeof(T) < 512) { T *t = stackalloc T[delimiter.Length]; peekBuffer = new Span <T>(t, delimiter.Length); } else { peekBuffer = new Span <T>(new T[delimiter.Length]); } bool advanced = false; while (!End) { if (!TryReadTo(out sequence, delimiter[0], advancePastDelimiter: false)) { this = copy; return(false); } if (delimiter.Length == 1) { return(true); } ReadOnlySpan <T> next = Peek(peekBuffer); if (next.SequenceEqual(delimiter)) { //TODO: Figure out a faster way to do this, potentially by avoiding the Advance in the previous TryReadTo call if (advanced) { sequence = copy.Sequence.Slice(copy.Consumed, Consumed - copy.Consumed); } if (advancePastDelimiter) { Advance(delimiter.Length); } return(true); } else { Advance(1); advanced = true; } } this = copy; sequence = default; return(false); }
/// <summary> /// Try to read everything up to the given <paramref name="delimiter"/>, ignoring delimiters that are /// preceeded by <paramref name="delimiterEscape"/>. /// </summary> /// <param name="sequence">The read data, if any.</param> /// <param name="delimiter">The delimiter to look for.</param> /// <param name="delimiterEscape">If found prior to <paramref name="delimiter"/> it will skip that occurence.</param> /// <param name="advancePastDelimiter">True to move past the <paramref name="delimiter"/> if found.</param> /// <returns>True if the <paramref name="delimiter"/> was found.</returns> public bool TryReadTo(out ReadOnlySequence <T> sequence, T delimiter, T delimiterEscape, bool advancePastDelimiter = true) { BufferReader <T> copy = this; ReadOnlySpan <T> remaining = UnreadSpan; bool priorEscape = false; while (!End) { int index = remaining.IndexOf(delimiter); if (index != -1) { if (index == 0 && priorEscape) { // We were in the escaped state, so skip this delimiter priorEscape = false; Advance(index + 1); remaining = UnreadSpan; continue; } else if (index > 0 && remaining[index - 1].Equals(delimiterEscape)) { // This delimiter might be skipped // Count our escapes int escapeCount = 0; for (int i = index; i > 0 && remaining[i - 1].Equals(delimiterEscape); i--, escapeCount++) { ; } if (escapeCount == index && priorEscape) { // Started and ended with escape, increment once more escapeCount++; } priorEscape = false; if (escapeCount % 2 != 0) { // We're in the escaped state, so skip this delimiter Advance(index + 1); remaining = UnreadSpan; continue; } } // Found the delimiter. Move to it, slice, then move past it. if (index > 0) { Advance(index); } sequence = Sequence.Slice(copy.Position, Position); if (advancePastDelimiter) { Advance(1); } return(true); } // No delimiter, need to check the end of the span for odd number of escapes then advance { int escapeCount = 0; for (int i = remaining.Length; i > 0 && remaining[i - 1].Equals(delimiterEscape); i--, escapeCount++) { ; } if (priorEscape && escapeCount == remaining.Length) { escapeCount++; } priorEscape = escapeCount % 2 != 0; } // Nothing in the current span, move to the end, checking for the skip delimiter Advance(remaining.Length); remaining = CurrentSpan; } // Didn't find anything, reset our original state. this = copy; sequence = default; return(false); }
private bool TryReadToSlow(out ReadOnlySequence <T> sequence, T delimiter, T delimiterEscape, int index, bool advancePastDelimiter) { BufferReader <T> copy = this; ReadOnlySpan <T> remaining = UnreadSpan; bool priorEscape = false; do { if (index >= 0) { if (index == 0 && priorEscape) { // We were in the escaped state, so skip this delimiter priorEscape = false; Advance(index + 1); remaining = UnreadSpan; goto Continue; } else if (index > 0 && remaining[index - 1].Equals(delimiterEscape)) { // This delimiter might be skipped // Count our escapes int escapeCount = 1; int i = index - 2; for (; i >= 0; i--) { if (!remaining[i].Equals(delimiterEscape)) { break; } } if (i < 0 && priorEscape) { // Started and ended with escape, increment once more escapeCount++; } escapeCount += index - 2 - i; if ((escapeCount & 1) != 0) { priorEscape = false; // We're in the escaped state, so skip this delimiter Advance(index + 1); remaining = UnreadSpan; goto Continue; } } // Found the delimiter. Move to it, slice, then move past it. Advance(index); sequence = Sequence.Slice(copy.Position, Position); if (advancePastDelimiter) { Advance(1); } return(true); } else { // No delimiter, need to check the end of the span for odd number of escapes then advance if (remaining.Length > 0 && remaining[remaining.Length - 1].Equals(delimiterEscape)) { int escapeCount = 1; int i = remaining.Length - 2; for (; i >= 0; i--) { if (!remaining[i].Equals(delimiterEscape)) { break; } } escapeCount += remaining.Length - 2 - i; if (i < 0 && priorEscape) { priorEscape = (escapeCount & 1) == 0; // equivalent to incrementing escapeCount before setting priorEscape } else { priorEscape = (escapeCount & 1) != 0; } } else { priorEscape = false; } } // Nothing in the current span, move to the end, checking for the skip delimiter Advance(remaining.Length); remaining = CurrentSpan; Continue: index = remaining.IndexOf(delimiter); } while (!End); // Didn't find anything, reset our original state. this = copy; sequence = default; return(false); }
public static int Peek <TSequence>(BufferReader <TSequence> reader, Span <byte> destination) where TSequence : ISequence <ReadOnlyMemory <byte> > => BufferReader <TSequence> .Peek(reader, destination);