-
Notifications
You must be signed in to change notification settings - Fork 12
/
parse.py
58 lines (50 loc) · 2.34 KB
/
parse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import array
from qtypes import TranslateType, q_str, types, q_none
class Parser:
def __init__(self,types):
self.types=types
# Defines order of type code lookup (important for types like q_str that are sub_types of a type already used for translation)
self.type_order = ['char','symbol','month','date','minute','second','time','datetime','int','long','float','bool','real','short','byte','dict','flip','table']
def update_types(self):
self.read_byte = types['byte'].read_data
self.write_byte = types['byte'].write_data
self.read_integer = types['int'].read_data
self.write_integer = types['int'].write_data
self.read_symbol = types['symbol'].read_data
self.write_symbol = types['symbol'].write_data
self._type_dict = dict(map(lambda x:(x.type,x),self.types.itervalues()))
self._type_preferences = [(x.type,x) for x in map(self.types.get,self.type_order)]
self.code_dict = dict(map(lambda x:(x.list_code,x),self.types.itervalues()))
def type(self,x):
if isinstance(x,q_none): return self.code_dict[x.code]
if isinstance(x,list) or (isinstance(x,q_str) and not x.is_char): return self.types['list']
if isinstance(x,self.types['table'].type):
return self.type(x._data)
t = self._type_dict.get(type(x))
if t: return t
for (inherited_type,t) in self._type_preferences:
if isinstance(x,inherited_type): return t
return TranslateType()
def read(self,endianness,offset,bytes):
(t,offset) = self.read_byte(endianness,offset,bytes)
if t < 0 or t == 98 or t == 99:
return self.code_dict[abs(t)].read_data(endianness,offset,bytes)
elif t > 0 and t < 98:
return self.types['list'].overwrite_read(self.code_dict[t].read_data,t,endianness,offset,bytes)
elif t is 0:
return self.types['list'].overwrite_read(self.read,t,endianness,offset,bytes)
else:
(v,offset) = self.read_byte(endianness,offset,bytes)
if t == 101 and v == 0: return (None,offset)
else: return ("func",len(bytes))
def write(self,val,message=None):
if message is None: message = array.array('b')
val = self.types['list'].type.convert_sequence(val)
t = self.type(val)
if t.code is 0:
t_code = val.type.list_code
else:
t_code = t.code
message.fromstring(parser.write_byte(t_code))
return t.write_data(val,message)
parser = Parser(types)