/// <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 void Do <T>(this ISpanSequence <T> buffer, ActionOfSpan <T> action) { Span <T> flat; if (buffer.Count < 2) { flat = buffer.Flatten(); } if (buffer.TotalLength < 128) { unsafe { var stackArray = stackalloc byte[128]; flat = new Span <T>(stackArray, 128); if (!buffer.TryCopyTo(ref flat, 0)) { throw new Exception(nameof(buffer) + ".TotalLength returned bad value."); } } } else { flat = buffer.Flatten(); } action(flat); }
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)); } }
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 SpanSequenceEnumerator(ISpanSequence <T> sequence) { _sequence = sequence; _position = Position.BeforeFirst; }
public SequenceFormatter(ISpanSequence <byte> buffers, EncodingData encoding) { _encoding = encoding; _buffers = buffers; _previousWrittenBytes = -1; }
public SequenceFormatter(ISpanSequence<byte> buffers, EncodingData encoding) { _encoding = encoding; _buffers = buffers; _previousWrittenBytes = -1; }