remove `stew/ranges` (#152)
* deprecated for years * relies on unavailable (shallowCopy) or broken (missing range checks) features in nim
This commit is contained in:
parent
665e1d1604
commit
f295d00db9
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{.used.}
|
||||
|
||||
import
|
||||
ttypedranges, tstackarrays, tbitranges
|
||||
tstackarrays
|
||||
|
|
|
@ -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"
|
|
@ -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])
|
||||
|
Loading…
Reference in New Issue