[pypy-svn] r49298 - in pypy/dist/pypy/rlib: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Sun Dec 2 21:05:09 CET 2007
Author: cfbolz
Date: Sun Dec 2 21:05:08 2007
New Revision: 49298
Modified:
pypy/dist/pypy/rlib/rope.py
pypy/dist/pypy/rlib/test/test_rope.py
Log:
completely rewrite the seekable rope iterator to be conceptually more right:
seeking now is O(log(distance)), not O(distance).
Modified: pypy/dist/pypy/rlib/rope.py
==============================================================================
--- pypy/dist/pypy/rlib/rope.py (original)
+++ pypy/dist/pypy/rlib/rope.py Sun Dec 2 21:05:08 2007
@@ -970,48 +970,64 @@
class SeekableItemIterator(object):
def __init__(self, node):
- self.iter = SeekableFringeIterator(node)
- self.node = self.nextnode()
- self.nodelength = self.node.length()
- self.index = 0
+ self.stack = []
+ self.tookleft = []
+ self.find_downward(node)
+ assert False not in self.tookleft
+
+ def find_downward(self, node, items=0):
+ assert 0 <= items < node.length()
+ while isinstance(node, BinaryConcatNode):
+ self.stack.append(node)
+ right = node.right
+ left = node.left
+ if items >= left.length():
+ items -= left.length()
+ node = node.right
+ self.tookleft.append(False)
+ else:
+ node = node.left
+ self.tookleft.append(True)
+ assert len(self.tookleft) == len(self.stack)
+ self.node = node
+ self.nodelength = node.length()
+ self.index = items
+ return self.node
def nextnode(self):
- while 1:
- node = self.node = self.iter.next()
- nodelength = self.nodelength = node.length()
- if nodelength != 0:
- break
- self.index = 0
- return node
-
+ below = self.node
+ while self.stack:
+ tookleft = self.tookleft.pop()
+ if tookleft:
+ node = self.stack[-1]
+ assert isinstance(node, BinaryConcatNode)
+ self.tookleft.append(False)
+ self.find_downward(node.right)
+ return self.node
+ self.stack.pop()
+ raise StopIteration
+
+ def getnode(self):
+ if self.index == self.node.length():
+ return self.nextnode()
+ return self.node
- def advance_index(self):
- if self.index == self.nodelength - 1:
- self.node = None
- self.index += 1
-
def nextchar(self):
- node = self.node
- if node is None:
- node = self.nextnode()
- result = self.node.getchar(self.index)
- self.advance_index()
+ node = self.getnode()
+ result = node.getchar(self.index)
+ self.index += 1
return result
def nextunichar(self):
- node = self.node
- if node is None:
- node = self.nextnode()
- result = self.node.getunichar(self.index)
- self.advance_index()
+ node = self.getnode()
+ result = node.getunichar(self.index)
+ self.index += 1
return result
def nextint(self):
- node = self.node
- if node is None:
- node = self.nextnode()
- result = self.node.getint(self.index)
- self.advance_index()
+ node = self.getnode()
+ result = node.getint(self.index)
+ self.index += 1
return result
def seekforward(self, numchars):
@@ -1019,36 +1035,42 @@
self.index += numchars
return
numchars -= self.nodelength - self.index
- while 1:
- node = self.iter.next()
- length = node.length()
- if length <= numchars:
- numchars -= length
- else:
- self.index = numchars
- self.node = node
- self.nodelength = node.length()
- return
+ while self.stack:
+ tookleft = self.tookleft.pop()
+ if tookleft:
+ node = self.stack[-1]
+ assert isinstance(node, BinaryConcatNode)
+ right = node.right
+ if right.length() > numchars:
+ break
+ numchars -= right.length()
+ self.stack.pop()
+ else:
+ raise StopIteration
+ self.tookleft.append(False)
+ self.find_downward(right, numchars)
+
def seekback(self, numchars):
if numchars <= self.index:
self.index -= numchars
- if self.node is None:
- self.iter.seekback()
- self.node = self.iter.next()
return
numchars -= self.index
- self.iter.seekback() # for first item
- while 1:
- node = self.iter.seekback()
- length = node.length()
- if length < numchars:
- numchars -= length
- else:
- self.index = length - numchars
- self.node = self.iter.next()
- self.nodelength = self.node.length()
- return
+ while self.stack:
+ tookleft = self.tookleft.pop()
+ if not tookleft:
+ node = self.stack[-1]
+ assert isinstance(node, BinaryConcatNode)
+ left = node.left
+ if left.length() >= numchars:
+ break
+ numchars -= left.length()
+ self.stack.pop()
+ else:
+ raise StopIteration
+ self.tookleft.append(True)
+ self.find_downward(left, left.length() - numchars)
+
class FindIterator(object):
def __init__(self, node, sub, start=0, stop=-1):
Modified: pypy/dist/pypy/rlib/test/test_rope.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_rope.py (original)
+++ pypy/dist/pypy/rlib/test/test_rope.py Sun Dec 2 21:05:08 2007
@@ -391,8 +391,6 @@
for j in range(len(result) - 1):
for i in range(len(result) - 1 - j):
iter = SeekableItemIterator(rope)
-# if (j, i) == (3, 1):
-# import pdb; pdb.set_trace()
for c in result[:j]:
c2 = iter.nextchar()
assert c2 == c
More information about the pypy-svn
mailing list