mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
ref https://github.com/nim-lang/Nim/issues/24764 To keep destructors injected consistently, we need to transform `mAsgn` properly into `nkSinkAsgn` and `nkAsgn`. This PR is the first step towards overhauling hook injections. In this PR, hooks (except mAsgn) are treated consistently whether it is resolved in matching or instantiated by sempass2. It also fixes a spelling `=wasMoved` to its normalized version, which caused no replacing generic hook calls with lifted hook calls.
123 lines
3.5 KiB
Nim
123 lines
3.5 KiB
Nim
#
|
|
#
|
|
# 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 std/[deques, streams]
|
|
|
|
when defined(nimPreviewSlimSystem):
|
|
import std/assertions
|
|
|
|
|
|
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..<n:
|
|
var c = s.buffer.popFirst
|
|
if c == '\c':
|
|
c = readChar(s)
|
|
return true
|
|
elif c == '\L': return true
|
|
elif c == '\0':
|
|
return line.len > 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:
|
|
dest[i] = s.buffer.popFirst
|
|
if bufLen > 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:
|
|
dest[i] = s.buffer[i]
|
|
|
|
if bufLen > n:
|
|
let
|
|
newDataNeeded = bufLen - n
|
|
numRead = s.baseReadDataImpl(s, addr dest[n], newDataNeeded)
|
|
result += numRead
|
|
for i in 0..<numRead:
|
|
s.buffer.addLast dest[n + i]
|
|
|
|
proc newPipeOutStream*[T](s: sink (ref T)): owned PipeOutStream[T] =
|
|
## Wrap pipe for reading with PipeOutStream so that you can use peek* procs and generate runtime error
|
|
## when setPosition/getPosition is called or write operation is performed.
|
|
##
|
|
## Example:
|
|
## ```Nim
|
|
## import std/[osproc, streamwrapper]
|
|
## var
|
|
## p = startProcess(exePath)
|
|
## outStream = p.outputStream().newPipeOutStream()
|
|
## echo outStream.peekChar
|
|
## p.close()
|
|
## ```
|
|
|
|
assert s.readDataImpl != nil
|
|
|
|
new(result)
|
|
for dest, src in fields((ref T)(result)[], s[]):
|
|
dest = src
|
|
{.cast(raises: []), cast(tags: []).}:
|
|
wasMoved(s[])
|
|
if result.readLineImpl != nil:
|
|
result.baseReadLineImpl = result.readLineImpl
|
|
result.readLineImpl = posReadLine[T]
|
|
result.baseReadDataImpl = result.readDataImpl
|
|
result.readDataImpl = posReadData[T]
|
|
result.readDataStrImpl = posReadDataStr[T]
|
|
result.peekDataImpl = posPeekData[T]
|
|
|
|
# Set nil to anything you may not call.
|
|
result.setPositionImpl = nil
|
|
result.getPositionImpl = nil
|
|
result.writeDataImpl = nil
|
|
result.flushImpl = nil
|