blender-gdsimporter/gds/reader.py

148 lines
3.4 KiB
Python
Raw Normal View History

from datetime import datetime
from .record import *
import abc
2019-07-02 14:45:29 +02:00
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
2019-07-02 14:49:58 +02:00
@property
def total(self):
return self._total
def __init__(self, file):
self.stream = file
# find file size
self.stream.seek(0, 2)
2019-07-02 14:49:58 +02:00
self._total = self.stream.tell()
self.stream.seek(0, 0)
def skip(self, n):
self.stream.read(n)
2019-07-02 14:45:29 +02:00
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
2019-07-02 14:45:29 +02:00
def read_ushort(self):
temp = self.stream.read(2)
if len(temp) != 2:
return None
return int(temp[1]) | int(temp[0]) << 8
2019-07-02 14:45:29 +02:00
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):
2019-07-02 14:45:29 +02:00
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
2019-07-02 14:45:29 +02:00
# 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:
2019-07-02 14:45:29 +02:00
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
2019-07-02 14:45:29 +02:00
year = self.read_ushort()
month = self.read_ushort()
day = self.read_ushort()
# time
2019-07-02 14:45:29 +02:00
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