# # # Nim's Runtime Library # (c) Copyright 2020 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## This module implements stream wrapper. ## ## **Since** version 1.2. import deques, streams type PipeOutStream*[T] = ref object of T # When stream peek operation is called, it reads from base stream # type using `baseReadDataImpl` and stores the content to this buffer. # Next stream read operation returns data in the buffer so that previus peek # operation looks like didn't changed read positon. # When stream read operation that returns N byte data is called and the size is smaller than buffer size, # first N elements are removed from buffer. # Deque type can do such operation more efficiently than seq type. buffer: Deque[char] baseReadLineImpl: typeof(StreamObj.readLineImpl) baseReadDataImpl: typeof(StreamObj.readDataImpl) proc posReadLine[T](s: Stream, line: var string): bool = var s = PipeOutStream[T](s) assert s.baseReadLineImpl != nil let n = s.buffer.len line.setLen(0) for i in 0.. 0 line.add(c) var line2: string result = s.baseReadLineImpl(s, line2) line.add line2 proc posReadData[T](s: Stream, buffer: pointer, bufLen: int): int = var s = PipeOutStream[T](s) assert s.baseReadDataImpl != nil let dest = cast[ptr UncheckedArray[char]](buffer) n = min(s.buffer.len, bufLen) result = n for i in 0.. n: result += s.baseReadDataImpl(s, addr dest[n], bufLen - n) proc posReadDataStr[T](s: Stream, buffer: var string, slice: Slice[int]): int = posReadData[T](s, addr buffer[slice.a], slice.len) proc posPeekData[T](s: Stream, buffer: pointer, bufLen: int): int = var s = PipeOutStream[T](s) assert s.baseReadDataImpl != nil let dest = cast[ptr UncheckedArray[char]](buffer) n = min(s.buffer.len, bufLen) result = n for i in 0.. n: let newDataNeeded = bufLen - n numRead = s.baseReadDataImpl(s, addr dest[n], newDataNeeded) result += numRead for i in 0..