forked from HenryHu/pybbs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cstruct.py
119 lines (90 loc) · 2.75 KB
/
cstruct.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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from Util import Util
import struct
class CStruct(object):
def unpack(self, data):
Util.Unpack(self, self.parser.unpack(data))
def pack(self):
return self.parser.pack(*Util.Pack(self))
def __init__(self, data = None):
if (data == None):
Util.InitStruct(self)
else:
self.unpack(data)
class InmemStruct(object):
def __init__(self):
self.value = ['\0'] * self.size
def read(self, pos, len):
return "".join(self.value[pos:pos+len])
def write(self, pos, data):
self.value[pos:pos+len(data)] = list(data)
class Field(object):
def __init__(self):
self._parser = struct.Struct(self._format)
self._base = 0
def setbase(self, base):
self._base = base
def __get__(self, obj, objtype):
return self._parser.unpack(obj.read(self._base, self._parser.size))[0]
def __set__(self, obj, val):
obj.write(self._base, self._parser.pack(val))
@property
def size(self):
return self._parser.size
class I8(Field):
_format = '=b'
class U8(Field):
_format = '=B'
class I32(Field):
_format = '=i'
class U32(Field):
_format = '=I'
class FixStr(Field):
def __init__(self, len):
self._format = "%ds" % len
Field.__init__(self)
class Str(FixStr):
def __init__(self, len):
FixStr.__init__(self, len)
# no problem in __set__: auto pad 0
def __get__(self, obj, val):
return Util.CString(Field.__get__(self, obj, val))
class Array(object):
def __init__(self, childtype, count):
self.childtype = childtype
self.children = []
for i in range(0, count):
self.children.append(childtype())
self._base = 0
def __get__(self, obj, objtype):
# the point is to pass obj to __get__
return ArrayWithOwner(self, obj, objtype)
def setbase(self, base):
self._base = base
i = 0
for child in self.children:
child.setbase(base + child.size * i)
i += 1
@property
def size(self):
if (len(self.children) > 0):
return len(self.children) * self.children[0].size
else:
return 0
class ArrayWithOwner(object):
def __init__(self, array, obj, objtype):
self.array = array
self.obj = obj
self.objtype = objtype
def __getitem__(self, index):
return self.array.children[index].__get__(self.obj, self.objtype)
def __setitem__(self, index, val):
return self.array.children[index].__set__(self.obj, val)
@property
def _base(self):
return self.array._base
@property
def size(self):
return self.array.size
def init_fields(cls):
Util.InitFields(cls)
return cls