#
# Ropes are a data structure introduced in a 1995 paper from
# Hans J. Boehm, Russ Atkinson and Michael Plass.
-# See : `Ropes : an Alternative to Strings`, `Software - Practice and Experience,
-# Vol. 25(12), 1315-1330 (December 1995)`.
+#
+# See:
+#
+# > Ropes: an Alternative to Strings,
+# > *Software - Practice and Experience*,
+# > Vol. 25(12), 1315-1330 (December 1995).
#
# The implementation developed here provides an automatic change
# of data structure depending on the length of the leaves.
#
# Example :
#
-# ` Concat `
-# ` / \ `
-# ` Concat Concat `
-# ` / \ / \ `
-# `"My" " Name" " is" " Simon." `
+# Concat
+# / \
+# Concat Concat
+# / \ / \
+# "My" " Name" " is" " Simon."
#
# Note that the above example is not representative of the actual implementation
# of `Ropes`, since short leaves are merged to keep the rope at an acceptable
super Rope
super String
- redef fun chars is cached do return new RopeChars(self)
+ redef var chars is lazy do return new RopeChars(self)
end
# Node that represents a concatenation between two `String`
private class Concat
super RopeString
- redef var length: Int
+ redef var length is noinit
redef fun substrings do return new RopeSubstrings(self)
redef fun empty do return ""
- redef fun to_cstring is cached do
+ redef var to_cstring is lazy do
var len = length
var ns = new NativeString(len + 1)
ns[len] = '\0'
# Right child of the node
var right: String
- init(l: String, r: String) is old_style_init do
- left = l
- right = r
- length = l.length + r.length
+ init do
+ length = left.length + right.length
end
redef fun output do
else
var r = right
var rlen = r.length
- if rlen + slen > maxlen then return new Concat(left, new Concat(r, s))
+ if rlen + slen > maxlen then return new Concat(self, s)
return new Concat(left, r + s)
end
end
+
+ redef fun copy_to_native(dest, n, src_offset, dest_offset) do
+ var subs = new RopeSubstrings.from(self, src_offset)
+ var st = src_offset - subs.pos
+ var off = dest_offset
+ while n > 0 do
+ var it = subs.item
+ if n > it.length then
+ var cplen = it.length - st
+ it.items.copy_to(dest, cplen, st, off)
+ off += cplen
+ n -= cplen
+ else
+ it.items.copy_to(dest, n, st, off)
+ n = 0
+ end
+ subs.next
+ st = 0
+ end
+ end
end
# Mutable `Rope`, optimized for concatenation operations
super Rope
super Buffer
- redef fun chars: Sequence[Char] is cached do return new RopeBufferChars(self)
+ redef var chars: Sequence[Char] is lazy do return new RopeBufferChars(self)
# The final string being built on the fly
private var str: String is noinit
# mutable native string (`ns`)
private var buf_size: Int is noinit
- redef fun substrings: Iterator[String] do return new RopeBufSubstringIterator(self)
+ redef fun substrings do return new RopeBufSubstringIterator(self)
# Builds an empty `RopeBuffer`
init do
end
private class RopeBufSubstringIterator
- super Iterator[String]
+ super Iterator[FlatText]
# Iterator on the substrings of the building string
- var iter: Iterator[String]
+ var iter: Iterator[FlatText]
# Makes a String out of the buffered part of the Ropebuffer
- var nsstr: String
+ var nsstr: FlatString
# Did we attain the buffered part ?
var nsstr_done = false
# Substrings of a Rope (i.e. Postfix iterator on leaves)
private class RopeSubstrings
- super IndexedIterator[String]
+ super IndexedIterator[FlatString]
# Visit Stack
var iter: RopeIterPiece is noinit
var max: Int is noinit
# Current leaf
- var str: String is noinit
+ var str: FlatString is noinit
init(root: RopeString) is old_style_init do
var r = new RopeIterPiece(root, true, false, null)
rnod = rnod.left
r = new RopeIterPiece(rnod, true, false, r)
else
- str = rnod
+ str = rnod.as(FlatString)
r.rdone = true
iter = r
break
r = new RopeIterPiece(rnod, true, false, r)
end
else
- str = rnod
+ str = rnod.as(FlatString)
r.rdone = true
iter = r
self.pos = pos - off
if not rnod isa Concat then
it.ldone = true
it.rdone = true
- str = rnod
+ str = rnod.as(FlatString)
iter = it.as(not null)
break
end
private class RopeChars
super StringCharView
- var tgt: RopeString
-
- init(s: RopeString) is old_style_init do tgt = s
+ redef type SELFTYPE: RopeString
redef fun [](i) do
- return tgt[i]
+ return target[i]
end
- redef fun iterator_from(i) do return new RopeIter.from(tgt, i)
+ redef fun iterator_from(i) do return new RopeIter.from(target, i)
- redef fun reverse_iterator_from(i) do return new RopeReviter.from(tgt, i)
+ redef fun reverse_iterator_from(i) do return new RopeReviter.from(target, i)
end
# Maximum position iterable.
var maxpos: Int
- redef var index: Int
+ redef var index
# Init the iterator from a RopeBuffer.
init(t: RopeBuffer) is old_style_init do
# Current position in `ns`.
var pns: Int
- redef var index: Int
+ redef var index
# Init the iterator from a RopeBuffer.
init(tgt: RopeBuffer) is old_style_init do