Turn the consumeOutputs templates into procs to reduce code bloat
This commit is contained in:
parent
87309f3120
commit
65f82f2f2d
1 changed files with 46 additions and 29 deletions
|
|
@ -249,17 +249,20 @@ template vtableAddr*(vtable: OutputStreamVTable): ptr OutputStreamVTable =
|
||||||
{.noSideEffect.}:
|
{.noSideEffect.}:
|
||||||
unsafeAddr vtable
|
unsafeAddr vtable
|
||||||
|
|
||||||
proc fileOutput*(filename: string,
|
proc fileOutput*(f: File,
|
||||||
fileMode: FileMode = fmWrite,
|
|
||||||
pageSize = defaultPageSize): OutputStreamHandle
|
pageSize = defaultPageSize): OutputStreamHandle
|
||||||
{.raises: [IOError, Defect].} =
|
{.raises: [IOError, Defect].} =
|
||||||
let f = open(filename, fileMode)
|
|
||||||
|
|
||||||
makeHandle FileOutputStream(
|
makeHandle FileOutputStream(
|
||||||
vtable: vtableAddr fileOutputVTable,
|
vtable: vtableAddr fileOutputVTable,
|
||||||
buffers: initPageBuffers(pageSize),
|
buffers: initPageBuffers(pageSize),
|
||||||
file: f)
|
file: f)
|
||||||
|
|
||||||
|
proc fileOutput*(filename: string,
|
||||||
|
fileMode: FileMode = fmWrite,
|
||||||
|
pageSize = defaultPageSize): OutputStreamHandle
|
||||||
|
{.raises: [IOError, Defect].} =
|
||||||
|
fileOutput(open(filename, fileMode), pageSize)
|
||||||
|
|
||||||
proc pos*(s: OutputStream): int =
|
proc pos*(s: OutputStream): int =
|
||||||
s.spanEndPos - s.span.len
|
s.spanEndPos - s.span.len
|
||||||
|
|
||||||
|
|
@ -690,35 +693,36 @@ proc writeMemCopy*[T](c: var WriteCursor, value: T) =
|
||||||
proc write*(c: var WriteCursor, str: string) =
|
proc write*(c: var WriteCursor, str: string) =
|
||||||
writeBytesToCursor(c, str.toOpenArrayByte(0, str.len - 1))
|
writeBytesToCursor(c, str.toOpenArrayByte(0, str.len - 1))
|
||||||
|
|
||||||
template consumeOutputs*(sp: OutputStream, bytesVar, body: untyped) =
|
type
|
||||||
|
OutputConsumingProc = proc (data: openArray[byte])
|
||||||
|
{.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
|
proc consumeOutputsImpl(s: OutputStream, consumer: OutputConsumingProc) =
|
||||||
|
let runway = s.span.len
|
||||||
|
|
||||||
|
fsAssert s.extCursorsCount == 0 and s.buffers != nil
|
||||||
|
trackWrittenTo(s.buffers, s.span.startAddr)
|
||||||
|
|
||||||
|
for pageReadableStart, pageLen in consumePageBuffers(s.buffers):
|
||||||
|
consumer(makeOpenArray(pageReadableStart, pageLen))
|
||||||
|
|
||||||
|
s.span = getWritableSpan(s.buffers)
|
||||||
|
s.spanEndPos += s.span.len - runway
|
||||||
|
|
||||||
|
template consumeOutputs*(s: OutputStream, bytesVar, body: untyped) =
|
||||||
## Please note that calling `consumeOutputs` on an unbuffered stream
|
## Please note that calling `consumeOutputs` on an unbuffered stream
|
||||||
## or an unsafe memory stream is considered a Defect.
|
## or an unsafe memory stream is considered a Defect.
|
||||||
##
|
##
|
||||||
## Before consuming the outputs, all outstanding delayed writes must
|
## Before consuming the outputs, all outstanding delayed writes must
|
||||||
## be finalized.
|
## be finalized.
|
||||||
let s = sp
|
proc consumer(bytesVar: openarray[byte]) {.gcsafe, raises: [Defect].} =
|
||||||
fsAssert s.extCursorsCount == 0 and s.buffers != nil
|
|
||||||
|
|
||||||
for pageReadableStart, pageLen in consumePageBuffers(s.buffers):
|
|
||||||
template bytesVar: untyped =
|
|
||||||
makeOpenArray(pageReadableStart, pageLen)
|
|
||||||
|
|
||||||
body
|
body
|
||||||
|
|
||||||
template consumeContiguousOutput*(sp: OutputStream, bytesVar, body: untyped) =
|
consumeOutputsImpl(s, consumer)
|
||||||
## Please note that calling `consumeContiguousOutput` on an unbuffered stream
|
|
||||||
## or an unsafe memory stream is considered a Defect.
|
|
||||||
##
|
|
||||||
## Before consuming the output, all outstanding delayed writes must
|
|
||||||
## be finalized.
|
|
||||||
##
|
|
||||||
|
|
||||||
# TODO: This code is a bit too much to be inlined. Maybe this should be
|
proc consumeContiguousOutputImpl(s: OutputStream, consumer: OutputConsumingProc) =
|
||||||
# a proc with a callback, but this will restrict the types of variables
|
|
||||||
# it can write to. OTOH, perhaps only `consumePageBuffers` is the offending
|
|
||||||
# part.
|
|
||||||
var
|
var
|
||||||
s = sp
|
runway = s.span.len
|
||||||
contigiousBytes: string
|
contigiousBytes: string
|
||||||
# this may remain null
|
# this may remain null
|
||||||
# We are using a string, because `newStringOfCap` doesn't zero out
|
# We are using a string, because `newStringOfCap` doesn't zero out
|
||||||
|
|
@ -727,6 +731,7 @@ template consumeContiguousOutput*(sp: OutputStream, bytesVar, body: untyped) =
|
||||||
bytesLen: int
|
bytesLen: int
|
||||||
|
|
||||||
fsAssert s.extCursorsCount == 0 and s.buffers != nil
|
fsAssert s.extCursorsCount == 0 and s.buffers != nil
|
||||||
|
s.buffers.trackWrittenTo s.span.startAddr
|
||||||
|
|
||||||
if s.buffers.queue.len == 1:
|
if s.buffers.queue.len == 1:
|
||||||
let page = s.buffers.queue[0]
|
let page = s.buffers.queue[0]
|
||||||
|
|
@ -736,18 +741,30 @@ template consumeContiguousOutput*(sp: OutputStream, bytesVar, body: untyped) =
|
||||||
page.consumedTo = 0
|
page.consumedTo = 0
|
||||||
page.writtenTo = 0
|
page.writtenTo = 0
|
||||||
else:
|
else:
|
||||||
contigiousBytes = newStringOfCap(s.pos)
|
contigiousBytes = newStringOfCap(s.buffers.totalBufferedBytes)
|
||||||
|
|
||||||
for pageReadableStart, pageLen in consumePageBuffers(s.buffers):
|
for pageReadableStart, pageLen in consumePageBuffers(s.buffers):
|
||||||
contigiousBytes.add makeOpenArray(cast[ptr char](pageReadableStart), pageLen)
|
contigiousBytes.add makeOpenArray(cast[ptr char](pageReadableStart), pageLen)
|
||||||
|
|
||||||
bytesPtr = addr contigiousBytes[0]
|
bytesPtr = cast[ptr byte](addr contigiousBytes[0])
|
||||||
bytesLen = contigiousBytes.len
|
bytesLen = contigiousBytes.len
|
||||||
|
|
||||||
template bytesVar: untyped =
|
consumer(makeOpenArray(bytesPtr, bytesLen))
|
||||||
makeOpenArray(bytesPtr, bytesLen)
|
|
||||||
|
|
||||||
body
|
s.span = s.buffers.getWritableSpan()
|
||||||
|
s.spanEndPos += s.span.len - runway
|
||||||
|
|
||||||
|
template consumeContiguousOutput*(s: OutputStream, bytesVar, body: untyped) =
|
||||||
|
## Please note that calling `consumeContiguousOutput` on an unbuffered stream
|
||||||
|
## or an unsafe memory stream is considered a Defect.
|
||||||
|
##
|
||||||
|
## Before consuming the output, all outstanding delayed writes must
|
||||||
|
## be finalized.
|
||||||
|
##
|
||||||
|
proc consumer(bytesVar: openarray[byte]) {.gcsafe, raises: [Defect].} =
|
||||||
|
body
|
||||||
|
|
||||||
|
consumeContiguousOutputImpl(s, consumer)
|
||||||
|
|
||||||
proc getOutput*(s: OutputStream, T: type string): string =
|
proc getOutput*(s: OutputStream, T: type string): string =
|
||||||
## Please note that calling `getOutput` on an unbuffered stream
|
## Please note that calling `getOutput` on an unbuffered stream
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue