示例#1
0
        // TODO: Hide this ctor and force users to pass Positions. This will let us hide Position.Object
        public ReadOnlyBytes(IBufferList first, IBufferList last)
        {
            _start      = first;
            _startIndex = 0;
            _end        = last;
            _endIndex   = last.Memory.Length;

            Validate();
        }
示例#2
0
        public ReadWriteBytes(IBufferList <byte> first, IBufferList <byte> last)
        {
            _start      = first;
            _startIndex = 0;
            _end        = last;
            _endIndex   = last.Memory.Length;

            Validate();
        }
示例#3
0
        public ReadOnlyBuffer(IBufferList startSegment, int offset, IBufferList endSegment, int endIndex)
        {
            Debug.Assert(startSegment != null);
            Debug.Assert(endSegment != null);
            Debug.Assert(startSegment.Memory.Length >= offset);
            Debug.Assert(endSegment.Memory.Length >= endIndex);

            BufferStart = new Position(startSegment, offset);
            BufferEnd   = new Position(endSegment, endIndex);
        }
示例#4
0
 public static Position?PositionOf(this IBufferList list, byte value)
 {
     while (list != null)
     {
         var current = list.Memory.Span;
         var index   = current.IndexOf(value);
         if (index != -1)
         {
             return(new Position(list, index));
         }
         list = list.Next;
     }
     return(null);
 }
示例#5
0
        public static long IndexOf(this IBufferList list, ReadOnlySpan <byte> value)
        {
            var first = list.Memory.Span;
            var index = first.IndexOf(value);

            if (index != -1)
            {
                return(index);
            }

            var rest = list.Next;

            if (rest == null)
            {
                return(-1);
            }

            return(IndexOfStraddling(first, list.Next, value));
        }
示例#6
0
        public static int CopyTo(this IBufferList list, Span <byte> destination)
        {
            var current = list.Memory.Span;
            int copied  = 0;

            while (destination.Length > 0)
            {
                if (current.Length >= destination.Length)
                {
                    current.Slice(0, destination.Length).CopyTo(destination);
                    copied += destination.Length;
                    return(copied);
                }
                else
                {
                    current.CopyTo(destination);
                    copied     += current.Length;
                    destination = destination.Slice(current.Length);
                }
            }
            return(copied);
        }
示例#7
0
 public ReadWriteBytes(IBufferList <byte> segments) :
     this(segments.First, segments.Rest, Unspecified)
 {
 }
示例#8
0
 public ReadWriteBytes(IBufferList <byte> segments, int length) :
     this(segments.First, segments.Rest, length)
 {
 }
示例#9
0
 public ReadWriteBytes(Buffer <byte> first, IBufferList <byte> rest) :
     this(first, rest, Unspecified)
 {
 }
示例#10
0
 public ReadWriteBytes(Buffer <byte> first, IBufferList <byte> rest, int length)
 {
     _rest   = rest;
     _first  = first;
     _length = length;
 }
示例#11
0
        // TODO (pri 3): I am pretty sure this whole routine can be written much better

        // searches values that potentially straddle between first and rest
        internal static long IndexOfStraddling(this ReadOnlySpan <byte> first, IBufferList rest, ReadOnlySpan <byte> value)
        {
            Debug.Assert(first.IndexOf(value) == -1);
            if (rest == null)
            {
                return(-1);
            }

            // we only need to search the end of the first buffer. More precisely, only up to value.Length - 1 bytes in the first buffer
            // The other bytes in first, were already search and presumably did not match
            int bytesToSkipFromFirst = 0;

            if (first.Length > value.Length - 1)
            {
                bytesToSkipFromFirst = first.Length - value.Length - 1;
            }

            // now that we know how many bytes we need to skip, create slice of first buffer with bytes that need to be searched.
            ReadOnlySpan <byte> bytesToSearchAgain;

            if (bytesToSkipFromFirst > 0)
            {
                bytesToSearchAgain = first.Slice(bytesToSkipFromFirst);
            }
            else
            {
                bytesToSearchAgain = first;
            }

            long index;

            // now combine the bytes from the end of the first buffer with bytes in the rest, and serarch the combined buffer
            // this check is a small optimization: if the first byte from the value does not exist in the bytesToSearchAgain, there is no reason to combine
            if (bytesToSearchAgain.IndexOf(value[0]) != -1)
            {
                var combinedBufferLength = value.Length << 1;
                var combined             = combinedBufferLength < 128 ?
                                           stackalloc byte[combinedBufferLength] :
                                           // TODO (pri 3): I think this could be eliminated by chunking values
                                           new byte[combinedBufferLength];

                bytesToSearchAgain.CopyTo(combined);
                int combinedLength = bytesToSearchAgain.Length + rest.CopyTo(combined.Slice(bytesToSearchAgain.Length));
                combined = combined.Slice(0, combinedLength);

                if (combined.Length < value.Length)
                {
                    return(-1);
                }

                index = combined.IndexOf(value);
                if (index != -1)
                {
                    return(index + bytesToSkipFromFirst);
                }
            }

            // try to find the bytes in _rest
            index = rest.IndexOf(value);
            if (index != -1)
            {
                return(first.Length + index);
            }

            return(-1);
        }