private static void CopyStream(IEnumerator <Step> sourceWalker, IEnumerator <Step> targetWalker, CopyInfo copyInfo) { /* initialize source walker */ var sourceStream = default(Stream); var lastSourceChunk = default(ulong[]); /* initialize target walker */ var targetBuffer = default(Memory <byte>); var lastTargetChunk = default(ulong[]); var currentTarget = default(Memory <byte>); /* walk until end */ while (sourceWalker.MoveNext()) { /* load next source stream */ var sourceStep = sourceWalker.Current; if (sourceStream is null /* if stream not assigned yet */ || !sourceStep.Chunk.SequenceEqual(lastSourceChunk) /* or the chunk has changed */) { sourceStream = copyInfo.GetSourceStream(sourceStep.Chunk); lastSourceChunk = sourceStep.Chunk; } sourceStream?.Seek((int)sourceStep.Offset * copyInfo.TypeSize, SeekOrigin.Begin); // corresponds to var currentLength = (int)sourceStep.Length * copyInfo.TypeSize; // sourceBuffer.Slice() while (currentLength > 0) { /* load next target buffer */ if (currentTarget.Length == 0) { var success = targetWalker.MoveNext(); var targetStep = targetWalker.Current; if (!success || targetStep.Length == 0) { throw new UriFormatException("The target walker stopped early."); } if (targetBuffer.Length == 0 /* if buffer not assigned yet */ || !targetStep.Chunk.SequenceEqual(lastTargetChunk) /* or the chunk has changed */) { targetBuffer = copyInfo.GetTargetBuffer(targetStep.Chunk); lastTargetChunk = targetStep.Chunk; } currentTarget = targetBuffer.Slice( (int)targetStep.Offset * copyInfo.TypeSize, (int)targetStep.Length * copyInfo.TypeSize); } /* copy */ var length = Math.Min(currentLength, currentTarget.Length); sourceStream?.Read(currentTarget.Slice(0, length).Span); // corresponds to span.CopyTo sourceStream?.Seek((int)sourceStep.Offset * copyInfo.TypeSize, SeekOrigin.Begin); // corresponds to currentLength -= (int)sourceStep.Length * copyInfo.TypeSize; // sourceBuffer.Slice() currentTarget = currentTarget.Slice(length); } } }
private static void CopyMemory(IEnumerator <Step> sourceWalker, IEnumerator <Step> targetWalker, CopyInfo copyInfo) { /* initialize source walker */ var sourceBuffer = default(Memory <byte>); var lastSourceChunk = default(ulong[]); /* initialize target walker */ var targetBuffer = default(Memory <byte>); var lastTargetChunk = default(ulong[]); var currentTarget = default(Memory <byte>); /* walk until end */ while (sourceWalker.MoveNext()) { /* load next source buffer */ var sourceStep = sourceWalker.Current; if (sourceBuffer.Length == 0 /* if buffer not assigned yet */ || !sourceStep.Chunk.SequenceEqual(lastSourceChunk) /* or the chunk has changed */) { sourceBuffer = copyInfo.GetSourceBuffer(sourceStep.Chunk); lastSourceChunk = sourceStep.Chunk; } var currentSource = sourceBuffer.Slice( (int)sourceStep.Offset * copyInfo.TypeSize, (int)sourceStep.Length * copyInfo.TypeSize); while (currentSource.Length > 0) { /* load next target buffer */ if (currentTarget.Length == 0) { var success = targetWalker.MoveNext(); var targetStep = targetWalker.Current; if (!success || targetStep.Length == 0) { throw new UriFormatException("The target walker stopped early."); } if (targetBuffer.Length == 0 /* if buffer not assigned yet */ || !targetStep.Chunk.SequenceEqual(lastTargetChunk) /* or the chunk has changed */) { targetBuffer = copyInfo.GetTargetBuffer(targetStep.Chunk); lastTargetChunk = targetStep.Chunk; } currentTarget = targetBuffer.Slice( (int)targetStep.Offset * copyInfo.TypeSize, (int)targetStep.Length * copyInfo.TypeSize); } /* copy */ var length = Math.Min(currentSource.Length, currentTarget.Length); currentSource .Slice(0, length) .CopyTo(currentTarget); currentSource = currentSource.Slice(length); currentTarget = currentTarget.Slice(length); } } }