예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        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);
        }
예제 #9
0
 public static int Peek <TSequence>(BufferReader <TSequence> reader, Span <byte> destination)
     where TSequence : ISequence <ReadOnlyMemory <byte> >
 => BufferReader <TSequence> .Peek(reader, destination);