public static Span <T> Flatten <T>(this ISpanSequence <T> sequence)
        {
            var      position = Position.First;
            Span <T> firstSpan;

            // if sequence length == 0
            if (!sequence.TryGet(ref position, out firstSpan, advance: true))
            {
                return(Span <T> .Empty);
            }
            Span <T> secondSpan;

            // if sequence length == 1
            if (!sequence.TryGet(ref position, out secondSpan, advance: true))
            {
                return(firstSpan);
            }

            // allocate and copy
            Span <T> result;

            // if we know the total size of the sequence
            if (sequence.TotalLength != null)
            {
                result = new T[sequence.TotalLength.Value];
                result.Set(firstSpan);
                result.Slice(firstSpan.Length).Set(secondSpan);
                int      copied = firstSpan.Length + secondSpan.Length;
                Span <T> nextSpan;
                while (sequence.TryGet(ref position, out nextSpan, advance: true))
                {
                    nextSpan.CopyTo(result.Slice(copied));
                    copied += nextSpan.Length;
                }
                return(result);
            }
            else
            {
                var capacity       = (firstSpan.Length + secondSpan.Length) * 2;
                var resizableArray = new ResizableArray <T>(capacity);
                firstSpan.CopyTo(ref resizableArray);
                secondSpan.CopyTo(ref resizableArray);
                Span <T> nextSpan;
                int      copied = firstSpan.Length + secondSpan.Length;
                while (sequence.TryGet(ref position, out nextSpan, advance: true))
                {
                    while (copied + nextSpan.Length > resizableArray.Capacity)
                    {
                        var newLength = resizableArray.Capacity * 2;
                        resizableArray.Resize(newLength);
                    }
                    nextSpan.CopyTo(ref resizableArray);
                    copied += nextSpan.Length;
                }
                return(resizableArray._array.Slice(0, copied));
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sequence"></param>
        /// <param name="destination">The parameter is updated if it's longer than the items in the sequence</param>
        /// <param name="skip">number of items from the begining of sequence to skip, i.e. not copy.</param>
        /// <returns>True if all items did fit in the destination, false otherwise.</returns>
        /// <remarks>If the destination is too short, up to destination.Length items are copied in, even if the function returns false.</remarks>
        public static bool TryCopyTo <T>(this ISpanSequence <T> sequence, ref Span <T> destination, int skip = 0)
        {
            var      position = Position.First;
            Span <T> next;
            int      copied = 0;

            while (sequence.TryGet(ref position, out next, advance: true))
            {
                var free = destination.Slice(copied);

                if (skip > next.Length)
                {
                    skip -= next.Length;
                    continue;
                }
                if (skip > 0)
                {
                    next = next.Slice(skip);
                }

                if (free.Length > next.Length)
                {
                    free.Set(next);
                    copied += next.Length;
                }
                else
                {
                    free.Set(next.Slice(0, free.Length));
                    return(false);
                }
            }

            destination = destination.Slice(0, copied);
            return(true);
        }
        public static Span <T> First <T>(this ISpanSequence <T> sequence)
        {
            Span <T> result;
            var      first = Position.First;

            if (!sequence.TryGet(ref first, out result))
            {
                ThrowHelper.ThrowInvalidOperationException();
            }

            return(result);
        }
        public bool MoveNext()
        {
            Span <T> span;
            var      result = _sequence.TryGet(ref _position, out span, advance: true);

            if (_position == Position.First)
            {
                return(true);
            }
            if (_position == Position.AfterLast)
            {
                return(false);
            }
            return(result);
        }
Exemple #5
0
        void IOutput.Enlarge(int desiredBufferLength)
        {
            if (NeedShift)
            {
                throw new NotImplementedException("need to allocate temp array");
            }

            _previousPosition     = _currentPosition;
            _previousWrittenBytes = _currentWrittenBytes;

            Span <byte> span;

            if (!_buffers.TryGet(ref _currentPosition, out span, advance: true))
            {
                throw new InvalidOperationException();
            }
            _currentWrittenBytes = 0;
        }