# HG changeset patch # User Paul Boddie # Date 1252774103 -7200 # Node ID 76bd0bcfa998cf54b8de031b82ff1db309699442 # Parent 0cd36671c34eaafa644a3186437ededc50dcd4a9 Attempted to provide cache navigation without slicing the cache all the time. diff -r 0cd36671c34e -r 76bd0bcfa998 iixr.py --- a/iixr.py Sat Sep 12 01:52:23 2009 +0200 +++ b/iixr.py Sat Sep 12 18:48:23 2009 +0200 @@ -199,8 +199,12 @@ def __init__(self, f): File.__init__(self, f) + self.reset_cache() + + def reset_cache(self): self.cache = "" self.cache_length = 0 + self.cache_start = 0 def read_number(self): @@ -255,30 +259,56 @@ # Cache-affected methods. def read(self, n): - needed = n - self.cache_length + needed = n - (self.cache_length - self.cache_start) + + # Read the needed number of characters, if possible. + if needed > 0: s = self.f.read(max(needed, 1000)) self.cache += s self.cache_length += len(s) - s = self.cache[:n] - self.cache = self.cache[n:] - self.cache_length = len(self.cache) + # Get the end of the requested block. + + next_start = self.cache_start + n + s = self.cache[self.cache_start:next_start] + + # Reposition the pointer to the cache. + + self._seek_cache(len(s)) return s def tell(self): - return self.f.tell() - self.cache_length + return self.f.tell() - self.cache_length + self.cache_start def seek(self, offset): current = self.tell() self.f.seek(offset) + + # If seeking forward, attempt to navigate the cache. + if offset >= current: - discarded = offset - current - self.cache = self.cache[discarded:] + self._seek_cache(offset - current) + else: + self.reset_cache() + + def _seek_cache(self, delta): + next_start = self.cache_start + delta + + if next_start >= len(self.cache): + self.reset_cache() + + # If the cache is too big, resize it. + + elif next_start > 1000: + self.cache = self.cache[next_start:] self.cache_length = len(self.cache) + self.cache_start = 0 + + # Otherwise, just reference the next part of the cache. + else: - self.cache = "" - self.cache_length = 0 + self.cache_start = next_start class FileOpener: