Merge branch 'master' into test-with-nightly-nimble
This commit is contained in:
commit
2e765379be
|
@ -1,4 +1,4 @@
|
||||||
## Copyright (c) 2021-2023 Status Research & Development GmbH
|
## Copyright (c) 2021-2024 Status Research & Development GmbH
|
||||||
## Licensed under either of
|
## Licensed under either of
|
||||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
##
|
##
|
||||||
## Encoding procedures are adopted versions of C functions described here:
|
## Encoding procedures are adopted versions of C functions described here:
|
||||||
## # https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
|
## # https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
|
||||||
import results
|
import pkg/results
|
||||||
export results
|
export results
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
@ -39,7 +39,7 @@ type
|
||||||
data*: array[maxLen(Base10, T), byte]
|
data*: array[maxLen(Base10, T), byte]
|
||||||
len*: int8 # >= 1 when holding valid unsigned integer
|
len*: int8 # >= 1 when holding valid unsigned integer
|
||||||
|
|
||||||
proc decode*[A: byte|char, T: SomeUnsignedInt](
|
func decode*[A: byte|char, T: SomeUnsignedInt](
|
||||||
B: typedesc[Base10], t: typedesc[T],
|
B: typedesc[Base10], t: typedesc[T],
|
||||||
src: openArray[A]): Result[T, cstring] =
|
src: openArray[A]): Result[T, cstring] =
|
||||||
## Convert base10 encoded string or array of bytes to unsigned integer.
|
## Convert base10 encoded string or array of bytes to unsigned integer.
|
||||||
|
@ -62,7 +62,7 @@ proc decode*[A: byte|char, T: SomeUnsignedInt](
|
||||||
v = (v shl 3) + (v shl 1) + T(d)
|
v = (v shl 3) + (v shl 1) + T(d)
|
||||||
ok(v)
|
ok(v)
|
||||||
|
|
||||||
proc encodedLength*(B: typedesc[Base10], value: SomeUnsignedInt): int8 =
|
func encodedLength*(B: typedesc[Base10], value: SomeUnsignedInt): int8 =
|
||||||
## Procedure returns number of characters needed to encode integer ``value``.
|
## Procedure returns number of characters needed to encode integer ``value``.
|
||||||
when type(value) is uint8:
|
when type(value) is uint8:
|
||||||
if value < 10'u8:
|
if value < 10'u8:
|
||||||
|
@ -132,7 +132,7 @@ proc encodedLength*(B: typedesc[Base10], value: SomeUnsignedInt): int8 =
|
||||||
return 11'i8 + (if value >= P11: 1'i8 else: 0)
|
return 11'i8 + (if value >= P11: 1'i8 else: 0)
|
||||||
return 12'i8 + B.encodedLength(value div P12)
|
return 12'i8 + B.encodedLength(value div P12)
|
||||||
|
|
||||||
proc encode[A: byte|char](B: typedesc[Base10], value: SomeUnsignedInt,
|
func encode[A: byte|char](B: typedesc[Base10], value: SomeUnsignedInt,
|
||||||
output: var openArray[A],
|
output: var openArray[A],
|
||||||
length: int8): Result[int8, cstring] =
|
length: int8): Result[int8, cstring] =
|
||||||
const Digits = cstring(
|
const Digits = cstring(
|
||||||
|
@ -175,25 +175,25 @@ proc encode[A: byte|char](B: typedesc[Base10], value: SomeUnsignedInt,
|
||||||
output[next - 1] = byte(Digits[index])
|
output[next - 1] = byte(Digits[index])
|
||||||
ok(length)
|
ok(length)
|
||||||
|
|
||||||
proc encode*[A: byte|char](B: typedesc[Base10], value: SomeUnsignedInt,
|
func encode*[A: byte|char](B: typedesc[Base10], value: SomeUnsignedInt,
|
||||||
output: var openArray[A]): Result[int8, cstring] =
|
output: var openArray[A]): Result[int8, cstring] =
|
||||||
## Encode integer value to array of characters or bytes.
|
## Encode integer value to array of characters or bytes.
|
||||||
B.encode(value, output, B.encodedLength(value))
|
B.encode(value, output, B.encodedLength(value))
|
||||||
|
|
||||||
proc toString*(B: typedesc[Base10], value: SomeUnsignedInt): string =
|
func toString*(B: typedesc[Base10], value: SomeUnsignedInt): string =
|
||||||
## Encode integer value ``value`` to string.
|
## Encode integer value ``value`` to string.
|
||||||
var buf = newString(B.encodedLength(value))
|
var buf = newString(B.encodedLength(value))
|
||||||
# Buffer of proper size is allocated, so error is not possible
|
# Buffer of proper size is allocated, so error is not possible
|
||||||
discard B.encode(value, buf, int8(len(buf)))
|
discard B.encode(value, buf, int8(len(buf)))
|
||||||
buf
|
buf
|
||||||
|
|
||||||
proc toBytes*[I: SomeUnsignedInt](B: typedesc[Base10], v: I): Base10Buf[I] {.
|
func toBytes*[I: SomeUnsignedInt](B: typedesc[Base10], v: I): Base10Buf[I] {.
|
||||||
noinit.} =
|
noinit.} =
|
||||||
## Encode integer value ``value`` to array of bytes.
|
## Encode integer value ``value`` to array of bytes.
|
||||||
let res = B.encode(v, result.data, B.encodedLength(v))
|
let res = B.encode(v, result.data, B.encodedLength(v))
|
||||||
result.len = int8(res.get())
|
result.len = int8(res.get())
|
||||||
|
|
||||||
proc toBytes*[I: SomeUnsignedInt](v: I, B: typedesc[Base10]): Base10Buf[I] {.
|
func toBytes*[I: SomeUnsignedInt](v: I, B: typedesc[Base10]): Base10Buf[I] {.
|
||||||
noinit.} =
|
noinit.} =
|
||||||
## Encode integer value ``value`` to array of bytes.
|
## Encode integer value ``value`` to array of bytes.
|
||||||
let res = B.encode(v, result.data, B.encodedLength(v))
|
let res = B.encode(v, result.data, B.encodedLength(v))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Nimbus - Types, data structures and shared utilities used in network sync
|
# Nimbus - Types, data structures and shared utilities used in network sync
|
||||||
#
|
#
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -108,11 +108,12 @@
|
||||||
## isomorpic to a subclass of `S`.
|
## isomorpic to a subclass of `S`.
|
||||||
##
|
##
|
||||||
|
|
||||||
import
|
|
||||||
"."/[results, sorted_set]
|
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
pkg/results,
|
||||||
|
"."/sorted_set
|
||||||
|
|
||||||
export
|
export
|
||||||
`isRed=`,
|
`isRed=`,
|
||||||
`linkLeft=`,
|
`linkLeft=`,
|
||||||
|
@ -282,25 +283,25 @@ template scalarOne(): untyped =
|
||||||
## the value `1` from the scalar data type
|
## the value `1` from the scalar data type
|
||||||
(S.default + 1)
|
(S.default + 1)
|
||||||
|
|
||||||
proc blk[P,S](kvp: DataRef[P,S]): BlockRef[S] =
|
func blk[P,S](kvp: DataRef[P,S]): BlockRef[S] =
|
||||||
kvp.data
|
kvp.data
|
||||||
|
|
||||||
proc left[P,S](kvp: DataRef[P,S]): P =
|
func left[P,S](kvp: DataRef[P,S]): P =
|
||||||
kvp.key
|
kvp.key
|
||||||
|
|
||||||
proc right[P,S](kvp: DataRef[P,S]): P =
|
func right[P,S](kvp: DataRef[P,S]): P =
|
||||||
kvp.key + kvp.blk.size
|
kvp.key + kvp.blk.size
|
||||||
|
|
||||||
proc len[P,S](kvp: DataRef[P,S]): S =
|
func len[P,S](kvp: DataRef[P,S]): S =
|
||||||
kvp.data.size
|
kvp.data.size
|
||||||
|
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
proc new[P,S](T: type Segm[P,S]; left, right: P): T =
|
func new[P,S](T: type Segm[P,S]; left, right: P): T =
|
||||||
## Constructor using `[left,right)` points representation
|
## Constructor using `[left,right)` points representation
|
||||||
T(start: left, size: right - left)
|
T(start: left, size: right - left)
|
||||||
|
|
||||||
proc brew[P,S](T: type Segm[P,S]; left, right: P): Result[T,void] =
|
func brew[P,S](T: type Segm[P,S]; left, right: P): Result[T,void] =
|
||||||
## Constructor providing `[left, max(left,right)-left)` (if any.)
|
## Constructor providing `[left, max(left,right)-left)` (if any.)
|
||||||
if high(P) <= left:
|
if high(P) <= left:
|
||||||
return err()
|
return err()
|
||||||
|
@ -313,39 +314,39 @@ proc brew[P,S](T: type Segm[P,S]; left, right: P): Result[T,void] =
|
||||||
(high(P) - left)
|
(high(P) - left)
|
||||||
ok(T(start: left, size: length))
|
ok(T(start: left, size: length))
|
||||||
|
|
||||||
proc left[P,S](iv: Segm[P,S]): P =
|
func left[P,S](iv: Segm[P,S]): P =
|
||||||
iv.start
|
iv.start
|
||||||
|
|
||||||
proc right[P,S](iv: Segm[P,S]): P =
|
func right[P,S](iv: Segm[P,S]): P =
|
||||||
iv.start + iv.size
|
iv.start + iv.size
|
||||||
|
|
||||||
proc len[P,S](iv: Segm[P,S]): S =
|
func len[P,S](iv: Segm[P,S]): S =
|
||||||
iv.size
|
iv.size
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
proc incPt[P,S](a: var P; n: S) =
|
func incPt[P,S](a: var P; n: S) =
|
||||||
## Might not be generally available for point `P` and scalar `S`
|
## Might not be generally available for point `P` and scalar `S`
|
||||||
a = a + n
|
a = a + n
|
||||||
|
|
||||||
proc maxPt[P](a, b: P): P =
|
func maxPt[P](a, b: P): P =
|
||||||
## Instead of max() which might not be generally available
|
## Instead of max() which might not be generally available
|
||||||
if a < b: b else: a
|
if a < b: b else: a
|
||||||
|
|
||||||
proc minPt[P](a, b: P): P =
|
func minPt[P](a, b: P): P =
|
||||||
## Instead of min() which might not be generally available
|
## Instead of min() which might not be generally available
|
||||||
if a < b: a else: b
|
if a < b: a else: b
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
proc new[P,S](T: type Interval[P,S]; kvp: DataRef[P,S]): T =
|
func new[P,S](T: type Interval[P,S]; kvp: DataRef[P,S]): T =
|
||||||
T(least: kvp.left, last: kvp.right - scalarOne)
|
T(least: kvp.left, last: kvp.right - scalarOne)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private helpers
|
# Private helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc overlapOrLeftJoin[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
func overlapOrLeftJoin[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
||||||
## Find and return
|
## Find and return
|
||||||
## * either the rightmost interval `[a,b)` which overlaps `r`
|
## * either the rightmost interval `[a,b)` which overlaps `r`
|
||||||
## * or `[a,b)` with `b==l`
|
## * or `[a,b)` with `b==l`
|
||||||
|
@ -358,11 +359,11 @@ proc overlapOrLeftJoin[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
||||||
return ok(rc.value)
|
return ok(rc.value)
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc overlapOrLeftJoin[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] =
|
func overlapOrLeftJoin[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] =
|
||||||
ds.overlapOrLeftJoin(iv.left, iv.right)
|
ds.overlapOrLeftJoin(iv.left, iv.right)
|
||||||
|
|
||||||
|
|
||||||
proc overlap[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
func overlap[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
||||||
## Find and return the rightmost `[l,r)` overlapping interval `[a,b)`.
|
## Find and return the rightmost `[l,r)` overlapping interval `[a,b)`.
|
||||||
doAssert l < r
|
doAssert l < r
|
||||||
let rc = ds.leftPos.lt(r) # search for `max(a) < r`
|
let rc = ds.leftPos.lt(r) # search for `max(a) < r`
|
||||||
|
@ -373,14 +374,14 @@ proc overlap[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] =
|
||||||
return ok(rc.value)
|
return ok(rc.value)
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc overlap[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] =
|
func overlap[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] =
|
||||||
ds.overlap(iv.left, iv.right)
|
ds.overlap(iv.left, iv.right)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private transfer function helpers
|
# Private transfer function helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc findInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
func findInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
||||||
## Find largest sub-segment of `iv` fully contained in another segment
|
## Find largest sub-segment of `iv` fully contained in another segment
|
||||||
## of the argument database.
|
## of the argument database.
|
||||||
##
|
##
|
||||||
|
@ -400,7 +401,7 @@ proc findInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
||||||
Segm[P,S].new(maxPt(p.left,iv.left), minPt(p.right,iv.right))
|
Segm[P,S].new(maxPt(p.left,iv.left), minPt(p.right,iv.right))
|
||||||
|
|
||||||
|
|
||||||
proc merge[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
func merge[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
||||||
## Merges argument interval into into database and returns
|
## Merges argument interval into into database and returns
|
||||||
## the segment really added (if any)
|
## the segment really added (if any)
|
||||||
|
|
||||||
|
@ -513,7 +514,7 @@ proc merge[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] =
|
||||||
# s: [--------------)
|
# s: [--------------)
|
||||||
|
|
||||||
|
|
||||||
proc deleteInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]) =
|
func deleteInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]) =
|
||||||
## Delete fully contained interval
|
## Delete fully contained interval
|
||||||
if not ds.isNil and 0 < iv.len:
|
if not ds.isNil and 0 < iv.len:
|
||||||
|
|
||||||
|
@ -560,7 +561,7 @@ proc deleteInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]) =
|
||||||
# Private transfer() function implementation for merge/reduce
|
# Private transfer() function implementation for merge/reduce
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc transferImpl[P,S](src, trg: Desc[P,S]; iv: Segm[P,S]): S =
|
func transferImpl[P,S](src, trg: Desc[P,S]; iv: Segm[P,S]): S =
|
||||||
## From the `src` argument database, delete the data segment/interval
|
## From the `src` argument database, delete the data segment/interval
|
||||||
## `[start,start+length)` and merge it into the `trg` argument database.
|
## `[start,start+length)` and merge it into the `trg` argument database.
|
||||||
## Not both arguments `src` and `trg` must be `nil`.
|
## Not both arguments `src` and `trg` must be `nil`.
|
||||||
|
@ -592,7 +593,7 @@ proc transferImpl[P,S](src, trg: Desc[P,S]; iv: Segm[P,S]): S =
|
||||||
# Private covered() function implementation
|
# Private covered() function implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc coveredImpl[P,S](ds: IntervalSetRef[P,S]; start: P; length: S): S =
|
func coveredImpl[P,S](ds: IntervalSetRef[P,S]; start: P; length: S): S =
|
||||||
## Calulate the accumulated size of the interval `[start,start+length)`
|
## Calulate the accumulated size of the interval `[start,start+length)`
|
||||||
## covered by intervals in the set `ds`. The result cannot exceed the
|
## covered by intervals in the set `ds`. The result cannot exceed the
|
||||||
## argument `length` (of course.)
|
## argument `length` (of course.)
|
||||||
|
@ -644,12 +645,12 @@ proc coveredImpl[P,S](ds: IntervalSetRef[P,S]; start: P; length: S): S =
|
||||||
# Public constructor, clone, etc.
|
# Public constructor, clone, etc.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc init*[P,S](T: type IntervalSetRef[P,S]): T =
|
func init*[P,S](T: type IntervalSetRef[P,S]): T =
|
||||||
## Interval set constructor.
|
## Interval set constructor.
|
||||||
new result
|
new result
|
||||||
result.leftPos.init()
|
result.leftPos.init()
|
||||||
|
|
||||||
proc clone*[P,S](ds: IntervalSetRef[P,S]): IntervalSetRef[P,S] =
|
func clone*[P,S](ds: IntervalSetRef[P,S]): IntervalSetRef[P,S] =
|
||||||
## Return a copy of the interval list. Beware, this might be slow as it
|
## Return a copy of the interval list. Beware, this might be slow as it
|
||||||
## needs to copy every interval record.
|
## needs to copy every interval record.
|
||||||
result = Desc[P,S].init()
|
result = Desc[P,S].init()
|
||||||
|
@ -666,7 +667,7 @@ proc clone*[P,S](ds: IntervalSetRef[P,S]): IntervalSetRef[P,S] =
|
||||||
# optional clean up, see comments on the destroy() directive
|
# optional clean up, see comments on the destroy() directive
|
||||||
walk.destroy
|
walk.destroy
|
||||||
|
|
||||||
proc `==`*[P,S](a, b: IntervalSetRef[P,S]): bool =
|
func `==`*[P,S](a, b: IntervalSetRef[P,S]): bool =
|
||||||
## Compare interval sets for equality. Beware, this can be slow. Every
|
## Compare interval sets for equality. Beware, this can be slow. Every
|
||||||
## interval record has to be checked.
|
## interval record has to be checked.
|
||||||
if a.ptsCount == b.ptsCount and
|
if a.ptsCount == b.ptsCount and
|
||||||
|
@ -686,13 +687,13 @@ proc `==`*[P,S](a, b: IntervalSetRef[P,S]): bool =
|
||||||
# optional clean up, see comments on the destroy() directive
|
# optional clean up, see comments on the destroy() directive
|
||||||
aWalk.destroy()
|
aWalk.destroy()
|
||||||
|
|
||||||
proc clear*[P,S](ds: IntervalSetRef[P,S]) =
|
func clear*[P,S](ds: IntervalSetRef[P,S]) =
|
||||||
## Clear the interval set.
|
## Clear the interval set.
|
||||||
ds.ptsCount = scalarZero
|
ds.ptsCount = scalarZero
|
||||||
ds.lastHigh = false
|
ds.lastHigh = false
|
||||||
ds.leftPos.clear()
|
ds.leftPos.clear()
|
||||||
|
|
||||||
proc new*[P,S](T: type Interval[P,S]; minPt, maxPt: P): T =
|
func new*[P,S](T: type Interval[P,S]; minPt, maxPt: P): T =
|
||||||
## Create interval `[minPt,max(minPt,maxPt)]`
|
## Create interval `[minPt,max(minPt,maxPt)]`
|
||||||
Interval[P,S](least: minPt, last: max(minPt, maxPt))
|
Interval[P,S](least: minPt, last: max(minPt, maxPt))
|
||||||
|
|
||||||
|
@ -700,7 +701,7 @@ proc new*[P,S](T: type Interval[P,S]; minPt, maxPt: P): T =
|
||||||
# Public interval operations add, remove, erc.
|
# Public interval operations add, remove, erc.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc merge*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
func merge*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
||||||
## merge `I` with the intervals of the argument set `ds`. The function
|
## merge `I` with the intervals of the argument set `ds`. The function
|
||||||
## returns the accumulated number of points that were added to some
|
## returns the accumulated number of points that were added to some
|
||||||
|
@ -720,12 +721,12 @@ proc merge*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
else:
|
else:
|
||||||
result = scalarZero
|
result = scalarZero
|
||||||
|
|
||||||
proc merge*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
func merge*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
||||||
## Variant of `merge()`
|
## Variant of `merge()`
|
||||||
ds.merge(iv.least, iv.last)
|
ds.merge(iv.least, iv.last)
|
||||||
|
|
||||||
|
|
||||||
proc reduce*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
func reduce*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
||||||
## remove the points from `I` from intervals of the argument set `ds`.
|
## remove the points from `I` from intervals of the argument set `ds`.
|
||||||
## The function returns the accumulated number of elements removed (i.e.
|
## The function returns the accumulated number of elements removed (i.e.
|
||||||
|
@ -745,12 +746,12 @@ proc reduce*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
else:
|
else:
|
||||||
result = scalarZero
|
result = scalarZero
|
||||||
|
|
||||||
proc reduce*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
func reduce*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
||||||
## Variant of `reduce()`
|
## Variant of `reduce()`
|
||||||
ds.reduce(iv.least, iv.last)
|
ds.reduce(iv.least, iv.last)
|
||||||
|
|
||||||
|
|
||||||
proc covered*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
func covered*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`,
|
||||||
## calulate the accumulated points `I` contained in some interval in the
|
## calulate the accumulated points `I` contained in some interval in the
|
||||||
## set `ds`. The return value is the same as that for `reduce()` (only
|
## set `ds`. The return value is the same as that for `reduce()` (only
|
||||||
|
@ -765,12 +766,12 @@ proc covered*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S =
|
||||||
else:
|
else:
|
||||||
result = scalarZero
|
result = scalarZero
|
||||||
|
|
||||||
proc covered*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
func covered*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S =
|
||||||
## Variant of `covered()`
|
## Variant of `covered()`
|
||||||
ds.covered(iv.least, iv.last)
|
ds.covered(iv.least, iv.last)
|
||||||
|
|
||||||
|
|
||||||
proc ge*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] =
|
func ge*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] =
|
||||||
## Find smallest interval in the set `ds` with start point (i.e. minimal
|
## Find smallest interval in the set `ds` with start point (i.e. minimal
|
||||||
## value in the interval as a set) greater or equal the argument `minPt`.
|
## value in the interval as a set) greater or equal the argument `minPt`.
|
||||||
let rc = ds.leftPos.ge(minPt)
|
let rc = ds.leftPos.ge(minPt)
|
||||||
|
@ -785,11 +786,11 @@ proc ge*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] =
|
||||||
return ok(Interval[P,S].new(high(P),high(P)))
|
return ok(Interval[P,S].new(high(P),high(P)))
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc ge*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] =
|
func ge*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] =
|
||||||
## Find the interval with the least elements of type `P` (if any.)
|
## Find the interval with the least elements of type `P` (if any.)
|
||||||
ds.ge(low(P))
|
ds.ge(low(P))
|
||||||
|
|
||||||
proc le*[P,S](ds: IntervalSetRef[P,S]; maxPt: P): IntervalRc[P,S] =
|
func le*[P,S](ds: IntervalSetRef[P,S]; maxPt: P): IntervalRc[P,S] =
|
||||||
## Find largest interval in the set `ds` with end point (i.e. maximal
|
## Find largest interval in the set `ds` with end point (i.e. maximal
|
||||||
## value in the interval as a set) smaller or equal to the argument `maxPt`.
|
## value in the interval as a set) smaller or equal to the argument `maxPt`.
|
||||||
let rc = ds.leftPos.le(maxPt)
|
let rc = ds.leftPos.le(maxPt)
|
||||||
|
@ -818,12 +819,12 @@ proc le*[P,S](ds: IntervalSetRef[P,S]; maxPt: P): IntervalRc[P,S] =
|
||||||
return ok(Interval[P,S].new(high(P),high(P)))
|
return ok(Interval[P,S].new(high(P),high(P)))
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc le*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] =
|
func le*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] =
|
||||||
## Find the interval with the largest elements of type `P` (if any.)
|
## Find the interval with the largest elements of type `P` (if any.)
|
||||||
ds.le(high(P))
|
ds.le(high(P))
|
||||||
|
|
||||||
|
|
||||||
proc envelope*[P,S](ds: IntervalSetRef[P,S]; pt: P): IntervalRc[P,S] =
|
func envelope*[P,S](ds: IntervalSetRef[P,S]; pt: P): IntervalRc[P,S] =
|
||||||
## Find the interval that contains the argument point `pt` (if any)
|
## Find the interval that contains the argument point `pt` (if any)
|
||||||
let rc = ds.leftPos.le(pt)
|
let rc = ds.leftPos.le(pt)
|
||||||
if rc.isOk:
|
if rc.isOk:
|
||||||
|
@ -838,7 +839,7 @@ proc envelope*[P,S](ds: IntervalSetRef[P,S]; pt: P): IntervalRc[P,S] =
|
||||||
err()
|
err()
|
||||||
|
|
||||||
|
|
||||||
proc delete*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] =
|
func delete*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] =
|
||||||
## Find the interval `[minPt,maxPt]` for some point `maxPt` in the interval
|
## Find the interval `[minPt,maxPt]` for some point `maxPt` in the interval
|
||||||
## set `ds` and remove it from `ds`. The function returns the deleted
|
## set `ds` and remove it from `ds`. The function returns the deleted
|
||||||
## interval (if any.)
|
## interval (if any.)
|
||||||
|
@ -915,21 +916,21 @@ iterator decreasing*[P,S](
|
||||||
# Public interval operators
|
# Public interval operators
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `==`*[P,S](iv, jv: Interval[P,S]): bool =
|
func `==`*[P,S](iv, jv: Interval[P,S]): bool =
|
||||||
## Compare intervals for equality
|
## Compare intervals for equality
|
||||||
iv.least == jv.least and iv.last == jv.last
|
iv.least == jv.least and iv.last == jv.last
|
||||||
|
|
||||||
proc `==`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): bool =
|
func `==`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): bool =
|
||||||
## Variant of `==`
|
## Variant of `==`
|
||||||
if iv.isOk:
|
if iv.isOk:
|
||||||
return iv.value == jv
|
return iv.value == jv
|
||||||
|
|
||||||
proc `==`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): bool =
|
func `==`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): bool =
|
||||||
## Variant of `==`
|
## Variant of `==`
|
||||||
if jv.isOk:
|
if jv.isOk:
|
||||||
return iv == jv.value
|
return iv == jv.value
|
||||||
|
|
||||||
proc `==`*[P,S](iv, jv: IntervalRc[P,S]): bool =
|
func `==`*[P,S](iv, jv: IntervalRc[P,S]): bool =
|
||||||
## Variant of `==`
|
## Variant of `==`
|
||||||
if iv.isOk:
|
if iv.isOk:
|
||||||
if jv.isOk:
|
if jv.isOk:
|
||||||
|
@ -941,7 +942,7 @@ proc `==`*[P,S](iv, jv: IntervalRc[P,S]): bool =
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
proc `*`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
func `*`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Intersect itervals `iv` and `jv` if this operation results in a
|
## Intersect itervals `iv` and `jv` if this operation results in a
|
||||||
## non-emty interval. Note that the `*` operation is associative, i.e.
|
## non-emty interval. Note that the `*` operation is associative, i.e.
|
||||||
## ::
|
## ::
|
||||||
|
@ -953,19 +954,19 @@ proc `*`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
maxPt(jv.least,iv.least), minPt(jv.last,iv.last)))
|
maxPt(jv.least,iv.least), minPt(jv.last,iv.last)))
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `*`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
func `*`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `*`
|
## Variant of `*`
|
||||||
if iv.isOk:
|
if iv.isOk:
|
||||||
return iv.value * jv
|
return iv.value * jv
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `*`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `*`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `*`
|
## Variant of `*`
|
||||||
if jv.isOk:
|
if jv.isOk:
|
||||||
return iv * jv.value
|
return iv * jv.value
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `*`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `*`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `*`
|
## Variant of `*`
|
||||||
if iv.isOk and jv.isOk:
|
if iv.isOk and jv.isOk:
|
||||||
return iv.value * jv.value
|
return iv.value * jv.value
|
||||||
|
@ -973,7 +974,7 @@ proc `*`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
proc `+`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
func `+`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Merge intervals `iv` and `jv` if this operation results in an interval.
|
## Merge intervals `iv` and `jv` if this operation results in an interval.
|
||||||
## Note that the `+` operation is *not* associative, i.e.
|
## Note that the `+` operation is *not* associative, i.e.
|
||||||
## ::
|
## ::
|
||||||
|
@ -997,19 +998,19 @@ proc `+`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
|
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `+`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
func `+`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `+`
|
## Variant of `+`
|
||||||
if iv.isOk:
|
if iv.isOk:
|
||||||
return iv.value + jv
|
return iv.value + jv
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `+`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `+`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `+`
|
## Variant of `+`
|
||||||
if jv.isOk:
|
if jv.isOk:
|
||||||
return iv + jv.value
|
return iv + jv.value
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `+`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `+`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `+`
|
## Variant of `+`
|
||||||
if iv.isOk and jv.isOk:
|
if iv.isOk and jv.isOk:
|
||||||
return iv.value + jv.value
|
return iv.value + jv.value
|
||||||
|
@ -1017,7 +1018,7 @@ proc `+`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
|
|
||||||
# ------
|
# ------
|
||||||
|
|
||||||
proc `-`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
func `-`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Return the interval `iv` reduced by elements of `jv` if this operation
|
## Return the interval `iv` reduced by elements of `jv` if this operation
|
||||||
## results in a non-empty interval.
|
## results in a non-empty interval.
|
||||||
## Note that the `-` operation is *not* associative, i.e.
|
## Note that the `-` operation is *not* associative, i.e.
|
||||||
|
@ -1074,19 +1075,19 @@ proc `-`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
|
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `-`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
func `-`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `-`
|
## Variant of `-`
|
||||||
if iv.isOk:
|
if iv.isOk:
|
||||||
return iv.value - jv
|
return iv.value - jv
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `-`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `-`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `-`
|
## Variant of `-`
|
||||||
if jv.isOk:
|
if jv.isOk:
|
||||||
return iv - jv.value
|
return iv - jv.value
|
||||||
err()
|
err()
|
||||||
|
|
||||||
proc `-`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
func `-`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
## Variant of `-`
|
## Variant of `-`
|
||||||
if iv.isOk and jv.isOk:
|
if iv.isOk and jv.isOk:
|
||||||
return iv.value - jv.valu
|
return iv.value - jv.valu
|
||||||
|
@ -1096,7 +1097,7 @@ proc `-`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] =
|
||||||
# Public getters
|
# Public getters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc len*[P,S](iv: Interval[P,S]): S =
|
func len*[P,S](iv: Interval[P,S]): S =
|
||||||
## Cardinality (ie. length) of argument interval `iv`. If the argument
|
## Cardinality (ie. length) of argument interval `iv`. If the argument
|
||||||
## interval `iv` is `[low(P),high(P)]`, the return value will be the scalar
|
## interval `iv` is `[low(P),high(P)]`, the return value will be the scalar
|
||||||
## *zero* (there are no empty intervals in this implementation.)
|
## *zero* (there are no empty intervals in this implementation.)
|
||||||
|
@ -1105,15 +1106,15 @@ proc len*[P,S](iv: Interval[P,S]): S =
|
||||||
else:
|
else:
|
||||||
(iv.last - iv.least) + scalarOne
|
(iv.last - iv.least) + scalarOne
|
||||||
|
|
||||||
proc minPt*[P,S](iv: Interval[P,S]): P =
|
func minPt*[P,S](iv: Interval[P,S]): P =
|
||||||
## Left end, smallest point of `P` contained in the interval
|
## Left end, smallest point of `P` contained in the interval
|
||||||
iv.least
|
iv.least
|
||||||
|
|
||||||
proc maxPt*[P,S](iv: Interval[P,S]): P =
|
func maxPt*[P,S](iv: Interval[P,S]): P =
|
||||||
## Right end, largest point of `P` contained in the interval
|
## Right end, largest point of `P` contained in the interval
|
||||||
iv.last
|
iv.last
|
||||||
|
|
||||||
proc total*[P,S](ds: IntervalSetRef[P,S]): S =
|
func total*[P,S](ds: IntervalSetRef[P,S]): S =
|
||||||
## Accumulated size covered by intervals in the interval set `ds`.
|
## Accumulated size covered by intervals in the interval set `ds`.
|
||||||
##
|
##
|
||||||
## In the special case when there is only the single interval
|
## In the special case when there is only the single interval
|
||||||
|
@ -1126,7 +1127,7 @@ proc total*[P,S](ds: IntervalSetRef[P,S]): S =
|
||||||
else:
|
else:
|
||||||
ds.ptsCount + scalarOne
|
ds.ptsCount + scalarOne
|
||||||
|
|
||||||
proc chunks*[P,S](ds: IntervalSetRef[P,S]): int =
|
func chunks*[P,S](ds: IntervalSetRef[P,S]): int =
|
||||||
## Number of disjunkt intervals (aka chunks) in the interval set `ds`.
|
## Number of disjunkt intervals (aka chunks) in the interval set `ds`.
|
||||||
result = ds.leftPos.len
|
result = ds.leftPos.len
|
||||||
if ds.lastHigh:
|
if ds.lastHigh:
|
||||||
|
@ -1138,7 +1139,7 @@ proc chunks*[P,S](ds: IntervalSetRef[P,S]): int =
|
||||||
# Public debugging functions
|
# Public debugging functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `$`*[P,S](p: DataRef[P,S]): string =
|
func `$`*[P,S](p: DataRef[P,S]): string =
|
||||||
## Needed by `ds.verify()` for printing error messages
|
## Needed by `ds.verify()` for printing error messages
|
||||||
"[" & $p.left & "," & $p.right & ")"
|
"[" & $p.left & "," & $p.right & ")"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
{.deprecated: "use https://nim-lang.org/docs/syncio.html#writeFile%2Cstring%2CopenArray%5Bbyte%5D directly".}
|
||||||
|
|
||||||
when not compiles(writeFile("filename", @[byte(1)])):
|
when not compiles(writeFile("filename", @[byte(1)])):
|
||||||
proc writeFile*(filename: string, content: openArray[byte]) =
|
proc writeFile*(filename: string, content: openArray[byte]) =
|
||||||
## Opens a file named `filename` for writing. Then writes the
|
## Opens a file named `filename` for writing. Then writes the
|
||||||
|
@ -11,4 +13,3 @@ when not compiles(writeFile("filename", @[byte(1)])):
|
||||||
close(f)
|
close(f)
|
||||||
else:
|
else:
|
||||||
raise newException(IOError, "cannot open: " & filename)
|
raise newException(IOError, "cannot open: " & filename)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## Copyright (c) 2020-2023 Status Research & Development GmbH
|
## Copyright (c) 2020-2024 Status Research & Development GmbH
|
||||||
## Licensed under either of
|
## Licensed under either of
|
||||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import algorithm
|
import std/algorithm
|
||||||
import results
|
import pkg/results
|
||||||
export results
|
export results
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -22,12 +22,12 @@
|
||||||
## semantics, this means that `=` performs a deep copy of the allocated queue
|
## semantics, this means that `=` performs a deep copy of the allocated queue
|
||||||
## which is refered to the deep copy semantics of the underlying table driver.
|
## which is refered to the deep copy semantics of the underlying table driver.
|
||||||
|
|
||||||
import std/tables, results
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import std/tables, pkg/results
|
||||||
|
|
||||||
export results
|
export results
|
||||||
|
|
||||||
{.push raises: [].}
|
|
||||||
|
|
||||||
type
|
type
|
||||||
KeyedQueueItem*[K, V] = object
|
KeyedQueueItem*[K, V] = object
|
||||||
## Data value container as stored in the queue.
|
## Data value container as stored in the queue.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -12,10 +12,12 @@
|
||||||
## =============================
|
## =============================
|
||||||
##
|
##
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/tables,
|
std/tables,
|
||||||
../keyed_queue,
|
results,
|
||||||
../results
|
../keyed_queue
|
||||||
|
|
||||||
type
|
type
|
||||||
KeyedQueueInfo* = enum ##\
|
KeyedQueueInfo* = enum ##\
|
||||||
|
@ -31,13 +33,11 @@ type
|
||||||
kQVfyPrvNxtExpected
|
kQVfyPrvNxtExpected
|
||||||
kQVfyFirstExpected
|
kQVfyFirstExpected
|
||||||
|
|
||||||
{.push raises: [].}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions, debugging
|
# Public functions, debugging
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `$`*[K,V](item: KeyedQueueItem[K,V]): string =
|
func `$`*[K,V](item: KeyedQueueItem[K,V]): string =
|
||||||
## Pretty print data container item.
|
## Pretty print data container item.
|
||||||
##
|
##
|
||||||
## :CAVEAT:
|
## :CAVEAT:
|
||||||
|
@ -51,8 +51,8 @@ proc `$`*[K,V](item: KeyedQueueItem[K,V]): string =
|
||||||
else:
|
else:
|
||||||
"(" & $item.value & ", link[" & $item.prv & "," & $item.kNxt & "])"
|
"(" & $item.value & ", link[" & $item.prv & "," & $item.kNxt & "])"
|
||||||
|
|
||||||
proc verify*[K,V](rq: var KeyedQueue[K,V]): Result[void,(K,V,KeyedQueueInfo)]
|
func verify*[K,V](rq: var KeyedQueue[K,V]): Result[void,(K,V,KeyedQueueInfo)]
|
||||||
{.gcsafe,raises: [KeyError].} =
|
{.raises: [KeyError].} =
|
||||||
## Check for consistency. Returns an error unless the argument
|
## Check for consistency. Returns an error unless the argument
|
||||||
## queue `rq` is consistent.
|
## queue `rq` is consistent.
|
||||||
let tabLen = rq.tab.len
|
let tabLen = rq.tab.len
|
||||||
|
@ -97,7 +97,7 @@ proc verify*[K,V](rq: var KeyedQueue[K,V]): Result[void,(K,V,KeyedQueueInfo)]
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc dumpLinkedKeys*[K,V](rq: var KeyedQueue[K,V]): string =
|
func dumpLinkedKeys*[K,V](rq: var KeyedQueue[K,V]): string =
|
||||||
## Dump the linked key list. This function depends on the `$` operator
|
## Dump the linked key list. This function depends on the `$` operator
|
||||||
## for converting a `K` type into a string
|
## for converting a `K` type into a string
|
||||||
if 0 < rq.tab.len:
|
if 0 < rq.tab.len:
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{.deprecated: "use std/os".}
|
|
||||||
import std/os
|
|
||||||
export os
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -47,9 +47,12 @@
|
||||||
## rc = w.next
|
## rc = w.next
|
||||||
## # optional clean up, see comments on the destroy() directive
|
## # optional clean up, see comments on the destroy() directive
|
||||||
## walk.destroy
|
## walk.destroy
|
||||||
##
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[tables],
|
std/[tables],
|
||||||
|
pkg/results,
|
||||||
./sorted_set/[rbtree_delete,
|
./sorted_set/[rbtree_delete,
|
||||||
rbtree_desc,
|
rbtree_desc,
|
||||||
rbtree_find,
|
rbtree_find,
|
||||||
|
@ -57,8 +60,7 @@ import
|
||||||
rbtree_insert,
|
rbtree_insert,
|
||||||
rbtree_reset,
|
rbtree_reset,
|
||||||
rbtree_verify,
|
rbtree_verify,
|
||||||
rbtree_walk],
|
rbtree_walk]
|
||||||
./results
|
|
||||||
|
|
||||||
export
|
export
|
||||||
RbInfo,
|
RbInfo,
|
||||||
|
@ -93,18 +95,18 @@ type
|
||||||
# Private helpers
|
# Private helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc slstCmp[K,V](casket: SortedSetItemRef[K,V]; key: K): int =
|
func slstCmp[K,V](casket: SortedSetItemRef[K,V]; key: K): int =
|
||||||
casket.key.cmp(key)
|
casket.key.cmp(key)
|
||||||
|
|
||||||
proc slstMkc[K,V](key: K): SortedSetItemRef[K,V] =
|
func slstMkc[K,V](key: K): SortedSetItemRef[K,V] =
|
||||||
SortedSetItemRef[K,V](key: key)
|
SortedSetItemRef[K,V](key: key)
|
||||||
|
|
||||||
proc slstClup[K,V](c: var SortedSetItemRef[K,V]) =
|
func slstClup[K,V](c: var SortedSetItemRef[K,V]) =
|
||||||
# ... some smart stuff here?
|
# ... some smart stuff here?
|
||||||
c = nil # GC hint (if any, todo?)
|
c = nil # GC hint (if any, todo?)
|
||||||
|
|
||||||
|
|
||||||
proc slstLt[K,V](a, b: SortedSetItemRef[K,V]): bool =
|
func slstLt[K,V](a, b: SortedSetItemRef[K,V]): bool =
|
||||||
## Debugging only
|
## Debugging only
|
||||||
a.slstCmp(b.key) < 0
|
a.slstCmp(b.key) < 0
|
||||||
|
|
||||||
|
@ -116,22 +118,22 @@ proc slstPr(code: RbInfo; ctxInfo: string) =
|
||||||
# Public functions, constructor
|
# Public functions, constructor
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc init*[K,V](sl: var SortedSet[K,V]) =
|
func init*[K,V](sl: var SortedSet[K,V]) =
|
||||||
## Constructor for sorted list with key type `K` and data type `V`
|
## Constructor for sorted list with key type `K` and data type `V`
|
||||||
sl.tree = newRbTreeRef[SortedSetItemRef[K,V],K](
|
sl.tree = newRbTreeRef[SortedSetItemRef[K,V],K](
|
||||||
cmp = proc(c: SortedSetItemRef[K,V]; k: K): int = c.slstCmp(k),
|
cmp = proc(c: SortedSetItemRef[K,V]; k: K): int = c.slstCmp(k),
|
||||||
mkc = proc(k: K): SortedSetItemRef[K,V] = slstMkc[K,V](k))
|
mkc = proc(k: K): SortedSetItemRef[K,V] = slstMkc[K,V](k))
|
||||||
|
|
||||||
proc init*[K,V](T: type SortedSet[K,V]): T =
|
func init*[K,V](T: type SortedSet[K,V]): T =
|
||||||
## Variant of `init()`
|
## Variant of `init()`
|
||||||
result.init
|
result.init
|
||||||
|
|
||||||
proc move*[K,V](sl: var SortedSet[K,V]): SortedSet[K,V] =
|
func move*[K,V](sl: var SortedSet[K,V]): SortedSet[K,V] =
|
||||||
## Return a shallow copy of the argument list `sl`, then reset `sl`.
|
## Return a shallow copy of the argument list `sl`, then reset `sl`.
|
||||||
result.tree = sl.tree
|
result.tree = sl.tree
|
||||||
sl.init
|
sl.init
|
||||||
|
|
||||||
proc clear*[K,V](sl: var SortedSet[K,V]) =
|
func clear*[K,V](sl: var SortedSet[K,V]) =
|
||||||
## Reset list descriptor to its inital value. This function also de-registers
|
## Reset list descriptor to its inital value. This function also de-registers
|
||||||
## and flushes all traversal descriptors of type `SortedSetWalkRef`.
|
## and flushes all traversal descriptors of type `SortedSetWalkRef`.
|
||||||
sl.tree.rbTreeReset(clup = proc(c: var SortedSetItemRef[K,V]) = c.slstClup)
|
sl.tree.rbTreeReset(clup = proc(c: var SortedSetItemRef[K,V]) = c.slstClup)
|
||||||
|
@ -140,15 +142,15 @@ proc clear*[K,V](sl: var SortedSet[K,V]) =
|
||||||
# Public functions, getter, converter
|
# Public functions, getter, converter
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc key*[K,V](data: SortedSetItemRef[K,V]): K =
|
func key*[K,V](data: SortedSetItemRef[K,V]): K =
|
||||||
## Getter, extracts the key from the data container item.
|
## Getter, extracts the key from the data container item.
|
||||||
data.key
|
data.key
|
||||||
|
|
||||||
proc len*[K,V](sl: var SortedSet[K,V]): int =
|
func len*[K,V](sl: var SortedSet[K,V]): int =
|
||||||
## Number of list elements
|
## Number of list elements
|
||||||
sl.tree.size
|
sl.tree.size
|
||||||
|
|
||||||
proc toSortedSetResult*[K,V](key: K; data: V): SortedSetResult[K,V] =
|
func toSortedSetResult*[K,V](key: K; data: V): SortedSetResult[K,V] =
|
||||||
## Helper, chreate `ok()` result
|
## Helper, chreate `ok()` result
|
||||||
ok(SortedSetItemRef[K,V](key: key, data: data))
|
ok(SortedSetItemRef[K,V](key: key, data: data))
|
||||||
|
|
||||||
|
@ -156,24 +158,24 @@ proc toSortedSetResult*[K,V](key: K; data: V): SortedSetResult[K,V] =
|
||||||
# Public functions, list operations
|
# Public functions, list operations
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc insert*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func insert*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Insert `key`, returns data container item with the `key`. Function fails
|
## Insert `key`, returns data container item with the `key`. Function fails
|
||||||
## if `key` exists in the list.
|
## if `key` exists in the list.
|
||||||
sl.tree.rbTreeInsert(key)
|
sl.tree.rbTreeInsert(key)
|
||||||
|
|
||||||
proc findOrInsert*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func findOrInsert*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Insert or find `key`, returns data container item with the `key`. This
|
## Insert or find `key`, returns data container item with the `key`. This
|
||||||
## function always succeeds (unless there is s problem with the list.)
|
## function always succeeds (unless there is s problem with the list.)
|
||||||
result = sl.tree.rbTreeInsert(key)
|
result = sl.tree.rbTreeInsert(key)
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return sl.tree.rbTreeFindEq(key)
|
return sl.tree.rbTreeFindEq(key)
|
||||||
|
|
||||||
proc delete*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func delete*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Delete `key` from list and return the data container item that was
|
## Delete `key` from list and return the data container item that was
|
||||||
## holding the `key` if it was deleted.
|
## holding the `key` if it was deleted.
|
||||||
sl.tree.rbTreeDelete(key)
|
sl.tree.rbTreeDelete(key)
|
||||||
|
|
||||||
proc flush*[K,V](sl: var SortedSet[K,V]) =
|
func flush*[K,V](sl: var SortedSet[K,V]) =
|
||||||
## Flush the sorted list, i.e. delete all entries. This function is
|
## Flush the sorted list, i.e. delete all entries. This function is
|
||||||
## more efficient than running a `delete()` loop.
|
## more efficient than running a `delete()` loop.
|
||||||
sl.tree.rbTreeFlush(clup = proc(c: var SortedSetItemRef[K,V]) = c.slstClup)
|
sl.tree.rbTreeFlush(clup = proc(c: var SortedSetItemRef[K,V]) = c.slstClup)
|
||||||
|
@ -182,27 +184,27 @@ proc flush*[K,V](sl: var SortedSet[K,V]) =
|
||||||
# Public functions, query functions
|
# Public functions, query functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc eq*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func eq*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Find `key` in list, returns data container item with the `key` if it
|
## Find `key` in list, returns data container item with the `key` if it
|
||||||
## exists.
|
## exists.
|
||||||
sl.tree.rbTreeFindEq(key)
|
sl.tree.rbTreeFindEq(key)
|
||||||
|
|
||||||
proc le*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func le*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Find data container iten with *largest* key *less or equal* the argument
|
## Find data container iten with *largest* key *less or equal* the argument
|
||||||
## `key` in list and return it if found.
|
## `key` in list and return it if found.
|
||||||
sl.tree.rbTreeFindLe(key)
|
sl.tree.rbTreeFindLe(key)
|
||||||
|
|
||||||
proc lt*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func lt*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Find data container item with *largest* key *less than* the argument
|
## Find data container item with *largest* key *less than* the argument
|
||||||
## `key` in list and return it if found.
|
## `key` in list and return it if found.
|
||||||
sl.tree.rbTreeFindLt(key)
|
sl.tree.rbTreeFindLt(key)
|
||||||
|
|
||||||
proc ge*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func ge*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Find data container item with *smallest* key *greater or equal* the
|
## Find data container item with *smallest* key *greater or equal* the
|
||||||
## argument `key` in list and return it if found.
|
## argument `key` in list and return it if found.
|
||||||
sl.tree.rbTreeFindGe(key)
|
sl.tree.rbTreeFindGe(key)
|
||||||
|
|
||||||
proc gt*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
func gt*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
## Find data container item with *smallest* key *greater than* the argument
|
## Find data container item with *smallest* key *greater than* the argument
|
||||||
## `key` in list and return it if found.
|
## `key` in list and return it if found.
|
||||||
sl.tree.rbTreeFindGt(key)
|
sl.tree.rbTreeFindGt(key)
|
||||||
|
@ -211,12 +213,12 @@ proc gt*[K,V](sl: var SortedSet[K,V]; key: K): SortedSetResult[K,V] =
|
||||||
# Public functions, walk/traversal functions
|
# Public functions, walk/traversal functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc init*[K,V](T: type SortedSetWalkRef[K,V]; sl: var SortedSet[K,V]): T =
|
func init*[K,V](T: type SortedSetWalkRef[K,V]; sl: var SortedSet[K,V]): T =
|
||||||
## Open traversal descriptor on list and register it on the 'SortedSet`
|
## Open traversal descriptor on list and register it on the 'SortedSet`
|
||||||
## descriptor.
|
## descriptor.
|
||||||
sl.tree.newRbWalk
|
sl.tree.newRbWalk
|
||||||
|
|
||||||
proc destroy*[K,V](w: SortedSetWalkRef[K,V]) =
|
func destroy*[K,V](w: SortedSetWalkRef[K,V]) =
|
||||||
## De-register and close the traversal descriptor. This function renders
|
## De-register and close the traversal descriptor. This function renders
|
||||||
## the descriptor unusable, so it must be disposed of.
|
## the descriptor unusable, so it must be disposed of.
|
||||||
##
|
##
|
||||||
|
@ -227,7 +229,7 @@ proc destroy*[K,V](w: SortedSetWalkRef[K,V]) =
|
||||||
## rewound or destroyed.
|
## rewound or destroyed.
|
||||||
w.rbWalkDestroy
|
w.rbWalkDestroy
|
||||||
|
|
||||||
proc first*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
func first*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## Rewind the traversal descriptor to the *least* list key and return
|
## Rewind the traversal descriptor to the *least* list key and return
|
||||||
## the corresponding data container item.
|
## the corresponding data container item.
|
||||||
##
|
##
|
||||||
|
@ -235,7 +237,7 @@ proc first*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## list operations are reset.
|
## list operations are reset.
|
||||||
w.rbWalkFirst
|
w.rbWalkFirst
|
||||||
|
|
||||||
proc last*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
func last*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## Rewind the traversal descriptor to the *greatest* list key and return
|
## Rewind the traversal descriptor to the *greatest* list key and return
|
||||||
## the corresponding data container item.
|
## the corresponding data container item.
|
||||||
##
|
##
|
||||||
|
@ -243,14 +245,14 @@ proc last*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## list operations are reset.
|
## list operations are reset.
|
||||||
w.rbWalkLast
|
w.rbWalkLast
|
||||||
|
|
||||||
proc this*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
func this*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## Retrieve the *current* data container item. This is the same one retrieved
|
## Retrieve the *current* data container item. This is the same one retrieved
|
||||||
## last with any of the traversal functions returning the data container item.
|
## last with any of the traversal functions returning the data container item.
|
||||||
##
|
##
|
||||||
## Note that the current node becomes unavailable if it was recently deleted.
|
## Note that the current node becomes unavailable if it was recently deleted.
|
||||||
w.rbWalkCurrent
|
w.rbWalkCurrent
|
||||||
|
|
||||||
proc next*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
func next*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## Move the traversal descriptor to the next *greater* key and return the
|
## Move the traversal descriptor to the next *greater* key and return the
|
||||||
## corresponding data container item. If this is the first call after
|
## corresponding data container item. If this is the first call after
|
||||||
## `newWalk()`, then `w.first` is called implicitly.
|
## `newWalk()`, then `w.first` is called implicitly.
|
||||||
|
@ -259,7 +261,7 @@ proc next*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## causing this function to fail so that a rewind is needed.
|
## causing this function to fail so that a rewind is needed.
|
||||||
w.rbWalkNext
|
w.rbWalkNext
|
||||||
|
|
||||||
proc prev*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
func prev*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
## Move the traversal descriptor to the next *smaller* key and return the
|
## Move the traversal descriptor to the next *smaller* key and return the
|
||||||
## corresponding data container item . If this is the first call after
|
## corresponding data container item . If this is the first call after
|
||||||
## `newWalk()`, then `w.last` is called implicitly.
|
## `newWalk()`, then `w.last` is called implicitly.
|
||||||
|
@ -272,7 +274,7 @@ proc prev*[K,V](w: SortedSetWalkRef[K,V]): SortedSetResult[K,V] =
|
||||||
# Public helpers, debugging
|
# Public helpers, debugging
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `$`*[K,V](casket: SortedSetItemRef[K,V]): string =
|
func `$`*[K,V](casket: SortedSetItemRef[K,V]): string =
|
||||||
## Pretty printer
|
## Pretty printer
|
||||||
##
|
##
|
||||||
## :CAVEAT:
|
## :CAVEAT:
|
||||||
|
@ -284,7 +286,7 @@ proc `$`*[K,V](casket: SortedSetItemRef[K,V]): string =
|
||||||
return "nil"
|
return "nil"
|
||||||
"(" & $casket.key & "," & $casket.data & ")"
|
"(" & $casket.key & "," & $casket.data & ")"
|
||||||
|
|
||||||
proc `$`*[K,V](rc: SortedSetResult[K,V]): string =
|
func `$`*[K,V](rc: SortedSetResult[K,V]): string =
|
||||||
## Pretty printer
|
## Pretty printer
|
||||||
##
|
##
|
||||||
## :CAVEAT:
|
## :CAVEAT:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -8,18 +8,18 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
|
||||||
./rbtree_desc,
|
|
||||||
./rbtree_rotate,
|
|
||||||
../results
|
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
results,
|
||||||
|
./rbtree_desc,
|
||||||
|
./rbtree_rotate
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public
|
# Public
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc rbTreeDelete*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeDelete*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function, removes a node from the red-black tree.
|
## Generic red-black tree function, removes a node from the red-black tree.
|
||||||
## The node to be removed wraps a data container `casket` matching the
|
## The node to be removed wraps a data container `casket` matching the
|
||||||
## argument `key`, i.e. `rbt.cmp(casket,key) == 0`.
|
## argument `key`, i.e. `rbt.cmp(casket,key) == 0`.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -67,9 +67,11 @@
|
||||||
# anyone who has modified the code through
|
# anyone who has modified the code through
|
||||||
# a header comment, such as this one.typedef
|
# a header comment, such as this one.typedef
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[tables],
|
results,
|
||||||
../results
|
std/[tables]
|
||||||
|
|
||||||
const
|
const
|
||||||
rbTreeReBalancedFlag* = 1
|
rbTreeReBalancedFlag* = 1
|
||||||
|
@ -176,7 +178,7 @@ type
|
||||||
# Public functions, constructor
|
# Public functions, constructor
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc newRbTreeRef*[C,K](cmp: RbCmpFn[C,K]; mkc: RbMkcFn[C,K]): RbTreeRef[C,K] =
|
func newRbTreeRef*[C,K](cmp: RbCmpFn[C,K]; mkc: RbMkcFn[C,K]): RbTreeRef[C,K] =
|
||||||
## Constructor. Create generic red-black tree descriptor for data container
|
## Constructor. Create generic red-black tree descriptor for data container
|
||||||
## type `C` and key type `K`. Details about the function arguments `cmpFn`
|
## type `C` and key type `K`. Details about the function arguments `cmpFn`
|
||||||
## and `mkcFn` are documented with the type definitions of `RbCmpFn` and
|
## and `mkcFn` are documented with the type definitions of `RbCmpFn` and
|
||||||
|
@ -188,7 +190,7 @@ proc newRbTreeRef*[C,K](cmp: RbCmpFn[C,K]; mkc: RbMkcFn[C,K]): RbTreeRef[C,K] =
|
||||||
walks: initTable[uint,RbWalkRef[C,K]](1))
|
walks: initTable[uint,RbWalkRef[C,K]](1))
|
||||||
|
|
||||||
|
|
||||||
proc newWalkId*[C,K](rbt: RbTreeRef[C,K]): uint {.inline.} =
|
func newWalkId*[C,K](rbt: RbTreeRef[C,K]): uint {.inline.} =
|
||||||
## Generate new free walk ID, returns zero in (theoretical) case all other
|
## Generate new free walk ID, returns zero in (theoretical) case all other
|
||||||
## IDs are exhausted.
|
## IDs are exhausted.
|
||||||
for id in rbt.walkIdGen .. high(type rbt.walkIdGen):
|
for id in rbt.walkIdGen .. high(type rbt.walkIdGen):
|
||||||
|
@ -205,12 +207,12 @@ proc newWalkId*[C,K](rbt: RbTreeRef[C,K]): uint {.inline.} =
|
||||||
# Public handlers
|
# Public handlers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc cmp*[C,K](rbt: RbTreeRef[C,K]; casket: C; key: K): int {.inline.} =
|
func cmp*[C,K](rbt: RbTreeRef[C,K]; casket: C; key: K): int {.inline.} =
|
||||||
## See introduction for an explanation of opaque argument types `C` and `D`,
|
## See introduction for an explanation of opaque argument types `C` and `D`,
|
||||||
## and the type definition for `RbCmpFn` for properties of this function.
|
## and the type definition for `RbCmpFn` for properties of this function.
|
||||||
rbt.cmpFn(casket, key)
|
rbt.cmpFn(casket, key)
|
||||||
|
|
||||||
proc mkc*[C,K](rbt: RbTreeRef[C,K]; key: K): C {.inline.} =
|
func mkc*[C,K](rbt: RbTreeRef[C,K]; key: K): C {.inline.} =
|
||||||
## See introduction for an explanation of opaque argument/return types `C`
|
## See introduction for an explanation of opaque argument/return types `C`
|
||||||
## and `D`, and the type definition for `RbMkdFn` for properties of this
|
## and `D`, and the type definition for `RbMkdFn` for properties of this
|
||||||
## function.
|
## function.
|
||||||
|
@ -220,15 +222,15 @@ proc mkc*[C,K](rbt: RbTreeRef[C,K]; key: K): C {.inline.} =
|
||||||
# Public getters
|
# Public getters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc linkLeft*[C](node: RbNodeRef[C]): RbNodeRef[C] {.inline.} =
|
func linkLeft*[C](node: RbNodeRef[C]): RbNodeRef[C] {.inline.} =
|
||||||
## Getter, shortcut for `node.link[rbLeft]`
|
## Getter, shortcut for `node.link[rbLeft]`
|
||||||
node.link[rbLeft]
|
node.link[rbLeft]
|
||||||
|
|
||||||
proc linkRight*[C](node: RbNodeRef[C]): RbNodeRef[C] {.inline.} =
|
func linkRight*[C](node: RbNodeRef[C]): RbNodeRef[C] {.inline.} =
|
||||||
## Getter, shortcut for `node.link[rbRight]`
|
## Getter, shortcut for `node.link[rbRight]`
|
||||||
node.link[rbRight]
|
node.link[rbRight]
|
||||||
|
|
||||||
proc isRed*[C](node: RbNodeRef[C]): bool {.inline.} =
|
func isRed*[C](node: RbNodeRef[C]): bool {.inline.} =
|
||||||
## Getter, `true` if node colour is read.
|
## Getter, `true` if node colour is read.
|
||||||
not node.isNil and node.redColour
|
not node.isNil and node.redColour
|
||||||
|
|
||||||
|
@ -236,15 +238,15 @@ proc isRed*[C](node: RbNodeRef[C]): bool {.inline.} =
|
||||||
# Public setters
|
# Public setters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `linkLeft=`*[C](node, child: RbNodeRef[C]) {.inline.} =
|
func `linkLeft=`*[C](node, child: RbNodeRef[C]) {.inline.} =
|
||||||
## Getter, shortcut for `node.link[rbLeft] = child`
|
## Getter, shortcut for `node.link[rbLeft] = child`
|
||||||
node.link[rbLeft] = child
|
node.link[rbLeft] = child
|
||||||
|
|
||||||
proc `linkRight=`*[C](node, child: RbNodeRef[C]) {.inline.} =
|
func `linkRight=`*[C](node, child: RbNodeRef[C]) {.inline.} =
|
||||||
## Getter, shortcut for `node.link[rbRight] = child`
|
## Getter, shortcut for `node.link[rbRight] = child`
|
||||||
node.link[rbRight] = child
|
node.link[rbRight] = child
|
||||||
|
|
||||||
proc `isRed=`*[C](node: RbNodeRef[C]; value: bool) {.inline.} =
|
func `isRed=`*[C](node: RbNodeRef[C]; value: bool) {.inline.} =
|
||||||
## Setter, `true` sets red node colour.
|
## Setter, `true` sets red node colour.
|
||||||
node.redColour = value
|
node.redColour = value
|
||||||
|
|
||||||
|
@ -252,11 +254,11 @@ proc `isRed=`*[C](node: RbNodeRef[C]; value: bool) {.inline.} =
|
||||||
# Public helpers: `rbDir` as array index
|
# Public helpers: `rbDir` as array index
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `not`*(d: RbDir): RbDir {.inline.} =
|
func `not`*(d: RbDir): RbDir {.inline.} =
|
||||||
## Opposite direction of argument `d`.
|
## Opposite direction of argument `d`.
|
||||||
if d == rbLeft: rbRight else: rbLeft
|
if d == rbLeft: rbRight else: rbLeft
|
||||||
|
|
||||||
proc toDir*(b: bool): RbDir {.inline.} =
|
func toDir*(b: bool): RbDir {.inline.} =
|
||||||
## Convert to link diection `rbLeft` (false) or `rbRight` (true).
|
## Convert to link diection `rbLeft` (false) or `rbRight` (true).
|
||||||
if b: rbRight else: rbLeft
|
if b: rbRight else: rbLeft
|
||||||
|
|
||||||
|
@ -264,7 +266,7 @@ proc toDir*(b: bool): RbDir {.inline.} =
|
||||||
# Public pretty printer
|
# Public pretty printer
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc `$`*[C](node: RbNodeRef[C]): string =
|
func `$`*[C](node: RbNodeRef[C]): string =
|
||||||
## Pretty printer, requres `$()` for type `C` to be known.
|
## Pretty printer, requres `$()` for type `C` to be known.
|
||||||
if node.isNil:
|
if node.isNil:
|
||||||
return "nil"
|
return "nil"
|
||||||
|
@ -276,7 +278,7 @@ proc `$`*[C](node: RbNodeRef[C]): string =
|
||||||
"left=" & $node.linkLeft & "," &
|
"left=" & $node.linkLeft & "," &
|
||||||
"right=" & $node.linkRight & ")"
|
"right=" & $node.linkRight & ")"
|
||||||
|
|
||||||
proc `$`*[C,K](rbt: RbTreeRef[C,K]): string =
|
func `$`*[C,K](rbt: RbTreeRef[C,K]): string =
|
||||||
## Pretty printer
|
## Pretty printer
|
||||||
if rbt.isNil:
|
if rbt.isNil:
|
||||||
return "nil"
|
return "nil"
|
||||||
|
@ -285,7 +287,7 @@ proc `$`*[C,K](rbt: RbTreeRef[C,K]): string =
|
||||||
"gen=" & $rbt.walkIdGen & "," &
|
"gen=" & $rbt.walkIdGen & "," &
|
||||||
"root=" & $rbt.root & "]"
|
"root=" & $rbt.root & "]"
|
||||||
|
|
||||||
proc `$`*[C,K](w: RbWalkRef[C,K]): string =
|
func `$`*[C,K](w: RbWalkRef[C,K]): string =
|
||||||
## Pretty printer
|
## Pretty printer
|
||||||
if w.isNil:
|
if w.isNil:
|
||||||
return "nil"
|
return "nil"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -8,17 +8,17 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
|
||||||
./rbtree_desc,
|
|
||||||
../results
|
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
results,
|
||||||
|
./rbtree_desc
|
||||||
|
|
||||||
# ----------------------------------------------------------------------- ------
|
# ----------------------------------------------------------------------- ------
|
||||||
# Public
|
# Public
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc rbTreeFindEq*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeFindEq*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function. Search for a data container `casket` of
|
## Generic red-black tree function. Search for a data container `casket` of
|
||||||
## type `C` in the red black tree which matches the argument `key`,
|
## type `C` in the red black tree which matches the argument `key`,
|
||||||
## i.e. `rbt.cmp(casket,key) == 0`. If found, this data container `casket` is
|
## i.e. `rbt.cmp(casket,key) == 0`. If found, this data container `casket` is
|
||||||
|
@ -51,7 +51,7 @@ proc rbTreeFindEq*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
return err(rbNotFound)
|
return err(rbNotFound)
|
||||||
|
|
||||||
|
|
||||||
proc rbTreeFindGe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeFindGe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function. Search for the *smallest* data container
|
## Generic red-black tree function. Search for the *smallest* data container
|
||||||
## `casket` of type `C` which is *greater or equal* to the specified argument
|
## `casket` of type `C` which is *greater or equal* to the specified argument
|
||||||
## `key` in the red black-tree. If such a data container is found in the
|
## `key` in the red black-tree. If such a data container is found in the
|
||||||
|
@ -109,7 +109,7 @@ proc rbTreeFindGe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
return err(rbNotFound)
|
return err(rbNotFound)
|
||||||
|
|
||||||
|
|
||||||
proc rbTreeFindGt*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeFindGt*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function. Search for the *smallest* data container
|
## Generic red-black tree function. Search for the *smallest* data container
|
||||||
## of type `C` which is *strictly greater* than the specified argument `key`
|
## of type `C` which is *strictly greater* than the specified argument `key`
|
||||||
## in the red-black tree.
|
## in the red-black tree.
|
||||||
|
@ -148,7 +148,7 @@ proc rbTreeFindGt*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
return err(rbNotFound)
|
return err(rbNotFound)
|
||||||
|
|
||||||
|
|
||||||
proc rbTreeFindLe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeFindLe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function. Search for the *greatest* data container
|
## Generic red-black tree function. Search for the *greatest* data container
|
||||||
## of type `C` which is *less than or equal* to the specified argument
|
## of type `C` which is *less than or equal* to the specified argument
|
||||||
## `key` in the red-black tree.
|
## `key` in the red-black tree.
|
||||||
|
@ -190,7 +190,7 @@ proc rbTreeFindLe*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
return err(rbNotFound)
|
return err(rbNotFound)
|
||||||
|
|
||||||
|
|
||||||
proc rbTreeFindLt*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeFindLt*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function. Search for the *greatest* data container
|
## Generic red-black tree function. Search for the *greatest* data container
|
||||||
## of type `C` which is *strictly less* than the specified argument `key` in
|
## of type `C` which is *strictly less* than the specified argument `key` in
|
||||||
## the red-black tree.
|
## the red-black tree.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -8,25 +8,25 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
|
||||||
./rbtree_desc,
|
|
||||||
./rbtree_rotate,
|
|
||||||
../results
|
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
results,
|
||||||
|
./rbtree_desc,
|
||||||
|
./rbtree_rotate
|
||||||
|
|
||||||
# ----------------------------------------------------------------------- ------
|
# ----------------------------------------------------------------------- ------
|
||||||
# Private functions
|
# Private functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc insertRoot[C,K](rbt: RbTreeRef[C,K]; key: K): C {.inline.} =
|
func insertRoot[C,K](rbt: RbTreeRef[C,K]; key: K): C {.inline.} =
|
||||||
## Insert item `x` into an empty tree.
|
## Insert item `x` into an empty tree.
|
||||||
rbt.root = RbNodeRef[C](
|
rbt.root = RbNodeRef[C](
|
||||||
casket: rbt.mkc(key))
|
casket: rbt.mkc(key))
|
||||||
rbt.size = 1
|
rbt.size = 1
|
||||||
rbt.root.casket
|
rbt.root.casket
|
||||||
|
|
||||||
proc insertNode[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] {.inline.} =
|
func insertNode[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] {.inline.} =
|
||||||
## Insert item `key` into a non-empty tree.
|
## Insert item `key` into a non-empty tree.
|
||||||
|
|
||||||
doAssert not rbt.root.isNil
|
doAssert not rbt.root.isNil
|
||||||
|
@ -108,7 +108,7 @@ proc insertNode[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] {.inline.} =
|
||||||
# Public
|
# Public
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc rbTreeInsert*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
func rbTreeInsert*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
|
||||||
## Generic red-black tree function, inserts a data container `casket` derived
|
## Generic red-black tree function, inserts a data container `casket` derived
|
||||||
## from argument `key` into the red-black tree.
|
## from argument `key` into the red-black tree.
|
||||||
##
|
##
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -8,9 +8,11 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
./rbtree_desc,
|
results,
|
||||||
../results
|
./rbtree_desc
|
||||||
|
|
||||||
type
|
type
|
||||||
RbLtFn*[C] = ##\
|
RbLtFn*[C] = ##\
|
||||||
|
@ -40,7 +42,7 @@ type
|
||||||
# Private
|
# Private
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc pp[C](n: RbNodeRef[C]): string =
|
func pp[C](n: RbNodeRef[C]): string =
|
||||||
if n.isNil:
|
if n.isNil:
|
||||||
return "nil"
|
return "nil"
|
||||||
result = $n.casket
|
result = $n.casket
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Nimbus
|
# Nimbus
|
||||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
@ -8,18 +8,18 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
|
||||||
std/[tables],
|
|
||||||
./rbtree_desc,
|
|
||||||
../results
|
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
results,
|
||||||
|
std/[tables],
|
||||||
|
./rbtree_desc
|
||||||
|
|
||||||
# ----------------------------------------------------------------------- ------
|
# ----------------------------------------------------------------------- ------
|
||||||
# Priv
|
# Priv
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc walkMove[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
func walkMove[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
||||||
## Traverse a red black tree in the user-specified direction.
|
## Traverse a red black tree in the user-specified direction.
|
||||||
##
|
##
|
||||||
## :Returns:
|
## :Returns:
|
||||||
|
@ -62,7 +62,7 @@ proc walkMove[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
||||||
return err(rbEndOfWalk)
|
return err(rbEndOfWalk)
|
||||||
|
|
||||||
|
|
||||||
proc walkStart[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
func walkStart[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
||||||
## Rewind the traversal position to the left-most or-right-most position
|
## Rewind the traversal position to the left-most or-right-most position
|
||||||
## as defined by the function argument `dir`. After successfully rewinding,
|
## as defined by the function argument `dir`. After successfully rewinding,
|
||||||
## the desriptor is in `start` position (see `walkClearDirty()`).
|
## the desriptor is in `start` position (see `walkClearDirty()`).
|
||||||
|
@ -94,7 +94,7 @@ proc walkStart[C,K](w: RbWalkRef[C,K]; dir: RbDir): RbResult[C] =
|
||||||
return ok(w.node.casket)
|
return ok(w.node.casket)
|
||||||
|
|
||||||
|
|
||||||
proc walkClearDirtyFlags[C,K](w: RbWalkRef[C,K]): bool =
|
func walkClearDirtyFlags[C,K](w: RbWalkRef[C,K]): bool =
|
||||||
## Clear dirty flag if all traversal descriptors are in `start` postion.
|
## Clear dirty flag if all traversal descriptors are in `start` postion.
|
||||||
if w.tree.dirty != 0:
|
if w.tree.dirty != 0:
|
||||||
for u in w.tree.walks.values:
|
for u in w.tree.walks.values:
|
||||||
|
@ -110,7 +110,7 @@ proc walkClearDirtyFlags[C,K](w: RbWalkRef[C,K]): bool =
|
||||||
# Public constructor/desctructor
|
# Public constructor/desctructor
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc newRbWalk*[C,K](rbt: RbTreeRef[C,K]): RbWalkRef[C,K] =
|
func newRbWalk*[C,K](rbt: RbTreeRef[C,K]): RbWalkRef[C,K] =
|
||||||
## Generic red-black tree function, creates a new traversal descriptor on the
|
## Generic red-black tree function, creates a new traversal descriptor on the
|
||||||
## argument red-black tree `rbt`.
|
## argument red-black tree `rbt`.
|
||||||
##
|
##
|
||||||
|
@ -127,7 +127,7 @@ proc newRbWalk*[C,K](rbt: RbTreeRef[C,K]): RbWalkRef[C,K] =
|
||||||
rbt.walks[result.id] = result # register in parent descriptor
|
rbt.walks[result.id] = result # register in parent descriptor
|
||||||
|
|
||||||
|
|
||||||
proc rbWalkDestroy*[C,K](w: RbWalkRef[C,K]) =
|
func rbWalkDestroy*[C,K](w: RbWalkRef[C,K]) =
|
||||||
## Explicit destructor for current walk descriptor `w`. Clears the descriptor
|
## Explicit destructor for current walk descriptor `w`. Clears the descriptor
|
||||||
## argument `w`.
|
## argument `w`.
|
||||||
##
|
##
|
||||||
|
@ -142,7 +142,7 @@ proc rbWalkDestroy*[C,K](w: RbWalkRef[C,K]) =
|
||||||
w.path = @[]
|
w.path = @[]
|
||||||
w[].reset
|
w[].reset
|
||||||
|
|
||||||
proc rbWalkDestroyAll*[C,K](rbt: RbTreeRef[C,K]) =
|
func rbWalkDestroyAll*[C,K](rbt: RbTreeRef[C,K]) =
|
||||||
## Apply `rbWalkDestroy()` to all registered walk descriptors.
|
## Apply `rbWalkDestroy()` to all registered walk descriptors.
|
||||||
for w in rbt.walks.values:
|
for w in rbt.walks.values:
|
||||||
w.tree = nil # notify GC (if any, todo?)
|
w.tree = nil # notify GC (if any, todo?)
|
||||||
|
@ -151,7 +151,7 @@ proc rbWalkDestroyAll*[C,K](rbt: RbTreeRef[C,K]) =
|
||||||
w[].reset # clear
|
w[].reset # clear
|
||||||
rbt.walks = initTable[uint,RbWalkRef[C,K]](1)
|
rbt.walks = initTable[uint,RbWalkRef[C,K]](1)
|
||||||
|
|
||||||
proc rbWalkDestroyAll*[C,K](w: RbWalkRef[C,K]) =
|
func rbWalkDestroyAll*[C,K](w: RbWalkRef[C,K]) =
|
||||||
## Variant of `rbWalkDestroyAll()`
|
## Variant of `rbWalkDestroyAll()`
|
||||||
if not w.tree.isNil:
|
if not w.tree.isNil:
|
||||||
w.tree.rbWalkDestroyAll
|
w.tree.rbWalkDestroyAll
|
||||||
|
@ -160,7 +160,7 @@ proc rbWalkDestroyAll*[C,K](w: RbWalkRef[C,K]) =
|
||||||
# Public functions: rewind
|
# Public functions: rewind
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc rbWalkFirst*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
func rbWalkFirst*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
## Move to the beginning of the tree (*smallest* item) and return the
|
## Move to the beginning of the tree (*smallest* item) and return the
|
||||||
## corresponding data container of type `C`.
|
## corresponding data container of type `C`.
|
||||||
##
|
##
|
||||||
|
@ -181,7 +181,7 @@ proc rbWalkFirst*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
return w.walkStart(rbLeft)
|
return w.walkStart(rbLeft)
|
||||||
|
|
||||||
|
|
||||||
proc rbWalkLast*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
func rbWalkLast*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
## Move to the end of the tree (*greatest* item) and return the corresponding
|
## Move to the end of the tree (*greatest* item) and return the corresponding
|
||||||
## data container of type `C`.
|
## data container of type `C`.
|
||||||
##
|
##
|
||||||
|
@ -205,7 +205,7 @@ proc rbWalkLast*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
# Public functions: traversal, get data entry
|
# Public functions: traversal, get data entry
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc rbWalkCurrent*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
func rbWalkCurrent*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
## Retrieves the data container of type `C` for the current node. Note that
|
## Retrieves the data container of type `C` for the current node. Note that
|
||||||
## the current node becomes unavailable if it was recently deleted.
|
## the current node becomes unavailable if it was recently deleted.
|
||||||
##
|
##
|
||||||
|
@ -222,7 +222,7 @@ proc rbWalkCurrent*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc rbWalkNext*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
func rbWalkNext*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
## Traverse to the next value in ascending order and return the corresponding
|
## Traverse to the next value in ascending order and return the corresponding
|
||||||
## data container of type `C`. If this is the first call after `newRbWalk()`,
|
## data container of type `C`. If this is the first call after `newRbWalk()`,
|
||||||
## then `rbWalkFirst()` is called implicitly.
|
## then `rbWalkFirst()` is called implicitly.
|
||||||
|
@ -253,7 +253,7 @@ proc rbWalkNext*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
return w.walkStart(rbLeft) # minimum index item
|
return w.walkStart(rbLeft) # minimum index item
|
||||||
|
|
||||||
|
|
||||||
proc rbWalkPrev*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
func rbWalkPrev*[C,K](w: RbWalkRef[C,K]): RbResult[C] =
|
||||||
## Traverse to the next value in descending order and return the
|
## Traverse to the next value in descending order and return the
|
||||||
## corresponding data container of type `C`. If this is the first call
|
## corresponding data container of type `C`. If this is the first call
|
||||||
## after `newRbWalk()`, then `rbWalkLast()` is called implicitly.
|
## after `newRbWalk()`, then `rbWalkLast()` is called implicitly.
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# Copyright (c) 2020-2022 Status Research & Development GmbH
|
# Copyright (c) 2020-2024 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license: http://opensource.org/licenses/MIT
|
# * MIT license: http://opensource.org/licenses/MIT
|
||||||
# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import std/[os, strutils]
|
import std/[os, strutils]
|
||||||
import ../stew/io2, ../stew/results
|
import pkg/results
|
||||||
|
import ../stew/io2
|
||||||
|
|
||||||
proc lockFileFlags(path: string, flags: set[OpenFlags],
|
proc lockFileFlags(path: string, flags: set[OpenFlags],
|
||||||
lockType: LockType): IoResult[void] =
|
lockType: LockType): IoResult[void] =
|
||||||
|
|
Loading…
Reference in New Issue