Implement helpers for using alloca-based stack arrays
This commit is contained in:
parent
bd47531c5f
commit
0fb54a8a9d
|
@ -0,0 +1,56 @@
|
|||
proc alloca(n: int): pointer {.importc, header: "<alloca.h>".}
|
||||
|
||||
type
|
||||
StackArray*[T] = ptr object
|
||||
bufferLen: int
|
||||
buffer: UncheckedArray[T]
|
||||
|
||||
template `[]`*(a: StackArray, i: int): auto =
|
||||
if i < 0 or i >= a.len: raise newException(RangeError, "index out of range")
|
||||
a.buffer[i]
|
||||
|
||||
proc `[]=`*(a: StackArray, i: int, val: a.T) =
|
||||
if i < 0 or i >= a.len: raise newException(RangeError, "index out of range")
|
||||
a.buffer[i] = val
|
||||
|
||||
proc len*(a: StackArray): int {.inline.} =
|
||||
a.bufferLen
|
||||
|
||||
template high*(a: StackArray): int =
|
||||
a.bufferLen - 1
|
||||
|
||||
template low*(a: StackArray): int =
|
||||
0
|
||||
|
||||
iterator items*(a: StackArray): a.T =
|
||||
for i in 0 .. a.high:
|
||||
yield a.buffer[i]
|
||||
|
||||
iterator mitems*(a: var StackArray): var a.T =
|
||||
for i in 0 .. a.high:
|
||||
yield a.buffer[i]
|
||||
|
||||
iterator pairs*(a: StackArray): a.T =
|
||||
for i in 0 .. a.high:
|
||||
yield (i, a.buffer[i])
|
||||
|
||||
iterator mpairs*(a: var StackArray): (int, var a.T) =
|
||||
for i in 0 .. a.high:
|
||||
yield (i, a.buffer[i])
|
||||
|
||||
template allocStackArray*(T: typedesc, size: int): auto =
|
||||
if size < 0: raise newException(RangeError, "allocation with a negative size")
|
||||
# XXX: is it possible to perform a stack size check before
|
||||
# calling `alloca`? Nim has a stackBottom pointer in the
|
||||
# system module.
|
||||
var
|
||||
bufferSize = size * sizeof(T)
|
||||
totalSize = sizeof(int) + bufferSize
|
||||
arr = cast[StackArray[T]](alloca(totalSize))
|
||||
zeroMem(addr arr.buffer[0], bufferSize)
|
||||
arr.bufferLen = size
|
||||
arr
|
||||
|
||||
template toOpenArray*(a: StackArray): auto =
|
||||
toOpenArray(a.buffer, 0, a.high)
|
||||
|
|
@ -1 +1,2 @@
|
|||
import ttypedranges
|
||||
import
|
||||
ttypedranges, tstackarrays
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import
|
||||
unittest, math,
|
||||
../ranges/stackarray
|
||||
|
||||
suite "Stack arrays":
|
||||
test "Basic operations work as expected":
|
||||
var arr = allocStackArray(int, 10)
|
||||
check:
|
||||
type(arr[0]) is int
|
||||
arr.len == 10
|
||||
|
||||
# all items should be initially zero
|
||||
for i in arr: check i == 0
|
||||
for i in 0 .. arr.high: check arr[i] == 0
|
||||
|
||||
arr[0] = 3
|
||||
arr[5] = 10
|
||||
arr[9] = 6
|
||||
|
||||
check:
|
||||
sum(arr.toOpenArray) == 19
|
||||
arr[5] == 10
|
||||
|
||||
test "Allocating with a negative size throws a RangeError":
|
||||
expect RangeError:
|
||||
var arr = allocStackArray(string, -1)
|
||||
|
||||
test "The array access is bounds-checked":
|
||||
var arr = allocStackArray(string, 3)
|
||||
arr[2] = "test"
|
||||
check arr[2] == "test"
|
||||
expect RangeError:
|
||||
arr[3] = "another test"
|
||||
|
Loading…
Reference in New Issue