예제 #1
0
        public int CopyTo(Span <byte> buffer)
        {
            var first       = First;
            var firstLength = first.Length;

            if (firstLength > buffer.Length)
            {
                first.Slice(0, buffer.Length).CopyTo(buffer);
                return(buffer.Length);
            }
            first.CopyTo(buffer);
            if (buffer.Length == firstLength || _rest == null)
            {
                return(firstLength);
            }
            return(firstLength + _rest.CopyTo(buffer.Slice(firstLength)));
        }
예제 #2
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 int IndexOfStraddling(this ReadOnlySpan <byte> first, IReadOnlyBufferList <byte> 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;
            }

            int 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);
        }