lib/standard/ropes: Added a final forward iterator on the chars.
[nit.git] / lib / standard / ropes.nit
index b76784f..f4221b0 100644 (file)
@@ -117,6 +117,12 @@ abstract class Rope
        # Iterator on the leaves of the rope, forward order
        private fun leaves(from: Int): LeavesIterator do return new LeavesIterator(self, from)
 
+       # Iterator on the substrings from 0, in forward order
+       fun substrings: IndexedIterator[Text] do return new SubstringsIterator(self, 0)
+
+       # Iterator on the substrings, starting at position `from`, in forward order
+       fun substrings_from(from: Int): IndexedIterator[Text] do return new SubstringsIterator(self, from)
+
        # Path to the Leaf for `position`
        private fun node_at(position: Int): Path
        do
@@ -420,3 +426,98 @@ class LeavesIterator
        end
 end
 
+# Uses the leaves and calculates a new substring on each iteration
+class SubstringsIterator
+       super IndexedIterator[Text]
+
+       private var nodes: IndexedIterator[Leaf]
+
+       # Current position in Rope
+       var pos: Int
+
+       # Current substring, computed from the current Leaf and indexes
+       var substring: Text
+
+       init(tgt: Rope, pos: Int)
+       do
+               nodes = tgt.leaves(pos)
+               self.pos = pos
+               if pos < 0 or pos >= tgt.length then return
+               make_substring
+       end
+
+       # Compute the bounds of the current substring and makes the substring
+       private fun make_substring
+       do
+               substring = nodes.item.str
+               var min = 0
+               var length = substring.length
+               if nodes.index < pos then
+                       min = pos - nodes.index
+               end
+               substring = substring.substring(min, length)
+       end
+
+       redef fun is_ok do return nodes.is_ok
+
+       redef fun item
+       do
+               assert is_ok
+               return substring
+       end
+
+       redef fun index do return pos
+
+       redef fun next
+       do
+               pos += substring.length
+               nodes.next
+               if nodes.is_ok then make_substring
+       end
+
+end
+
+class RopeCharIterator
+       super IndexedIterator[Char]
+
+       var substrings: IndexedIterator[Text]
+
+       var pos: Int
+
+       var max: Int
+
+       var substr_iter: IndexedIterator[Char]
+
+       init(tgt: Rope, from: Int)
+       do
+               substrings = tgt.substrings_from(from)
+               max = tgt.length - 1
+               if not substrings.is_ok then
+                       pos = tgt.length
+                       return
+               end
+               pos = from
+               substr_iter = substrings.item.chars.iterator
+       end
+
+       redef fun item do return substr_iter.item
+
+       redef fun is_ok do return pos <= max
+
+       redef fun index do return pos
+
+       redef fun next
+       do
+               pos += 1
+               if substr_iter.is_ok then
+                       substr_iter.next
+               end
+               if not substr_iter.is_ok then
+                       substrings.next
+                       if substrings.is_ok then
+                               substr_iter = substrings.item.chars.iterator
+                       end
+               end
+       end
+end
+