Mercurial > cgi-bin > hgweb.cgi > curlyq
changeset 2:8884b0bf779d
Improve the efficiency.
author | David Barts <n5jrn@me.com> |
---|---|
date | Thu, 26 Dec 2019 13:18:53 -0800 |
parents | 173e86601dbc |
children | 091c03f1b2e8 |
files | workspace.py |
diffstat | 1 files changed, 27 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/workspace.py Thu Dec 26 12:00:03 2019 -0800 +++ b/workspace.py Thu Dec 26 13:18:53 2019 -0800 @@ -206,6 +206,7 @@ raise TypeError("offset must be an int") self.bounds = bounds self.offset = offset + self.delta = self.offset - self.bounds.start def __repr__(self): return "{0}({1!r}, {2!r})".format(self.__class__.__name__, self.bounds, self.offset) @@ -233,11 +234,10 @@ self._length = pos def _mapped(self, index): - mi = self._binsch(index) - m = None if mi is None else self._mmap[mi] - if m is None: + mmap_index = self._binsch(index) + if mmap_index is None: raise IndexError("index {0} out of range".format(index)) - return index - m.bounds.start + m.offset + return index + self._mmap[mmap_index].delta def _binsch(self, index): a = 0 @@ -260,13 +260,34 @@ # XXX - this is sorta brute-forced and could be more efficient def __getitem__(self, key): + # Trivial cases if isinstance(key, int): return self._get1(key) if not isinstance(key, slice): raise TypeError("expecting int or slice") + if key.step is not None: + raise ValueError("__getitem__ does not support steps in slices") + + # Loop up the starting segment. + mi = self._binsch(key.start) + if mi is None: + return "" + m = self._mmap[mi] + + # Horray! There's only one segment, so we can optimize. + if key.stop <= m.bounds.stop: + start = key.start + m.delta + stop = key.stop + m.delta + return self.indexable[start:stop] + + # The most involved (multi-segment) case. with io.StringIO() as buf: - for i in range(key.start, key.stop, key.step or 1): - buf.write(self._get1(i)) + for m in self._mmap[mi:]: + if m.bounds.start >= key.stop: + break + start = max(key.start, m.bounds.start) + m.delta + stop = min(key.stop, m.bounds.stop) + m.delta + buf.write(self.indexable[start:stop]) return buf.getvalue() def __len__(self):