remove `stew/ranges` (#152)

* deprecated for years
* relies on unavailable (shallowCopy) or broken (missing range checks)
features in nim
This commit is contained in:
Jacek Sieka 2022-11-18 12:52:55 +01:00 committed by GitHub
parent 665e1d1604
commit f295d00db9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 3 additions and 829 deletions

View File

@ -1,11 +0,0 @@
{.deprecated: "unattractive memory unsafety - use openArray and other techniques instead".}
when not declared(shallowCopy):
{.error: "stew/ranges requires shallowCopy (--gc:refc)".}
import
ranges/memranges,
ranges/typedranges
export
memranges, typedranges

View File

@ -1,131 +0,0 @@
import
../bitops2, typedranges
type
BitRange* = object
data: MutByteRange
start: int
mLen: int
template `@`(s, idx: untyped): untyped =
(when idx is BackwardsIndex: s.len - int(idx) else: int(idx))
proc bits*(a: MutByteRange, start, len: int): BitRange =
doAssert start <= len
doAssert len <= 8 * a.len
result.data = a
result.start = start
result.mLen = len
template bits*(a: var seq[byte], start, len: int): BitRange =
bits(a.toRange, start, len)
template bits*(a: MutByteRange): BitRange =
bits(a, 0, a.len * 8)
template bits*(a: var seq[byte]): BitRange =
bits(a.toRange, 0, a.len * 8)
template bits*(a: MutByteRange, len: int): BitRange =
bits(a, 0, len)
template bits*(a: var seq[byte], len: int): BitRange =
bits(a.toRange, 0, len)
template bits*(bytes: MutByteRange, slice: HSlice): BitRange =
bits(bytes, bytes @ slice.a, bytes @ slice.b)
template bits*(x: BitRange): BitRange = x
proc len*(r: BitRange): int {.inline.} = r.mLen
iterator enumerateBits(x: BitRange): (int, bool) =
var p = x.start
var i = 0
let e = x.len
while i != e:
yield (i, getBitBE(x.data.toOpenArray, p))
inc p
inc i
iterator items*(x: BitRange): bool =
for _, v in enumerateBits(x): yield v
iterator pairs*(x: BitRange): (int, bool) =
for i, v in enumerateBits(x): yield (i, v)
proc `[]`*(x: BitRange, idx: int): bool {.inline.} =
doAssert idx < x.len
let p = x.start + idx
result = getBitBE(x.data.toOpenArray, p)
proc sliceNormalized(x: BitRange, ibegin, iend: int): BitRange =
doAssert ibegin >= 0 and
ibegin < x.len and
iend < x.len and
iend + 1 >= ibegin # the +1 here allows the result to be
# an empty range
result.data = x.data
result.start = x.start + ibegin
result.mLen = iend - ibegin + 1
proc `[]`*(r: BitRange, s: HSlice): BitRange {.inline.} =
sliceNormalized(r, r @ s.a, r @ s.b)
proc `==`*(a, b: BitRange): bool =
if a.len != b.len: return false
for i in 0 ..< a.len:
if a[i] != b[i]: return false
true
proc `[]=`*(r: var BitRange, idx: Natural, val: bool) {.inline.} =
doAssert idx < r.len
let absIdx = r.start + idx
changeBitBE(r.data.toOpenArray, absIdx, val)
proc pushFront*(x: var BitRange, val: bool) =
doAssert x.start > 0
dec x.start
x[0] = val
inc x.mLen
template neededBytes(nBits: int): int =
(nBits shr 3) + ord((nBits and 0b111) != 0)
static:
doAssert neededBytes(2) == 1
doAssert neededBytes(8) == 1
doAssert neededBytes(9) == 2
proc `&`*(a, b: BitRange): BitRange =
let totalLen = a.len + b.len
var bytes = newSeq[byte](totalLen.neededBytes)
result = bits(bytes, 0, totalLen)
for i in 0 ..< a.len: result.data.toOpenArray.changeBitBE(i, a[i])
for i in 0 ..< b.len: result.data.toOpenArray.changeBitBE(i + a.len, b[i])
proc `$`*(r: BitRange): string =
result = newStringOfCap(r.len)
for bit in r:
result.add(if bit: '1' else: '0')
proc fromBits*(T: type, r: BitRange, offset, num: Natural): T =
doAssert(num <= sizeof(T) * 8)
# XXX: Nim has a bug that a typedesc parameter cannot be used
# in a type coercion, so we must define an alias here:
type TT = T
for i in 0 ..< num:
result = (result shl 1) or TT(r[offset + i])
proc parse*(T: type BitRange, s: string): BitRange =
var bytes = newSeq[byte](s.len.neededBytes)
for i, c in s:
case c
of '0': discard
of '1': setBitBE(bytes, i)
else: doAssert false
result = bits(bytes, 0, s.len)

View File

@ -1,34 +0,0 @@
{.deprecated: "unattractive memory unsafety - use openArray and other techniques instead".}
import
ptr_arith
type
MemRange* = object
start: pointer
size: csize
template len*(mr: MemRange): int = mr.size
template `[]`*(mr: MemRange, idx: int): byte = (cast[ptr byte](shift(mr.start, idx)))[]
proc baseAddr*(mr: MemRange): pointer = mr.start
proc makeMemRange*(start: pointer, size: csize): MemRange =
result.start = start
result.size = size
proc toMemRange*(x: string): MemRange =
result.start = x.cstring.pointer
result.size = x.len
proc toMemRange*[T](x: openArray[T], fromIdx, toIdx: int): MemRange =
doAssert(fromIdx >= 0 and toIdx >= fromIdx and fromIdx < x.len and toIdx < x.len)
result.start = unsafeAddr x[fromIdx]
result.size = (toIdx - fromIdx + 1) * T.sizeof
proc toMemRange*[T](x: openArray[T], fromIdx: int): MemRange {.inline.} =
toMemRange(x, fromIdx, x.high)
proc toMemRange*[T](x: openArray[T]): MemRange {.inline.} =
toMemRange(x, 0, x.high)
template toMemRange*(mr: MemRange): MemRange = mr

View File

@ -1,251 +0,0 @@
{.deprecated: "unattractive memory unsafety - use openArray and other techniques instead".}
import ../ptrops, typetraits, hashes
when (NimMajor, NimMinor) < (1, 4):
import ../shims/stddefects
const rangesGCHoldEnabled = not defined(rangesDisableGCHold)
const unsafeAPIEnabled* = defined(rangesEnableUnsafeAPI)
type
# A view into immutable array
Range*[T] {.shallow.} = object
when rangesGCHoldEnabled:
gcHold: seq[T]
start: ptr T
mLen: int
# A view into mutable array
MutRange*[T] {.shallow.} = distinct Range[T]
ByteRange* = Range[byte]
MutByteRange* = MutRange[byte]
proc isLiteral[T](s: seq[T]): bool {.inline.} =
type
SeqHeader = object
length, reserved: int
(cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0
proc toImmutableRange[T](a: seq[T]): Range[T] =
if a.len != 0:
when rangesGCHoldEnabled:
if not isLiteral(a):
shallowCopy(result.gcHold, a)
else:
result.gcHold = a
result.start = addr result.gcHold[0]
result.mLen = a.len
when unsafeAPIEnabled:
proc toImmutableRangeNoGCHold[T](a: openArray[T]): Range[T] =
if a.len != 0:
result.start = unsafeAddr a[0]
result.mLen = a.len
proc toImmutableRange[T](a: openArray[T]): Range[T] {.inline.} =
toImmutableRangeNoGCHold(a)
proc toRange*[T](a: var seq[T]): MutRange[T] {.inline.} =
MutRange[T](toImmutableRange(a))
when unsafeAPIEnabled:
proc toRange*[T](a: var openArray[T]): MutRange[T] {.inline.} =
MutRange[T](toImmutableRange(a))
template initStackRange*[T](sz: static[int]): MutRange[T] =
var data: array[sz, T]
data.toRange()
proc toRange*[T](a: openArray[T]): Range[T] {.inline.} = toImmutableRange(a)
proc unsafeRangeConstruction*[T](a: var openArray[T]): MutRange[T] {.inline.} =
MutRange[T](toImmutableRange(a))
proc unsafeRangeConstruction*[T](a: openArray[T]): Range[T] {.inline.} =
toImmutableRange(a)
proc newRange*[T](sz: int): MutRange[T] {.inline.} =
MutRange[T](toImmutableRange(newSeq[T](sz)))
proc toRange*[T](a: seq[T]): Range[T] {.inline.} = toImmutableRange(a)
converter toImmutableRange*[T](a: MutRange[T]): Range[T] {.inline.} = Range[T](a)
proc len*(r: Range): int {.inline.} = int(r.mLen)
proc high*(r: Range): int {.inline.} = r.len - 1
proc low*(r: Range): int {.inline.} = 0
proc elemAt[T](r: MutRange[T], idx: int): var T {.inline.} =
doAssert(idx < r.len)
Range[T](r).start.offset(idx)[]
proc `[]=`*[T](r: MutRange[T], idx: int, v: T) {.inline.} = r.elemAt(idx) = v
proc `[]`*[T](r: MutRange[T], i: int): var T = r.elemAt(i)
proc `[]`*[T](r: Range[T], idx: int): T {.inline.} =
doAssert(idx < r.len)
r.start.offset(idx)[]
proc `==`*[T](a, b: Range[T]): bool =
if a.len != b.len: return false
equalMem(a.start, b.start, sizeof(T) * a.len)
iterator ptrs[T](r: Range[T]): (int, ptr T) =
var p = r.start
var i = 0
let e = r.len
while i != e:
yield (i, p)
p = p.offset(1)
inc i
iterator items*[T](r: Range[T]): T =
for _, v in ptrs(r): yield v[]
iterator pairs*[T](r: Range[T]): (int, T) =
for i, v in ptrs(r): yield (i, v[])
iterator mitems*[T](r: MutRange[T]): var T =
for _, v in ptrs(r): yield v[]
iterator mpairs*[T](r: MutRange[T]): (int, var T) =
for i, v in ptrs(r): yield (i, v[])
proc toSeq*[T](r: Range[T]): seq[T] =
result = newSeqOfCap[T](r.len)
for i in r: result.add(i)
proc `$`*(r: Range): string =
result = "R["
for i, v in r:
if i != 0:
result &= ", "
result &= $v
result &= "]"
proc sliceNormalized[T](r: Range[T], ibegin, iend: int): Range[T] =
doAssert ibegin >= 0 and
ibegin < r.len and
iend < r.len and
iend + 1 >= ibegin # the +1 here allows the result to be
# an empty range
when rangesGCHoldEnabled:
shallowCopy(result.gcHold, r.gcHold)
result.start = r.start.offset(ibegin)
result.mLen = iend - ibegin + 1
proc slice*[T](r: Range[T], ibegin = 0, iend = -1): Range[T] =
let e = if iend < 0: r.len + iend
else: iend
sliceNormalized(r, ibegin, e)
proc slice*[T](r: MutRange[T], ibegin = 0, iend = -1): MutRange[T] {.inline.} =
MutRange[T](Range[T](r).slice(ibegin, iend))
template `^^`(s, i: untyped): untyped =
(when i is BackwardsIndex: s.len - int(i) else: int(i))
proc `[]`*[T, U, V](r: Range[T], s: HSlice[U, V]): Range[T] {.inline.} =
sliceNormalized(r, r ^^ s.a, r ^^ s.b)
proc `[]`*[T, U, V](r: MutRange[T], s: HSlice[U, V]): MutRange[T] {.inline.} =
MutRange[T](sliceNormalized(r, r ^^ s.a, r ^^ s.b))
proc `[]=`*[T, U, V](r: MutRange[T], s: HSlice[U, V], v: openArray[T]) =
let a = r ^^ s.a
let b = r ^^ s.b
let L = b - a + 1
if L == v.len:
for i in 0..<L: r[i + a] = v[i]
else:
raise newException(RangeDefect, "different lengths for slice assignment")
template toOpenArray*[T](r: Range[T]): auto =
# NOTE: `0` in `array[0, T]` is irrelevant
toOpenArray(cast[ptr array[0, T]](r.start)[], 0, r.high)
proc `[]=`*[T, U, V](r: MutRange[T], s: HSlice[U, V], v: Range[T]) {.inline.} =
r[s] = toOpenArray(v)
proc baseAddr*[T](r: Range[T]): ptr T {.inline.} = r.start
proc gcHolder*[T](r: Range[T]): ptr T {.inline.} =
## This procedure is used only for shallow test, do not use it
## in production.
when rangesGCHoldEnabled:
if r.len > 0:
result = unsafeAddr r.gcHold[0]
template toRange*[T](a: Range[T]): Range[T] = a
# this preferred syntax doesn't work
# see https://github.com/nim-lang/Nim/issues/7995
#template copyRange[T](dest: seq[T], destOffset: int, src: Range[T]) =
# when supportsCopyMem(T):
template copyRange[T](E: typedesc, dest: seq[T], destOffset: int, src: Range[T]) =
when supportsCopyMem(E):
if dest.len != 0 and src.len != 0:
copyMem(dest[destOffset].unsafeAddr, src.start, sizeof(T) * src.len)
else:
for i in 0..<src.len:
dest[i + destOffset] = src[i]
proc concat*[T](v: varargs[Range[T], toRange]): seq[T] =
var len = 0
for c in v: inc(len, c.len)
result = newSeq[T](len)
len = 0
for c in v:
copyRange(T, result, len, c)
inc(len, c.len)
proc `&`*[T](a, b: Range[T]): seq[T] =
result = newSeq[T](a.len + b.len)
copyRange(T, result, 0, a)
copyRange(T, result, a.len, b)
proc hash*(x: Range): Hash =
result = hash(toOpenArray(x))
template advanceImpl(a, b: untyped): bool =
var res = false
if b == 0:
res = true
elif b > 0:
if isNil(a.start) or a.mLen <= 0:
res = false
else:
if a.mLen - b < 0:
res = false
else:
a.start = a.start.offset(b)
a.mLen -= b
res = true
res
proc tryAdvance*[T](x: var Range[T], idx: int): bool =
## Move internal start offset of range ``x`` by ``idx`` elements forward.
##
## Returns ``true`` if operation got completed successfully, or
## ``false`` if you are trying to overrun range ``x``.
result = x.advanceImpl(idx)
proc tryAdvance*[T](x: var MutRange[T], idx: int): bool {.inline.} =
## Move internal start offset of range ``x`` by ``idx`` elements forward.
##
## Returns ``true`` if operation got completed successfully, or
## ``false`` if you are trying to overrun range ``x``.
result = tryAdvance(Range[T](x), idx)
proc advance*[T](x: var Range[T], idx: int) =
## Move internal start offset of range ``x`` by ``idx`` elements forward.
let res = x.advanceImpl(idx)
if not res: raise newException(IndexDefect, "Advance Error")
proc advance*[T](x: var MutRange[T], idx: int) {.inline.} =
## Move internal start offset of range ``x`` by ``idx`` elements forward.
advance(Range[T](x), idx)

View File

@ -7,8 +7,8 @@
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
when declared(shallowCopy):
import ranges/all
import ranges/all
import
test_assign2,
test_arrayops,

View File

@ -1,4 +1,4 @@
{.used.}
import
ttypedranges, tstackarrays, tbitranges
tstackarrays

View File

@ -1,133 +0,0 @@
# Copyright (c) 2019-2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license: http://opensource.org/licenses/MIT
# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.used.}
import
random, unittest2,
../../stew/ranges/bitranges, ../../stew/bitseqs
proc randomBytes(n: int): seq[byte] =
result = newSeq[byte](n)
for i in 0 ..< result.len:
result[i] = byte(rand(256))
suite "bit sequences":
test "growing and indexing":
var b0 = BitSeq.init(0)
check b0.len == 0
var b10 = BitSeq.init(10)
check b10.len == 10
var b100 = BitSeq.init(100)
check b100.len == 100
var bytes = randomBytes(50)
var bitArr: BitArray[50]
for i in 0 ..< bytes.len:
let bit = bytes[i] < 128
b0.add bit
if i < b10.len:
b10[i] = bit
else:
b10.add bit
b100[i] = bit
bitArr[i] = bit
check:
b0.len == i + 1
b10.len == max(i + 1, 10)
b100.len == 100
for i in 0 ..< bytes.len:
let bit = bytes[i] < 128
check:
b0[i] == bit
b10[i] == bit
b100[i] == bit
bitArr[i] == bit
suite "bit ranges":
test "basic":
var a = @[byte 0b10101010, 0b11110000, 0b00001111, 0b01010101]
var bSeq = @[byte 0b10101010, 0b00000000, 0b00000000, 0b11111111]
var b = bits(bSeq, 8)
var cSeq = @[byte 0b11110000, 0b00001111, 0b00000000, 0b00000000]
var c = bits(cSeq, 16)
var dSeq = @[byte 0b00001111, 0b00000000, 0b00000000, 0b00000000]
var d = bits(dSeq, 8)
var eSeq = @[byte 0b01010101, 0b00000000, 0b00000000, 0b00000000]
var e = bits(eSeq, 8)
var m = a.bits
var n = m[0..7]
check n == b
check n.len == 8
check b.len == 8
check c == m[8..23]
check $(d) == "00001111"
check $(e) == "01010101"
var f = int.fromBits(e, 0, 4)
check f == 0b0101
let k = n & d
check(k.len == n.len + d.len)
check($k == $n & $d)
var asciiSeq = @[byte('A'),byte('S'),byte('C'),byte('I'),byte('I')]
let asciiBits = bits(asciiSeq)
check $asciiBits == "0100000101010011010000110100100101001001"
test "concat operator":
randomize(5000)
for i in 0..<256:
var xSeq = randomBytes(rand(i))
var ySeq = randomBytes(rand(i))
let x = xSeq.bits
let y = ySeq.bits
var z = x & y
check z.len == x.len + y.len
check($z == $x & $y)
test "get set bits":
randomize(1000)
for i in 0..<256:
# produce random vector
var xSeq = randomBytes(i)
var ySeq = randomBytes(i)
var x = xSeq.bits
var y = ySeq.bits
for idx, bit in x:
y[idx] = bit
check x == y
test "constructor with start":
var a = @[byte 0b10101010, 0b11110000, 0b00001111, 0b01010101]
var b = a.bits(1, 8)
check b.len == 8
check b[0] == false
check $b == "01010101"
b[0] = true
check $b == "11010101"
check b[0] == true
b.pushFront(false)
check b[0] == false
check $b == "011010101"

View File

@ -1,266 +0,0 @@
# Copyright (c) 2019-2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license: http://opensource.org/licenses/MIT
# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.used.}
import
unittest2, sets,
../../stew/ranges/[typedranges, ptr_arith]
when (NimMajor, NimMinor) < (1, 4):
import ../../stew/shims/stddefects
suite "Typed ranges":
test "basic stuff":
var r = newRange[int](5)
r[0] = 1
r[1 .. ^1] = [2, 3, 4, 5]
check $r == "R[1, 2, 3, 4, 5]"
var s = newSeq[int]()
for a in r: s.add(a)
check s == @[1, 2, 3, 4, 5]
test "subrange":
var a = newRange[int](5)
let b = toRange(@[1, 2, 3])
a[1 .. 3] = b
check a.toSeq == @[0, 1, 2, 3, 0]
check:
a[2 .. 2].len == 1
a[1 ..< 1].len == 0
test "equality operator":
var x = toRange(@[0, 1, 2, 3, 4, 5])
var y = x[1 .. ^2]
var z = toRange(@[1, 2, 3, 4])
check y == z
check x != z
test "concat operation":
var a = toRange(@[1,2,3])
var b = toRange(@[4,5,6])
var c = toRange(@[7,8,9])
var d = @[1,2,3,4,5,6,7,8,9]
var e = @[1,2,3,4,5,6]
var f = @[4,5,6,7,8,9]
var x = concat(a, b, c)
var y = a & b
check x == d
check y == e
var z = concat(b, @[7,8,9])
check z == f
let u = toRange(newSeq[int](0))
let v = toRange(@[3])
check concat(u, v) == @[3]
check (v & u) == @[3]
test "complex types concat operation":
type
Jaeger = object
name: string
weight: int
var A = Jaeger(name: "Gipsy Avenger", weight: 2004)
var B = Jaeger(name: "Striker Eureka", weight: 1850)
var C = Jaeger(name: "Saber Athena", weight: 1628)
var D = Jaeger(name: "Cherno Alpha", weight: 2412)
var k = toRange(@[A, B])
var m = toRange(@[C, D])
var n = concat(k, m)
check n == @[A, B, C ,D]
check n != @[A, B, C ,C]
test "shallowness":
var s = @[1, 2, 3]
var r = s.toRange()
var r2 = r
s[0] = 5
check(r[0] == 5)
s[1] = 10
check(r2[1] == 10)
var r3 = r[2..2]
s[2] = 15
check(r3[0] == 15)
test "hash function":
var a = toRange(@[1,2,3])
var b = toRange(@[4,5,6])
var c = toRange(@[7,8,9])
var d = toRange(@[1,2,3,4,5,6,7,8,9])
var e = toRange(@[1,2,3,4,5,6,7,8,9])
var x = toHashSet([a, b, c, a, b])
check x.len == 3
check a in x
var z = toRange(@[7,8,9])
var y = toHashSet([z, b, c])
check z in y
check z in x
var u = d[0..2]
var v = d[3..5]
var uu = e[0..2]
var vv = e[3..5]
check hash(u) != hash(v)
check hash(uu) == hash(u)
check hash(v) == hash(vv)
check hash(uu) != hash(vv)
test "toOpenArray":
var a = toRange(@[1,2,3])
check $a.toOpenArray == "[1, 2, 3]"
test "MutRange[T] shallow test":
var b = @[1, 2, 3, 4, 5, 6]
var r1 = b.toRange()
var r2 = r1
b[0] = 5
b[1] = 10
b[2] = 15
var r3 = r1[1..1]
var a0 = cast[uint](addr b[0])
var a1 = cast[uint](r1.gcHolder)
var a2 = cast[uint](r2.gcHolder)
var a3 = cast[uint](r3.gcHolder)
check:
a1 == a0
a2 == a0
a3 == a0
test "Range[T] shallow test":
var r1 = toRange(@[1, 2, 3, 4, 5, 6])
var r2 = r1
var r3 = r1[1..1]
var a1 = cast[uint](r1.gcHolder)
var a2 = cast[uint](r2.gcHolder)
var a3 = cast[uint](r3.gcHolder)
check:
a2 == a1
a3 == a1
test "tryAdvance(Range)":
var a: Range[int]
check:
a.tryAdvance(1) == false
a.tryAdvance(-1) == false
a.tryAdvance(0) == true
var b = toRange(@[1, 2, 3])
check:
b.tryAdvance(-1) == false
$b.toOpenArray == "[1, 2, 3]"
b.tryAdvance(0) == true
$b.toOpenArray == "[1, 2, 3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[2, 3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[]"
b.tryAdvance(1) == false
$b.toOpenArray == "[]"
test "advance(Range)":
template aecheck(a, b): int =
var res = 0
try:
a.advance(b)
res = 1
except IndexDefect:
res = 2
res
var a: Range[int]
check:
a.aecheck(1) == 2
a.aecheck(-1) == 2
a.aecheck(0) == 1
var b = toRange(@[1, 2, 3])
check:
b.aecheck(-1) == 2
$b.toOpenArray == "[1, 2, 3]"
b.aecheck(0) == 1
$b.toOpenArray == "[1, 2, 3]"
b.aecheck(1) == 1
$b.toOpenArray == "[2, 3]"
b.aecheck(1) == 1
$b.toOpenArray == "[3]"
b.aecheck(1) == 1
$b.toOpenArray == "[]"
b.aecheck(1) == 2
$b.toOpenArray == "[]"
test "tryAdvance(MutRange)":
var a: MutRange[int]
check:
a.tryAdvance(1) == false
a.tryAdvance(-1) == false
a.tryAdvance(0) == true
var buf = @[1, 2, 3]
var b = toRange(buf)
check:
b.tryAdvance(-1) == false
$b.toOpenArray == "[1, 2, 3]"
b.tryAdvance(0) == true
$b.toOpenArray == "[1, 2, 3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[2, 3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[3]"
b.tryAdvance(1) == true
$b.toOpenArray == "[]"
b.tryAdvance(1) == false
$b.toOpenArray == "[]"
test "advance(MutRange)":
template aecheck(a, b): int =
var res = 0
try:
a.advance(b)
res = 1
except IndexDefect:
res = 2
res
var a: MutRange[int]
check:
a.aecheck(1) == 2
a.aecheck(-1) == 2
a.aecheck(0) == 1
var buf = @[1, 2, 3]
var b = toRange(buf)
check:
b.aecheck(-1) == 2
$b.toOpenArray == "[1, 2, 3]"
b.aecheck(0) == 1
$b.toOpenArray == "[1, 2, 3]"
b.aecheck(1) == 1
$b.toOpenArray == "[2, 3]"
b.aecheck(1) == 1
$b.toOpenArray == "[3]"
b.aecheck(1) == 1
$b.toOpenArray == "[]"
b.aecheck(1) == 2
$b.toOpenArray == "[]"
test "make openarrays from pointers":
var str = "test 1,2,3"
var charPtr: ptr char = addr str[7]
var regularPtr: pointer = addr str[5]
check:
# (regularPtr.makeOpenArray(char, 4).len == 4)
(regularPtr.makeOpenArray(char, 5) == "1,2,3")
(regularPtr.makeOpenArray(char, 5) == str[5..9])
# (charPtr.makeOpenArray(3).len == 3)
(charPtr.makeOpenArray(3) == "2,3")
(charPtr.makeOpenArray(1) == str[7..7])