148 lines
3.4 KiB
Python
148 lines
3.4 KiB
Python
|
from datetime import datetime
|
||
|
from .record import *
|
||
|
import abc
|
||
|
import ctypes
|
||
|
|
||
|
class ProgressGetter(object, metaclass=abc.ABCMeta):
|
||
|
@abc.abstractproperty
|
||
|
def current(self):
|
||
|
pass
|
||
|
@abc.abstractproperty
|
||
|
def total(self):
|
||
|
pass
|
||
|
|
||
|
@abc.abstractmethod
|
||
|
def progress(self):
|
||
|
raise NotImplementedError("getting the progess is not implemented")
|
||
|
|
||
|
class Reader(ProgressGetter):
|
||
|
@property
|
||
|
def current(self):
|
||
|
return float(self.stream.tell())
|
||
|
|
||
|
# returns the read progress in percent
|
||
|
def progress(self):
|
||
|
if self.total <= 0:
|
||
|
return 1.0
|
||
|
|
||
|
return self.current / self.total
|
||
|
|
||
|
@property
|
||
|
def total(self):
|
||
|
return self._total
|
||
|
|
||
|
def __init__(self, file):
|
||
|
self.stream = file
|
||
|
|
||
|
# find file size
|
||
|
self.stream.seek(0, 2)
|
||
|
self._total = self.stream.tell()
|
||
|
self.stream.seek(0, 0)
|
||
|
|
||
|
def skip(self, n):
|
||
|
self.stream.read(n)
|
||
|
|
||
|
def read_uint(self):
|
||
|
temp = self.stream.read(4)
|
||
|
if len(temp) != 4:
|
||
|
return None
|
||
|
|
||
|
return int(temp[3]) | int(temp[2]) << 8 | int(temp[1]) << 16 | int(temp[0]) << 24
|
||
|
|
||
|
def read_ushort(self):
|
||
|
temp = self.stream.read(2)
|
||
|
if len(temp) != 2:
|
||
|
return None
|
||
|
|
||
|
return int(temp[1]) | int(temp[0]) << 8
|
||
|
|
||
|
def read_short(self):
|
||
|
temp = self.read_ushort()
|
||
|
|
||
|
if temp == None:
|
||
|
return None
|
||
|
|
||
|
return ctypes.c_short(temp).value
|
||
|
|
||
|
def read_int(self):
|
||
|
temp = self.read_uint()
|
||
|
|
||
|
if temp == None:
|
||
|
return None
|
||
|
|
||
|
return ctypes.c_int(temp).value
|
||
|
|
||
|
def read_double(self):
|
||
|
temp = self.stream.read(8)
|
||
|
if len(temp) != 8:
|
||
|
return None
|
||
|
|
||
|
result = 0
|
||
|
|
||
|
for i in temp:
|
||
|
if int(i) != 0:
|
||
|
# read double
|
||
|
for j in range(1,8):
|
||
|
result += float(temp[j])/(2.0**(j*8))
|
||
|
|
||
|
exp = int(temp[0]) & 0x7F
|
||
|
exp -= 64
|
||
|
result *= 16**exp
|
||
|
|
||
|
if int(temp[0]) & 0x80:
|
||
|
result += -1
|
||
|
|
||
|
return result
|
||
|
|
||
|
|
||
|
# double is Zero
|
||
|
return 0
|
||
|
|
||
|
def read_ascii(self, len):
|
||
|
# removes zero terminators
|
||
|
# as well as trailing and beginning whitespaces
|
||
|
return self.stream.read(len).decode("ASCII").replace("\x00", "").strip()
|
||
|
|
||
|
def read_record(self):
|
||
|
result = Record()
|
||
|
try:
|
||
|
result.len = self.read_ushort()
|
||
|
result.ident = Records(self.read_ushort())
|
||
|
except ValueError:
|
||
|
return None
|
||
|
|
||
|
result.len -= 4 # remove record header len
|
||
|
|
||
|
return result
|
||
|
|
||
|
def read_date(self):
|
||
|
# date
|
||
|
year = self.read_ushort()
|
||
|
month = self.read_ushort()
|
||
|
day = self.read_ushort()
|
||
|
|
||
|
# time
|
||
|
hour = self.read_ushort()
|
||
|
minute = self.read_ushort()
|
||
|
second = self.read_ushort()
|
||
|
|
||
|
return datetime(year=year, month=month, day=day, hour=hour, minute=minute, second=second)
|
||
|
|
||
|
def read_coord(self):
|
||
|
X = self.read_int()
|
||
|
Y = self.read_int()
|
||
|
|
||
|
return (X,Y)
|
||
|
|
||
|
def read_coords(self, len):
|
||
|
len /= 8
|
||
|
result = []
|
||
|
while len > 0:
|
||
|
point = self.read_coord()
|
||
|
if not point:
|
||
|
return None
|
||
|
|
||
|
result.append(point)
|
||
|
len -= 1
|
||
|
|
||
|
return result
|