From e759f255192beb7f95cb60b8a07286b3a514570e Mon Sep 17 00:00:00 2001 From: Alberto Torres Date: Tue, 3 Sep 2024 14:42:57 +0200 Subject: [PATCH] ArrRef and SliceMem: Add `concat`, suport for backward indexes, and fix `$`. --- libs/arr_ref/arr_ref.nim | 47 +++++++++++++++++++----------- libs/arr_ref/slice_mem.nim | 59 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 19 deletions(-) diff --git a/libs/arr_ref/arr_ref.nim b/libs/arr_ref/arr_ref.nim index ab554f3..3bb9d88 100644 --- a/libs/arr_ref/arr_ref.nim +++ b/libs/arr_ref/arr_ref.nim @@ -48,6 +48,12 @@ proc `[]=`*[T](a: ArrRef[T], i: Natural, v: T) = raise newException(RangeDefect, &"index out of range: {i} >= {a.len}") a.arr[i] = v +template `[]`*[T](a: ArrRef[T], i: BackwardsIndex): T = + a[a.len - i.int] + +template `[]=`*[T](a: ArrRef[T], i: BackwardsIndex, v: T) = + a[a.len - i.int] = v + template toPointer*[T](a: ArrRef[T]): pointer = a.arr[0].addr iterator items*[T](a: ArrRef[T]): T = @@ -68,7 +74,7 @@ iterator mpairs*[T](a: ArrRef[T]): tuple[key: int, val: var T] = proc `$`*[T](a: ArrRef[T]): string = result = "ArrRef([" - if a.endp != a.arr: + if a.byte_len >= sizeof(T): let hi = a.high for i in 0 ..< hi: result &= $a[i] & ", " @@ -78,21 +84,6 @@ proc `$`*[T](a: ArrRef[T]): string = template to*[T](a: ArrRef[T], U: untyped): untyped = cast[ArrRef[U]](a) -# proc setCap*[T](a: var ArrRef[T], size: Natural) = -# let n = newArrRef[T](size) -# copyMem(n[0].addr, a[0].addr, min(size, a.len) * sizeof(T)) -# a = n - -# proc setGrow*[T](a: var ArrRef[T], i: Natural, v: T) = -# let p = cast[int](a) +% header_size +% sizeof(T) * i -# if p +% sizeof(T) > cast[int](a.endp): -# var cap = max(1, a.len) -# while i >= cap: -# if cap < 65535: cap *= 2 -# else: cap = (cap * 3) div 2 -# a.setCap cap -# cast[ptr T](p)[] = v - proc fill*[T](a: ArrRef[T], v: T) = for i in a.low .. a.high: a[i] = v @@ -108,11 +99,14 @@ proc newArrRefWith*[T](size: Natural, v: T): ArrRef[T] = result.arr_ptr = result.arr[0].addr for i in result.low .. result.high: result[i] = v -proc newArrRef*[T](s: seq[T] | ArrRef[T]): ArrRef[T] = +proc newArrRef*[T](s: seq[T] | ArrRef[T] | openArray[T]): ArrRef[T] = result = newArrRef[T](s.len) if s.len != 0: copyMem(result.arr.addr, s[0].addr, s.len * sizeof(T)) +template newArrRef*[T](s: string): ArrRef[T] = + newArrRef[byte](s.toOpenArrayByte(0, s.high)).to(T) + proc newArrRef*[T; U: not T](s: seq[U]): ArrRef[T] = result = newArrRef[T](s.len) for i,v in s: result[i] = v.T @@ -139,3 +133,22 @@ proc hash*[T](arr: ArrRef[T]): Hash = template `[]`*[T](a: ArrRef[T], s: Slice[int]): var SliceMem[T] = toSliceMem(a, s) +template concatImpl(arrs: untyped) = + var total = 0 + for a in arrs: + total += a.len + result = newArrRef[T](total) + var offset = 0 + for a in arrs: + copyMem(result[offset].addr, a.toPointer, a.len * sizeof(T)) + offset += a.len + +proc concat*[T](arrs: varargs[ArrRef[T]]): ArrRef[T] = + concatImpl(arrs) + +proc concat*[T](arrs: seq[ArrRef[T]]): ArrRef[T] = + concatImpl(arrs) + +template `&`*[T,U](a: ArrRef[T], b: ArrRef[U]): ArrRef[T] = + concat(a, b.to(T)) + diff --git a/libs/arr_ref/slice_mem.nim b/libs/arr_ref/slice_mem.nim index 2771ddf..f1e29ad 100644 --- a/libs/arr_ref/slice_mem.nim +++ b/libs/arr_ref/slice_mem.nim @@ -26,6 +26,9 @@ proc `=destroy`(s: var CustomDestructor) = template toInt(p: pointer): int = cast[int](p) # template toPointer(i: int): pointer = cast[pointer](p) +template toPointer*(s: SliceMem): pointer = + s.data.pointer + proc newSliceMem*[T, U](container: sink U; p: pointer, byte_len: int): SliceMem[T] = ## Create a SliceMem from a container, a pointer, and a length in bytes. result = SliceMem[T]( @@ -67,6 +70,18 @@ proc newSliceMem*[T, U](container: sink U; first, last: pointer): SliceMem[T] = ), ) +proc newSliceMem*[T](size: int): SliceMem[T] = + ## Create a SliceMem from new memory, similar to ArrRef[T]. + var r: ref byte + unsafeNew(r, size * sizeof(T)) + result = SliceMem[T]( + data: cast[ptr UncheckedArray[T]](r), + byte_len: size * sizeof(T), + destroy_ref: (ref CustomDestructor)(destroy: proc()= + discard r + ), + ) + macro noMove(e: untyped): untyped = if e.kind == nnkCommand and e[0].repr == "move": e[1] else: e @@ -97,18 +112,33 @@ template low*[T](s: SliceMem[T]): Natural = 0 template high*[T](s: SliceMem[T]): int = s.len - 1 -template `[]`*[T](s: SliceMem[T], i: Natural): var T = +proc `[]`*[T](s: SliceMem[T], i: Natural): var T {.inline.} = when compileOption("rangechecks"): if i >= s.len: raise newException(RangeDefect, &"index out of range: {i} >= {s.len}") s.data[i] -proc `[]=`*[T](s: SliceMem[T], i: Natural, v: T) = +proc `[]=`*[T](s: SliceMem[T], i: Natural, v: T) {.inline.} = when compileOption("rangechecks"): if i >= s.len: raise newException(RangeDefect, &"index out of range: {i} >= {s.len}") s.data[i] = v +template `[]`*[T](s: SliceMem[T], i: BackwardsIndex): T = + s[s.len - i.int] + +template `[]=`*[T](s: SliceMem[T], i: BackwardsIndex, v: T) = + s[s.len - i.int] = v + +template `[]`*[T](s: SliceMem[T], i: BackwardsIndex): T = + s[s.len - i.int] + +template `[]=`*[T](s: SliceMem[T], i: BackwardsIndex, v: T) = + s[s.len - i.int] = v + +template `[]`*[T](a: SliceMem[T], s: Slice[int]): var SliceMem[T] = + toSliceMem(a, s) + iterator items*[T](s: SliceMem[T]): T = for i in 0 ..< s.len: yield s.data[i] @@ -146,3 +176,28 @@ template toOpenArrayByte*(s: SliceMem): untyped = template to*[T](s: SliceMem, typ: typedesc[T]): SliceMem[T] = cast[SliceMem[T]](s) + +template to*[T](s: seq[SliceMem], typ: typedesc[T]): seq[SliceMem[T]] = + var s2 = newSeqOfCap[SliceMem[T]](s.len) + for slice in s: + s2.add cast[SliceMem[T]](slice) + s2 + +template concatImpl(slices: untyped) = + var total = 0 + for s in slices: + total += s.len + result = newSliceMem[T](total) + var offset = 0 + for s in slices: + copyMem(result[offset].addr, s.data, s.len * sizeof(T)) + offset += s.len + +proc concat*[T](slices: varargs[SliceMem[T]]): SliceMem[T] = + concatImpl(slices) + +proc concat*[T](slices: seq[SliceMem[T]]): SliceMem[T] = + concatImpl(slices) + +template `&`*[T,U](a: SliceMem[T], b: SliceMem[U]): SliceMem[T] = + concat(a, b.to(T))