Last active
December 10, 2020 04:49
-
-
Save chen3feng/59af2ed84e45851cf07c4984206b2f8a to your computer and use it in GitHub Desktop.
NamedStruct, a combinationof struct and namedtuple in python, make code more readable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
NamedStruct, a combinationof struct and namedtuple in python, make code more readable. | |
You can access the fields by name rather than index. | |
""" | |
from __future__ import print_function | |
import struct | |
from collections import namedtuple | |
_BYTE_ORDERS = ( | |
'native', 'little-endian', 'big-endian', 'network') | |
_TYPES = { | |
'char' : 'c', | |
'int8' : 'b', | |
'uint8' : 'B', | |
'bool' : '?', | |
'int16' : 'h', | |
'uint16' : 'H', | |
'int32' : 'i', | |
'uint32' : 'I', | |
'int64' : 'q', | |
'uint64' : 'Q', | |
'float' : 'f', | |
'double' : 'd', | |
'string' : 's', | |
'psacal_string' : 'p', | |
'pointer' : 'P', | |
} | |
class NamedStruct(object): | |
def __init__(self, name, fields, byteorder=''): | |
self.name = name | |
self.byteorder = byteorder | |
self.fields, self.names, self.format = self._parse(fields) | |
self._struct = struct.Struct(self.format) | |
self._namedtuple = namedtuple(self.name, self.names) | |
def sizeof(self): | |
return self._struct.size() | |
def pack(self, *args): | |
return self._struct.pack(*args) | |
def pack_into(self, buffer, offset, *args): | |
return self._struct.pack_into(buffer, offset, *args) | |
def unpack(self, string): | |
return self._namedtuple._make(self._struct.unpack(string)) | |
def unpack_from(self, buffer, offset=0): | |
return self._namedtuple._make(self._struct.unpack_from(buffer, offset)) | |
def __str__(self): | |
return 'struct %s {\n %s;\n}' % (self.name, ';\n '.join(self.fields)) | |
def _string_type_format(self, type): | |
type = type[len('string'):] | |
return type[1:-1] + _TYPES['string'] | |
def _parse(self, fields): | |
if isinstance(fields, str): | |
fields = [f.strip() for f in fields.split(';')] | |
format = self.byteorder | |
names = [] | |
for f in fields: | |
type, name = f.split() | |
if type.startswith('string'): | |
format += self._string_type_format(type) | |
else: | |
format += _TYPES[type] | |
names.append(name) | |
return fields, names, format | |
def main(): | |
record = 'raymond \x32\x12\x08\x01\x08' | |
Student = NamedStruct( | |
'Student', [ | |
'string<10> name', | |
'uint16 serialnumn', | |
'uint16 school', | |
'int8 gradelevel'], | |
byteorder='<') | |
print(Student) | |
student = Student.unpack(record) | |
print(student) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NamedStruct 让你可以用名字而不是下标来访问结构体成员,提高代码的可读性。
Origin from:
https://stackoverflow.com/questions/11461125/is-there-an-elegant-way-to-use-struct-and-namedtuple-instead-of-this