Fixes ropes regressions due to the not-nil strings (#8687)
This commit is contained in:
parent
b28c7d434b
commit
b75808c7d9
2 changed files with 46 additions and 9 deletions
|
|
@ -37,8 +37,6 @@ type
|
||||||
length: int
|
length: int
|
||||||
data: string # != nil if a leaf
|
data: string # != nil if a leaf
|
||||||
|
|
||||||
proc isConc(r: Rope): bool {.inline.} = return r.length > 0
|
|
||||||
|
|
||||||
# Note that the left and right pointers are not needed for leafs.
|
# Note that the left and right pointers are not needed for leafs.
|
||||||
# Leaves have relatively high memory overhead (~30 bytes on a 32
|
# Leaves have relatively high memory overhead (~30 bytes on a 32
|
||||||
# bit machine) and we produce many of them. This is why we cache and
|
# bit machine) and we produce many of them. This is why we cache and
|
||||||
|
|
@ -50,12 +48,12 @@ proc isConc(r: Rope): bool {.inline.} = return r.length > 0
|
||||||
proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
|
proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
|
||||||
## the rope's length
|
## the rope's length
|
||||||
if a == nil: result = 0
|
if a == nil: result = 0
|
||||||
else: result = abs a.length
|
else: result = a.length
|
||||||
|
|
||||||
proc newRope(): Rope = new(result)
|
proc newRope(): Rope = new(result)
|
||||||
proc newRope(data: string): Rope =
|
proc newRope(data: string): Rope =
|
||||||
new(result)
|
new(result)
|
||||||
result.length = -len(data)
|
result.length = len(data)
|
||||||
result.data = data
|
result.data = data
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -170,7 +168,9 @@ proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
|
||||||
result = a
|
result = a
|
||||||
else:
|
else:
|
||||||
result = newRope()
|
result = newRope()
|
||||||
result.length = abs(a.length) + abs(b.length)
|
result.length = a.length + b.length
|
||||||
|
result.left = a
|
||||||
|
result.right = b
|
||||||
|
|
||||||
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
|
||||||
## the concatenation operator for ropes.
|
## the concatenation operator for ropes.
|
||||||
|
|
@ -199,11 +199,11 @@ proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} =
|
||||||
var j = i
|
var j = i
|
||||||
if x == nil: return
|
if x == nil: return
|
||||||
while true:
|
while true:
|
||||||
if not isConc(x):
|
if x != nil and x.data.len > 0:
|
||||||
if x.data.len <% j: return x.data[j]
|
if j < x.data.len: return x.data[j]
|
||||||
return '\0'
|
return '\0'
|
||||||
else:
|
else:
|
||||||
if x.left.len >% j:
|
if x.left.length > j:
|
||||||
x = x.left
|
x = x.left
|
||||||
else:
|
else:
|
||||||
x = x.right
|
x = x.right
|
||||||
|
|
@ -215,7 +215,8 @@ iterator leaves*(r: Rope): string =
|
||||||
var stack = @[r]
|
var stack = @[r]
|
||||||
while stack.len > 0:
|
while stack.len > 0:
|
||||||
var it = stack.pop
|
var it = stack.pop
|
||||||
while isConc(it):
|
while it.left != nil:
|
||||||
|
assert(it.right != nil)
|
||||||
stack.add(it.right)
|
stack.add(it.right)
|
||||||
it = it.left
|
it = it.left
|
||||||
assert(it != nil)
|
assert(it != nil)
|
||||||
|
|
|
||||||
36
tests/stdlib/tropes.nim
Normal file
36
tests/stdlib/tropes.nim
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
discard """
|
||||||
|
file: "tropes.nim"
|
||||||
|
output: '''0
|
||||||
|
3
|
||||||
|
|
||||||
|
123
|
||||||
|
3
|
||||||
|
6
|
||||||
|
123
|
||||||
|
123456
|
||||||
|
2
|
||||||
|
3'''
|
||||||
|
"""
|
||||||
|
import ropes
|
||||||
|
|
||||||
|
var
|
||||||
|
r1 = rope("")
|
||||||
|
r2 = rope("123")
|
||||||
|
|
||||||
|
echo r1.len
|
||||||
|
echo r2.len
|
||||||
|
|
||||||
|
echo r1
|
||||||
|
echo r2
|
||||||
|
|
||||||
|
r1.add("123")
|
||||||
|
r2.add("456")
|
||||||
|
|
||||||
|
echo r1.len
|
||||||
|
echo r2.len
|
||||||
|
|
||||||
|
echo r1
|
||||||
|
echo r2
|
||||||
|
|
||||||
|
echo r1[1]
|
||||||
|
echo r2[2]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue