From: Lucas Bajolet Date: Wed, 4 Jun 2014 20:41:48 +0000 (-0400) Subject: lib/standard/ropes: Search method and classes added. X-Git-Tag: v0.6.6~43^2~24 X-Git-Url: http://nitlanguage.org lib/standard/ropes: Search method and classes added. Signed-off-by: Lucas Bajolet --- diff --git a/lib/standard/ropes.nit b/lib/standard/ropes.nit index eef9360..30966ee 100644 --- a/lib/standard/ropes.nit +++ b/lib/standard/ropes.nit @@ -17,6 +17,29 @@ module ropes intrude import string +# Used when searching for a particular node +# Returns the path to the node from the root of the rope +# Also, the node and the offset for seeked position in the rope +private class Path + # Leaf found + var leaf: Leaf + # Offset in leaf + var offset: Int + # Stack of the nodes traversed, and the path used + var stack: List[PathElement] +end + +# An element for a Path, has the concat node and whether or not +# left or right child was visited. +private class PathElement + # Visited node + var node: Concat + # Was the left child visited ? + var left = false + # Was the right child visited ? + var right = false +end + # A node for a Rope private abstract class RopeNode # Length of the node @@ -87,6 +110,38 @@ abstract class Rope end redef fun length do return root.length + + # Path to the Leaf for `position` + private fun node_at(position: Int): Path + do + assert position >= 0 and position < length + return get_node_from(root.as(not null), 0, position, new List[PathElement]) + end + + # Builds the path to Leaf at position `seek_pos` + private fun get_node_from(node: RopeNode, curr_pos: Int, seek_pos: Int, stack: List[PathElement]): Path + do + assert curr_pos >= 0 + if node isa Leaf then return new Path(node, seek_pos - curr_pos, stack) + node = node.as(Concat) + + if node.left != null then + var next_pos = curr_pos + node.left.length + stack.add(new PathElement(node)) + if next_pos > seek_pos then + stack.last.left = true + return get_node_from(node.left.as(not null), curr_pos, seek_pos, stack) + end + stack.last.right = true + return get_node_from(node.right.as(not null), next_pos, seek_pos, stack) + else + var vis = new PathElement(node) + vis.right = true + stack.add(vis) + return get_node_from(node.right.as(not null), curr_pos, seek_pos, stack) + end + end + end # Rope that cannot be modified