blob: b699c5e4b090987a217df6ee84fa19bf019211b4 [file] [log] [blame]
Dan Talaycof75360a2010-02-05 22:22:54 -08001"""This module converts C types to Python struct pattern string.
2
3Date June 2009
4Created by ykk
5"""
6import cheader
7import struct
8
9class cstruct2py:
10 """Class converts C struct to Python struct pattern string
11
12 Date October 2009
13 Created by ykk
14 """
15 def __init__(self):
16 """Initialize
17 """
18 ##Mapping
19 self.structmap = {}
20 self.structmap["char"] = "c"
21 self.structmap["signed char"] = "b"
22 self.structmap["uint8_t"]=\
23 self.structmap["unsigned char"] = "B"
24 self.structmap["short"] = "h"
25 self.structmap["uint16_t"] =\
26 self.structmap["unsigned short"] = "H"
27 self.structmap["int"] = "i"
28 self.structmap["unsigned int"] = "I"
29 self.structmap["long"] = "l"
30 self.structmap["uint32_t"] =\
31 self.structmap["unsigned long"] = "L"
32 self.structmap["long long"] = "q"
33 self.structmap["uint64_t"] =\
34 self.structmap["unsigned long long"] = "Q"
35 self.structmap["float"] = "f"
36 self.structmap["double"] = "d"
37
38 def get_pattern(self,ctype):
39 """Get pattern string for ctype.
40 Return None if ctype is not expanded.
41 """
42 if (ctype.expanded):
43 if (isinstance(ctype, cheader.cprimitive)):
44 return self.structmap[ctype.typename]
45 elif (isinstance(ctype, cheader.cstruct)):
46 string=""
47 for member in ctype.members:
48 string += self.get_pattern(member)
49 return string
50 elif (isinstance(ctype, cheader.carray)):
51 if (ctype.size == 0):
52 return ""
53 else:
54 string = self.get_pattern(ctype.object)
55 return string * ctype.size
56 return None
57
58 def get_size(self, ctype, prefix="!"):
59 """Return size of struct or pattern specified
60 """
61 if (isinstance(ctype, str)):
62 return struct.calcsize(ctype)
63 elif (isinstance(ctype, cheader.ctype)):
64 return struct.calcsize(prefix + self.get_pattern(ctype))
65 else:
66 return 0
67
68class structpacker:
69 """Pack/unpack packets with ctype.
70
71 Date October 2009
72 Created by ykk
73 """
74 def __init__(self, prefix=""):
75 """Initialize with prefix to struct
76 """
77 ##Reference to prefix
78 self.prefix = prefix
79
80 def pack(self, ctype, *arg):
81 """Pack packet accordingly ctype or pattern provided.
82 Return struct packed.
83 """
84 if (isinstance(ctype, str)):
85 return struct.pack(self.prefix+ctype, *arg)
86 elif (isinstance(ctype, cheader.ctype)):
87 return struct.pack(self.prefix+cstruct2py.get_pattern(ctype),
88 *arg)
89 else:
90 return None
91
92 def unpack_from_front(self, ctype, binaryString, returnDictionary=True):
93 """Unpack packet using front of packet,
94 accordingly ctype or pattern provided.
95
96 Return (dictionary of values indexed by arg name,
97 remaining binary string) if ctype is cheader.ctype
98 and returnDictionary is True,
99 else return (array of data unpacked, remaining binary string).
100 """
101 pattern = ""
102 if (isinstance(ctype, str)):
103 pattern = ctype
104 elif (isinstance(ctype, cheader.ctype)):
105 pattern = cstruct2py.get_pattern(ctype)
106 else:
107 return None
108 dsize = struct.calcsize(pattern)
109
110 if (dsize > len(binaryString)):
111 return None
112
113 return (structpacker.peek_from_front(self, pattern, binaryString, returnDictionary),
114 binaryString[dsize:])
115
116 def peek_from_front(self, ctype, binaryString, returnDictionary=True):
117 """Unpack packet using front of packet,
118 accordingly ctype or pattern provided.
119
120 Return dictionary of values indexed by arg name,
121 if ctype is cheader.ctype and returnDictionary is True,
122 else return array of data unpacked.
123 """
124 pattern = self.prefix
125 if (isinstance(ctype, str)):
126 pattern += ctype
127 elif (isinstance(ctype, cheader.ctype)):
128 pattern += cstruct2py.get_pattern(ctype)
129 else:
130 return None
131 dsize = struct.calcsize(pattern)
132 if (dsize > len(binaryString)):
133 return None
134 data = struct.unpack(pattern, binaryString[0:dsize])
135
136 #Return values
137 if (isinstance(ctype, str) or
138 (not returnDictionary)):
139 return data
140 else:
141 return self.data2dic(data, ctype)
142
143 def data2dic(self,ctype,data):
144 """Convert data to dictionary
145 """
146 valDic = {}
147 names = ctype.get_names()
148 for name in names:
149 valDic[name] = []
150 for d in data:
151 name = names.pop(0)
152 valDic[name].append(d)
153 return valDic
154