source: mainline/tools/xstruct.py@ 77578e8

Last change on this file since 77578e8 was 8624d1f, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update some files that use shell-style comments

  • Property mode set to 100644
File size: 3.6 KB
Line 
1#
2# SPDX-FileCopyrightText: 2008 Martin Decky
3# SPDX-FileCopyrightText: 2011 Martin Sucha
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7"""
8Convert descriptive structure definitions to structure object
9"""
10
11import struct
12import sys
13import types
14
15# Handle long integer conversions nicely in both Python 2 and Python 3
16integer_types = (int, long) if sys.version < '3' else (int,)
17
18# Ensure that 's' format for struct receives correct data type depending
19# on Python version (needed due to different way to encode into bytes)
20ensure_string = \
21 (lambda value: value if type(value) is str else bytes(value)) \
22 if sys.version < '3' else \
23 (lambda value: bytes(value, 'ascii') if type(value) is str else value)
24
25ranges = {
26 'B': (integer_types, 0x00, 0xff),
27 'H': (integer_types, 0x0000, 0xffff),
28 'L': (integer_types, 0x00000000, 0xffffffff),
29 'Q': (integer_types, 0x0000000000000000, 0xffffffffffffffff),
30 'b': (integer_types, -0x80, 0x7f),
31 'h': (integer_types, -0x8000, 0x7fff),
32 'l': (integer_types, -0x80000000, 0x7fffffff) ,
33 'q': (integer_types, -0x8000000000000000, 0x7fffffffffffffff),
34}
35
36def check_range(varname, fmt, value):
37 if value == None:
38 raise ValueError('Variable "%s" not set' % varname)
39 if not fmt in ranges:
40 return
41 vartype, varmin, varmax = ranges[fmt]
42 if not isinstance(value, vartype):
43 raise ValueError('Variable "%s" is %s but should be %s' %
44 (varname, str(type(value)), str(vartype)))
45 if value < varmin or value > varmax:
46 raise ValueError('Variable "%s" value %s out of range %s..%s' %
47 (varname, repr(value), repr(varmin), repr(varmax)))
48
49class Struct:
50 def size(self):
51 return struct.calcsize(self._format_)
52
53 def pack(self):
54 args = []
55 for variable, fmt, length in self._args_:
56 value = self.__dict__[variable]
57 if isinstance(value, list):
58 if length != None and length != len(value):
59 raise ValueError('Variable "%s" length %u does not match %u' %
60 (variable, len(value), length))
61 for index, item in enumerate(value):
62 check_range(variable + '[' + repr(index) + ']', fmt, item)
63 args.append(item)
64 else:
65 if (fmt == "s"):
66 value = ensure_string(value)
67 check_range(variable, fmt, value)
68 args.append(value)
69 return struct.pack(self._format_, *args)
70
71 def unpack(self, data):
72 values = struct.unpack(self._format_, data)
73 i = 0
74 for variable, fmt, length in self._args_:
75 self.__dict__[variable] = values[i]
76 i += 1
77
78def create(definition):
79 "Create structure object"
80
81 tokens = definition.split(None)
82
83 # Initial byte order tag
84 format = {
85 "little:": lambda: "<",
86 "big:": lambda: ">",
87 "network:": lambda: "!"
88 }[tokens[0]]()
89 inst = Struct()
90 args = []
91
92 # Member tags
93 comment = False
94 variable = None
95 for token in tokens[1:]:
96 if (comment):
97 if (token == "*/"):
98 comment = False
99 continue
100
101 if (token == "/*"):
102 comment = True
103 continue
104
105 if (variable != None):
106 subtokens = token.split("[")
107
108 length = None
109 if (len(subtokens) > 1):
110 length = int(subtokens[1].split("]")[0])
111 format += "%d" % length
112
113 format += variable
114
115 inst.__dict__[subtokens[0]] = None
116 args.append((subtokens[0], variable, length))
117
118 variable = None
119 continue
120
121 if (token[0:8] == "padding["):
122 size = token[8:].split("]")[0]
123 format += "%dx" % int(size)
124 continue
125
126 variable = {
127 "char": lambda: "s",
128 "uint8_t": lambda: "B",
129 "uint16_t": lambda: "H",
130 "uint32_t": lambda: "L",
131 "uint64_t": lambda: "Q",
132
133 "int8_t": lambda: "b",
134 "int16_t": lambda: "h",
135 "int32_t": lambda: "l",
136 "int64_t": lambda: "q"
137 }[token]()
138
139 inst.__dict__['_format_'] = format
140 inst.__dict__['_args_'] = args
141 return inst
Note: See TracBrowser for help on using the repository browser.