diff options
Diffstat (limited to '')
-rw-r--r-- | portato/eix/libeix.pyx | 116 |
1 files changed, 102 insertions, 14 deletions
diff --git a/portato/eix/libeix.pyx b/portato/eix/libeix.pyx index 2b3ebb0..2a1c7df 100644 --- a/portato/eix/libeix.pyx +++ b/portato/eix/libeix.pyx @@ -1,14 +1,102 @@ -from portato.eix.eix_utils cimport File, fopen, fclose, ffree, fget - -def test (f): - cdef File* cf - cdef char* buf - - print "Trying to open: ", f - cf = fopen(f, "r") - try: - buf = fget(cf, 20) - print "The first two chars:", buf[0], buf[1] - ffree(buf) - finally: - fclose(cf) +class EixError (Exception): + message = "Unknown error." + + def __str__ (self): + return self.message + +class EndOfFileException (EixError): + + def __init__ (self, filename): + self.message = "End of file reached though it was not expected: '%s'" % filename + +class EixReaderClosed (EixError): + message = "EixReader is already closed." + +class UnsupportedVersionError (EixError): + + def __init__ (self, version): + self.message = "Version '%s' is not supported." % version + +cdef class EixReader (object): + cdef object file + cdef char closed + + cdef readonly object filename + cdef readonly object version + + supported_versions = (28, ) + + def __init__ (self, filename): + self.filename = filename + self.file = open(filename, "r") + self.closed = 0 + + self.version = self._get_number() + + if self.version not in self.supported_versions: + raise UnsupportedVersionError(self.version) + + cdef unsigned long _get_number (self) except *: + cdef unsigned char n + cdef short count, i + cdef unsigned long value + cdef char* rest + cdef object orest + + n = self._get_one_byte() + + if n < 0xFF: + value = n + else: + count = 0 + + while (n == 0xFF): + count += 1 + n = self._get_one_byte() + + if n == 0: + n = 0xFF # 0xFF is encoded as 0xFF 0x00 + count -= 1 + + value = n << (count*8) + + if count > 0: + orest = self.get_string(count) + rest = orest # cast to char* + + for 0 <= i < count: + value += (<unsigned char>rest[i]) << ((count - i - 1)*8) + + return value + + cdef unsigned char _get_one_byte (self) except? 0: + s = self.file.read(1) + + if len(s) != 1: + raise EndOfFileException, self.filename + + return ord(s) + + cdef object _get_string (self, length): + if self.closed: + raise EixReaderClosed + + s = self.file.read(length) + + if len(s) != length: + raise EndOfFileException, self.filename + + return s + + def get_number (self): + if self.closed: + raise EixReaderClosed + + return self._get_number() + + def close (self): + if self.closed: + raise EixReaderClosed + + self.file.close() + self.closed = 1 |