public static async Task CopyToAsync(this MemoryPoolIterator start, Stream stream, MemoryPoolBlock end) { if (start.IsDefault) { return; } var block = start.Block; var index = start.Index; while (true) { // Determine if we might attempt to copy data from block.Next before // calculating "following" so we don't risk skipping data that could // be added after block.End when we decide to copy from block.Next. // block.End will always be advanced before block.Next is set. var wasLastBlock = block.Next == null || block == end; var following = block.End - index; if (wasLastBlock) { await stream.WriteAsync(block.Array, index, following); break; } else { await stream.WriteAsync(block.Array, index, following); block = block.Next; index = block.Start; } } }
public int GetLength(MemoryPoolIterator end) { if (IsDefault || end.IsDefault) { return(-1); } var block = _block; var index = _index; var length = 0; checked { while (true) { if (block == end._block) { return(length + end._index - index); } else if (block.Next == null) { throw new InvalidOperationException("end did not follow iterator"); } else { length += block.End - index; block = block.Next; index = block.Start; } } } }
public MemoryPoolSpan BeginRead() { if (Interlocked.CompareExchange(ref _consumingState, 1, 0) != 0) { throw new InvalidOperationException("Already consuming input."); } var start = new MemoryPoolIterator(_head); var end = new MemoryPoolIterator(_tail, _tail?.End ?? 0); return(new MemoryPoolSpan(start, end)); }
public Task EndWriteAsync(MemoryPoolIterator end) { lock (_sync) { if (!end.IsDefault) { _tail = end.Block; _tail.End = end.Index; } Complete(); return(Task.FromResult(0)); } }
public static ArraySegment <byte> GetArraySegment(this MemoryPoolIterator start, MemoryPoolIterator end) { if (start.IsDefault || end.IsDefault) { return(default(ArraySegment <byte>)); } if (end.Block == start.Block) { return(new ArraySegment <byte>(start.Block.Array, start.Index, end.Index - start.Index)); } var length = start.GetLength(end); var array = new byte[length]; start.CopyTo(array, 0, length, out length); return(new ArraySegment <byte>(array, 0, length)); }
public void EndRead( MemoryPoolIterator consumed, MemoryPoolIterator examined) { MemoryPoolBlock returnStart = null; MemoryPoolBlock returnEnd = null; lock (_sync) { if (!consumed.IsDefault) { returnStart = _head; returnEnd = consumed.Block; _head = consumed.Block; _head.Start = consumed.Index; } if (!examined.IsDefault && examined.IsEnd && Completion.Status == TaskStatus.WaitingForActivation) { _manualResetEvent.Reset(); Interlocked.CompareExchange( ref _awaitableState, _awaitableIsNotCompleted, _awaitableIsCompleted); } } while (returnStart != returnEnd) { var returnBlock = returnStart; returnStart = returnStart.Next; returnBlock.Pool.Return(returnBlock); } if (Interlocked.CompareExchange(ref _consumingState, 0, 1) != 1) { throw new InvalidOperationException("No ongoing consuming operation to complete."); } }
public static void EndRead(this IReadableChannel input, MemoryPoolIterator consumed) { input.EndRead(consumed, consumed); }
public void EndRead(MemoryPoolIterator end) { EndRead(end, end); }
public MemoryPoolSpan(MemoryPoolIterator begin, MemoryPoolIterator end) { Begin = begin; End = end; }
public void EndRead(MemoryPoolIterator consumed, MemoryPoolIterator examined) => _channel.EndRead(consumed, examined);
public unsafe static string GetAsciiString(this MemoryPoolIterator start, MemoryPoolIterator end) { if (start.IsDefault || end.IsDefault) { return(null); } var length = start.GetLength(end); if (length == 0) { return(null); } // Bytes out of the range of ascii are treated as "opaque data" // and kept in string as a char value that casts to same input byte value // https://tools.ietf.org/html/rfc7230#section-3.2.4 var inputOffset = start.Index; var block = start.Block; var asciiString = new string('\0', length); fixed(char *outputStart = asciiString) { var output = outputStart; var remaining = length; var endBlock = end.Block; var endIndex = end.Index; while (true) { int following = (block != endBlock ? block.End : endIndex) - inputOffset; if (following > 0) { var input = block.DataFixedPtr + inputOffset; var i = 0; while (i < following - 11) { i += 12; *(output) = (char)*(input); *(output + 1) = (char)*(input + 1); *(output + 2) = (char)*(input + 2); *(output + 3) = (char)*(input + 3); *(output + 4) = (char)*(input + 4); *(output + 5) = (char)*(input + 5); *(output + 6) = (char)*(input + 6); *(output + 7) = (char)*(input + 7); *(output + 8) = (char)*(input + 8); *(output + 9) = (char)*(input + 9); *(output + 10) = (char)*(input + 10); *(output + 11) = (char)*(input + 11); output += 12; input += 12; } if (i < following - 5) { i += 6; *(output) = (char)*(input); *(output + 1) = (char)*(input + 1); *(output + 2) = (char)*(input + 2); *(output + 3) = (char)*(input + 3); *(output + 4) = (char)*(input + 4); *(output + 5) = (char)*(input + 5); output += 6; input += 6; } if (i < following - 3) { i += 4; *(output) = (char)*(input); *(output + 1) = (char)*(input + 1); *(output + 2) = (char)*(input + 2); *(output + 3) = (char)*(input + 3); output += 4; input += 4; } while (i < following) { i++; *output = (char)*input; output++; input++; } remaining -= following; } if (remaining == 0) { break; } block = block.Next; inputOffset = block.Start; } } return(asciiString); }
public static string GetUtf8String(this MemoryPoolIterator start, MemoryPoolIterator end) { if (start.IsDefault || end.IsDefault) { return(default(string)); } if (end.Block == start.Block) { return(_utf8.GetString(start.Block.Array, start.Index, end.Index - start.Index)); } var decoder = _utf8.GetDecoder(); var length = start.GetLength(end); var charLength = length * 2; var chars = new char[charLength]; var charIndex = 0; var block = start.Block; var index = start.Index; var remaining = length; while (true) { int bytesUsed; int charsUsed; bool completed; var following = block.End - index; if (remaining <= following) { decoder.Convert( block.Array, index, remaining, chars, charIndex, charLength - charIndex, true, out bytesUsed, out charsUsed, out completed); return(new string(chars, 0, charIndex + charsUsed)); } else if (block.Next == null) { decoder.Convert( block.Array, index, following, chars, charIndex, charLength - charIndex, true, out bytesUsed, out charsUsed, out completed); return(new string(chars, 0, charIndex + charsUsed)); } else { decoder.Convert( block.Array, index, following, chars, charIndex, charLength - charIndex, false, out bytesUsed, out charsUsed, out completed); charIndex += charsUsed; remaining -= following; block = block.Next; index = block.Start; } } }