Cosmetic renames and a simple helper for writing to arrays

This commit is contained in:
Zahary Karadjov 2019-08-07 05:18:56 +03:00
commit 6bbe1c21b6
No known key found for this signature in database
GPG key ID: C8936F8A3073D609
3 changed files with 25 additions and 20 deletions

View file

@ -55,6 +55,7 @@ proc init*(T: type ByteStream,
# TODO: the result should use `from mem` once it's supported # TODO: the result should use `from mem` once it's supported
result.head = unsafeAddr mem[0] result.head = unsafeAddr mem[0]
result.bufferEnd = result.head.shift mem.len result.bufferEnd = result.head.shift mem.len
result.bufferEndPos = mem.len
result.reader = reader result.reader = reader
result.asyncReader = asyncReader result.asyncReader = asyncReader
@ -73,7 +74,7 @@ proc init*(T: type BufferedStream,
proc endPos*(s: InputStreamVar): int = proc endPos*(s: InputStreamVar): int =
# TODO This needs to use a VTable for `system.File` based streams # TODO This needs to use a VTable for `system.File` based streams
s.bufferEndPos return s.bufferEndPos
proc syncRead(s: var ByteStream): bool = proc syncRead(s: var ByteStream): bool =
let bytesRead = s.reader(s.bufferStart, s.bufferSize) let bytesRead = s.reader(s.bufferStart, s.bufferSize)

View file

@ -48,15 +48,19 @@ const
# The goal is to make perfect page-aligned allocations # The goal is to make perfect page-aligned allocations
defaultPageSize = 4096 - allocatorMetadata - 1 # 1 byte for the null terminator defaultPageSize = 4096 - allocatorMetadata - 1 # 1 byte for the null terminator
proc createWriteCursor*[R, T](x: var array[R, T]): WriteCursor =
let startAddr = cast[ptr byte](addr x[0])
WriteCursor(head: startAddr, bufferEnd: shift(startAddr, sizeof x))
template canExtendOutput(s: OutputStreamVar): bool = template canExtendOutput(s: OutputStreamVar): bool =
# Streams writing to pre-allocated existing buffers cannot be grown # Streams writing to pre-allocated existing buffers cannot be grown
s.pageSize > 0 s != nil and s.pageSize > 0
template isExternalCursor(c: var WriteCursor): bool = template isExternalCursor(c: var WriteCursor): bool =
# Is this the original stream cursor or is it one created by a "delayed write" # Is this the original stream cursor or is it one created by a "delayed write"
addr(c) != addr(c.stream.cursor) addr(c) != addr(c.stream.cursor)
func remainingBytesToWrite*(c: var WriteCursor): int {.inline.} = func runway*(c: var WriteCursor): int {.inline.} =
distance(c.head, c.bufferEnd) distance(c.head, c.bufferEnd)
proc flipPage(s: OutputStreamVar) = proc flipPage(s: OutputStreamVar) =
@ -120,7 +124,7 @@ proc init*(T: type OutputStream,
result.endPos = len result.endPos = len
proc pos*(s: OutputStreamVar): int = proc pos*(s: OutputStreamVar): int =
s.endPos - s.cursor.remainingBytesToWrite s.endPos - s.cursor.runway
proc safeWritePage(s: OutputStreamVar, data: openarray[byte]) {.inline.} = proc safeWritePage(s: OutputStreamVar, data: openarray[byte]) {.inline.} =
if data.len > 0: s.vtable.writePage(s, data) if data.len > 0: s.vtable.writePage(s, data)
@ -133,7 +137,7 @@ proc writePages(s: OutputStreamVar, skipLast = 0) =
proc writePartialPage(s: OutputStreamVar, page: var OutputPage) = proc writePartialPage(s: OutputStreamVar, page: var OutputPage) =
assert s.vtable != nil assert s.vtable != nil
let let
unwrittenBytes = s.cursor.remainingBytesToWrite unwrittenBytes = s.cursor.runway
pageEndPos = s.pageSize - unwrittenBytes - 1 pageEndPos = s.pageSize - unwrittenBytes - 1
pageStartPos = page.startOffset pageStartPos = page.startOffset
@ -245,7 +249,7 @@ proc newStringFromBytes(input: ptr byte, inputLen: int): string =
proc handleLongAppend*(c: var WriteCursor, bytes: openarray[byte]) = proc handleLongAppend*(c: var WriteCursor, bytes: openarray[byte]) =
var var
pageRemaining = c.remainingBytesToWrite pageRemaining = c.runway
inputPos = unsafeAddr bytes[0] inputPos = unsafeAddr bytes[0]
inputLen = bytes.len inputLen = bytes.len
stream = c.stream stream = c.stream
@ -349,7 +353,7 @@ proc append*(c: var WriteCursor, bytes: openarray[byte]) {.inline.} =
# short enough to fit in the current page. We'll keep buffering until the # short enough to fit in the current page. We'll keep buffering until the
# page is full: # page is full:
let let
pageRemaining = c.remainingBytesToWrite pageRemaining = c.runway
inputLen = bytes.len inputLen = bytes.len
if inputLen <= pageRemaining: if inputLen <= pageRemaining:
@ -383,7 +387,7 @@ template appendMemCopy*(s: OutputStreamVar, value: auto) =
proc getOutput*(s: OutputStreamVar, T: type string): string = proc getOutput*(s: OutputStreamVar, T: type string): string =
doAssert s.vtable == nil and s.extCursorsCount == 0 and s.pageSize > 0 doAssert s.vtable == nil and s.extCursorsCount == 0 and s.pageSize > 0
s.pages[s.pages.len - 1].buffer.setLen(s.pageSize - s.cursor.remainingBytesToWrite) s.pages[s.pages.len - 1].buffer.setLen(s.pageSize - s.cursor.runway)
if s.pages.len == 1 and s.pages[0].startOffset == 0: if s.pages.len == 1 and s.pages[0].startOffset == 0:
result.swap s.pages[0].buffer result.swap s.pages[0].buffer
@ -416,7 +420,7 @@ proc createCursor(s: OutputStreamVar, size: int): WriteCursor =
s.cursor.head = result.bufferEnd s.cursor.head = result.bufferEnd
proc delayFixedSizeWrite*(s: OutputStreamVar, size: Natural): WriteCursor = proc delayFixedSizeWrite*(s: OutputStreamVar, size: Natural): WriteCursor =
let remainingBytesInPage = s.cursor.remainingBytesToWrite let remainingBytesInPage = s.cursor.runway
if size <= remainingBytesInPage: if size <= remainingBytesInPage:
result = s.createCursor(size) result = s.createCursor(size)
else: else:
@ -438,28 +442,28 @@ proc delayFixedSizeWrite*(s: OutputStreamVar, size: Natural): WriteCursor =
proc delayVarSizeWrite*(s: OutputStreamVar, maxSize: Natural): VarSizeWriteCursor = proc delayVarSizeWrite*(s: OutputStreamVar, maxSize: Natural): VarSizeWriteCursor =
doAssert maxSize < s.pageSize doAssert maxSize < s.pageSize
s.finishPageEarly s.cursor.remainingBytesToWrite s.finishPageEarly s.cursor.runway
VarSizeWriteCursor s.createCursor(maxSize) VarSizeWriteCursor s.createCursor(maxSize)
proc dispose*(cursor: var WriteCursor) = proc finalize*(cursor: var WriteCursor) =
doAssert cursor.stream.extCursorsCount > 0 doAssert cursor.stream.extCursorsCount > 0
dec cursor.stream.extCursorsCount dec cursor.stream.extCursorsCount
proc endWrite*(cursor: var WriteCursor, data: openarray[byte]) = proc writeAndFinalize*(cursor: var WriteCursor, data: openarray[byte]) =
doAssert data.len == cursor.remainingBytesToWrite doAssert data.len == cursor.runway
copyMem(cursor.head, unsafeAddr data[0], data.len) copyMem(cursor.head, unsafeAddr data[0], data.len)
dispose cursor finalize cursor
proc endWrite*(c: var VarSizeWriteCursor, data: openarray[byte]) = proc writeAndFinalize*(c: var VarSizeWriteCursor, data: openarray[byte]) =
template cursor: auto = WriteCursor(c) template cursor: auto = WriteCursor(c)
for page in mitems(cursor.stream.pages): for page in mitems(cursor.stream.pages):
if unsafeAddr(page.buffer[0]) == cursor.head: if unsafeAddr(page.buffer[0]) == cursor.head:
let overestimatedBytes = cursor.remainingBytesToWrite - data.len let overestimatedBytes = cursor.runway - data.len
doAssert overestimatedBytes >= 0 doAssert overestimatedBytes >= 0
page.startOffset = overestimatedBytes page.startOffset = overestimatedBytes
copyMem(cursor.head.shift(overestimatedBytes), unsafeAddr data[0], data.len) copyMem(cursor.head.shift(overestimatedBytes), unsafeAddr data[0], data.len)
dispose cursor finalize cursor
return return
doAssert false doAssert false

View file

@ -80,7 +80,7 @@ suite "output stream":
totalBytesWritten += count totalBytesWritten += count
check memStream.pos - cursorStart == totalBytesWritten check memStream.pos - cursorStart == totalBytesWritten
cursor.endWrite delayedWriteContent cursor.writeAndFinalize delayedWriteContent
checkOutputsMatch() checkOutputsMatch()
@ -116,7 +116,7 @@ suite "output stream":
delayedWrites[i].written += toWrite delayedWrites[i].written += toWrite
if remaining - toWrite == 0: if remaining - toWrite == 0:
dispose delayedWrites[i].cursor finalize delayedWrites[i].cursor
if i != delayedWrites.len - 1: if i != delayedWrites.len - 1:
swap(delayedWrites[i], delayedWrites[^1]) swap(delayedWrites[i], delayedWrites[^1])
delayedWrites.setLen(delayedWrites.len - 1) delayedWrites.setLen(delayedWrites.len - 1)
@ -141,7 +141,7 @@ suite "output stream":
for dw in mitems(delayedWrites): for dw in mitems(delayedWrites):
let remaining = dw.content.len - dw.written let remaining = dw.content.len - dw.written
dw.cursor.append dw.content[dw.written ..< dw.written + remaining] dw.cursor.append dw.content[dw.written ..< dw.written + remaining]
dispose dw.cursor finalize dw.cursor
# The final outputs are the same # The final outputs are the same
check altOutput == memStream.getOutput check altOutput == memStream.getOutput