Mercurial > cgi-bin > hgweb.cgi > curlyq
comparison workspace.py @ 2:8884b0bf779d
Improve the efficiency.
author | David Barts <n5jrn@me.com> |
---|---|
date | Thu, 26 Dec 2019 13:18:53 -0800 |
parents | 173e86601dbc |
children | 091c03f1b2e8 |
comparison
equal
deleted
inserted
replaced
1:173e86601dbc | 2:8884b0bf779d |
---|---|
204 raise TypeError("bounds must be a Bounds object") | 204 raise TypeError("bounds must be a Bounds object") |
205 if not isinstance(offset, int): | 205 if not isinstance(offset, int): |
206 raise TypeError("offset must be an int") | 206 raise TypeError("offset must be an int") |
207 self.bounds = bounds | 207 self.bounds = bounds |
208 self.offset = offset | 208 self.offset = offset |
209 self.delta = self.offset - self.bounds.start | |
209 | 210 |
210 def __repr__(self): | 211 def __repr__(self): |
211 return "{0}({1!r}, {2!r})".format(self.__class__.__name__, self.bounds, self.offset) | 212 return "{0}({1!r}, {2!r})".format(self.__class__.__name__, self.bounds, self.offset) |
212 | 213 |
213 class SegmentedView(object): | 214 class SegmentedView(object): |
231 pos += r.stop - r.start | 232 pos += r.stop - r.start |
232 self._mmap.append(Mapping(Bounds(opos, pos), r.start)) | 233 self._mmap.append(Mapping(Bounds(opos, pos), r.start)) |
233 self._length = pos | 234 self._length = pos |
234 | 235 |
235 def _mapped(self, index): | 236 def _mapped(self, index): |
236 mi = self._binsch(index) | 237 mmap_index = self._binsch(index) |
237 m = None if mi is None else self._mmap[mi] | 238 if mmap_index is None: |
238 if m is None: | |
239 raise IndexError("index {0} out of range".format(index)) | 239 raise IndexError("index {0} out of range".format(index)) |
240 return index - m.bounds.start + m.offset | 240 return index + self._mmap[mmap_index].delta |
241 | 241 |
242 def _binsch(self, index): | 242 def _binsch(self, index): |
243 a = 0 | 243 a = 0 |
244 z = len(self._mmap) - 1 | 244 z = len(self._mmap) - 1 |
245 while a <= z: | 245 while a <= z: |
258 raise TypeError("__setitem__ only supports integers") | 258 raise TypeError("__setitem__ only supports integers") |
259 self.indexable[self._mapped(key)] = value | 259 self.indexable[self._mapped(key)] = value |
260 | 260 |
261 # XXX - this is sorta brute-forced and could be more efficient | 261 # XXX - this is sorta brute-forced and could be more efficient |
262 def __getitem__(self, key): | 262 def __getitem__(self, key): |
263 # Trivial cases | |
263 if isinstance(key, int): | 264 if isinstance(key, int): |
264 return self._get1(key) | 265 return self._get1(key) |
265 if not isinstance(key, slice): | 266 if not isinstance(key, slice): |
266 raise TypeError("expecting int or slice") | 267 raise TypeError("expecting int or slice") |
268 if key.step is not None: | |
269 raise ValueError("__getitem__ does not support steps in slices") | |
270 | |
271 # Loop up the starting segment. | |
272 mi = self._binsch(key.start) | |
273 if mi is None: | |
274 return "" | |
275 m = self._mmap[mi] | |
276 | |
277 # Horray! There's only one segment, so we can optimize. | |
278 if key.stop <= m.bounds.stop: | |
279 start = key.start + m.delta | |
280 stop = key.stop + m.delta | |
281 return self.indexable[start:stop] | |
282 | |
283 # The most involved (multi-segment) case. | |
267 with io.StringIO() as buf: | 284 with io.StringIO() as buf: |
268 for i in range(key.start, key.stop, key.step or 1): | 285 for m in self._mmap[mi:]: |
269 buf.write(self._get1(i)) | 286 if m.bounds.start >= key.stop: |
287 break | |
288 start = max(key.start, m.bounds.start) + m.delta | |
289 stop = min(key.stop, m.bounds.stop) + m.delta | |
290 buf.write(self.indexable[start:stop]) | |
270 return buf.getvalue() | 291 return buf.getvalue() |
271 | 292 |
272 def __len__(self): | 293 def __len__(self): |
273 return self._length | 294 return self._length |
274 | 295 |