From d087c039c2f88e06851b22040dd95f37452c3c81 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 18 Nov 2022 14:22:29 +0100 Subject: [PATCH] fix `baseAddr`, move to `ptrops` (#156) * return `nil` for empty openArrays / avoid returning `16` * move to `ptrops`, deprecate `ptr_arith` fully --- stew/ptrops.nim | 10 ++++++++++ stew/ranges/ptr_arith.nim | 11 ++--------- tests/test_ptrops.nim | 27 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/stew/ptrops.nim b/stew/ptrops.nim index 65d19b0..3074a0d 100644 --- a/stew/ptrops.nim +++ b/stew/ptrops.nim @@ -48,3 +48,13 @@ template distance*[T](a, b: ptr T): int = # Number of elements between a and b - undefined behavior when difference # exceeds what can be represented in an int distance(cast[pointer](a), cast[pointer](b)) div sizeof(T) + +proc baseAddr*[T](x: openArray[T]): ptr T = + # Return the address of the zero:th element of x or `nil` if x is empty + if x.len == 0: nil else: cast[ptr T](x) + +template makeOpenArray*[T](p: ptr T, len: Natural): openArray[T] = + toOpenArray(cast[ptr UncheckedArray[T]](p), 0, len - 1) + +template makeOpenArray*(p: pointer, T: type, len: Natural): openArray[T] = + toOpenArray(cast[ptr UncheckedArray[T]](p), 0, len - 1) diff --git a/stew/ranges/ptr_arith.nim b/stew/ranges/ptr_arith.nim index 016074b..ca84f96 100644 --- a/stew/ranges/ptr_arith.nim +++ b/stew/ranges/ptr_arith.nim @@ -1,8 +1,8 @@ +{.deprecated: "use stew/ptrops".} + import ../ptrops export ptrops -proc baseAddr*[T](x: openArray[T]): pointer = cast[pointer](x) - # Please note that we use templates here on purpose. # As much as I believe in the power of optimizing compilers, it turned # out that the use of forced inlining with templates still creates a @@ -13,10 +13,3 @@ template shift*(p: pointer, delta: int): pointer {.deprecated: "use ptrops".} = template shift*[T](p: ptr T, delta: int): ptr T {.deprecated: "use ptrops".} = p.offset(delta) - -template makeOpenArray*[T](p: ptr T, len: Natural): auto = - toOpenArray(cast[ptr UncheckedArray[T]](p), 0, len - 1) - -template makeOpenArray*(p: pointer, T: type, len: Natural): auto = - toOpenArray(cast[ptr UncheckedArray[T]](p), 0, len - 1) - diff --git a/tests/test_ptrops.nim b/tests/test_ptrops.nim index 55106e2..36c1d72 100644 --- a/tests/test_ptrops.nim +++ b/tests/test_ptrops.nim @@ -59,3 +59,30 @@ suite "ptrops": p0.distance(p0) == 0 p0.distance(p1) == 2 p1.distance(p0) == -2 + + test "baseAddr": + block arrays: + var + v0: array[0, int] = [] + v1 = [22] + + check: + baseAddr(v0) == nil + baseAddr(v1) == addr v1[0] + baseAddr(v1)[] == v1[0] + + block seqs: + var + v0: seq[int] + v1 = @[22] + + check: + baseAddr(v0) == nil + baseAddr(v1) == addr v1[0] + baseAddr(v1)[] == v1[0] + + block oas: + var v = 56 + check: + baseAddr(makeOpenArray(nil, int, 0)) == nil + baseAddr(makeOpenArray(addr v, 1)) == addr v