Skip to content

Commit b2e37ed

Browse files
committed
cstruct.native_types and get_type added
1 parent 2d27fd3 commit b2e37ed

10 files changed

Lines changed: 367 additions & 47 deletions

File tree

cstruct/__init__.py

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@
2727
__version__ = '4.0'
2828
__date__ = '15 August 2013'
2929

30-
import struct
3130
from typing import Any, Dict, Optional, Type, Union
3231
from .base import (
3332
LITTLE_ENDIAN,
3433
BIG_ENDIAN,
3534
NATIVE_ORDER,
3635
STRUCTS,
36+
ENUMS,
3737
DEFINES,
3838
TYPEDEFS,
39-
C_TYPE_TO_FORMAT,
4039
CHAR_ZERO,
4140
)
4241
from .abstract import CStructMeta, AbstractCStruct, AbstractCEnum
4342
from .cstruct import CStruct
4443
from .c_parser import parse_struct_def
4544
from .mem_cstruct import MemCStruct
4645
from .cenum import CEnum
46+
from .native_types import get_native_type
4747

4848
__all__ = [
4949
'LITTLE_ENDIAN',
@@ -57,6 +57,7 @@
5757
'undef',
5858
'getdef',
5959
'typedef',
60+
'get_type',
6061
'sizeof',
6162
'parse',
6263
]
@@ -104,33 +105,62 @@ def typedef(type_: str, alias: str) -> None:
104105
TYPEDEFS[alias] = type_
105106

106107

107-
def sizeof(type_: str) -> int:
108+
def get_type(type_: str) -> Any:
108109
"""
109-
Return the size of the type.
110+
Get a data type (struct, union, enum) by name
111+
112+
Examples:
113+
>>> get_type("struct Position")
114+
<class 'abc.Position'>
115+
>>> get_type("enum htmlfont")
116+
<enum 'htmlfont'>
110117
111118
Args:
112-
type_: C type, struct or union (e.g. 'short int' or 'struct ZYZ')
119+
type_: C type, struct or union (e.g. 'short int' or 'struct ZYZ'), enum or native type
113120
114121
Returns:
115-
size: size in bytes
122+
class: data type class
116123
"""
117124
while type_ in TYPEDEFS:
118125
type_ = TYPEDEFS[type_]
119126
if isinstance(type_, CStructMeta):
120-
return len(type_)
127+
return type_
121128
elif type_.startswith('struct ') or type_.startswith('union '):
122129
kind, type_ = type_.split(' ', 1)
123-
t = STRUCTS.get(type_, None)
124-
if t is None:
125-
raise KeyError("Unknow %s \"%s\"" % (kind, type_))
126-
else:
127-
return t.sizeof()
130+
try:
131+
return STRUCTS[type_]
132+
except KeyError:
133+
raise KeyError(f"Unknown {kind} `{type_}`")
134+
elif type_.startswith('enum '):
135+
kind, type_ = type_.split(' ', 1)
136+
try:
137+
return ENUMS[type_]
138+
except KeyError:
139+
raise KeyError(f"Unknown {kind} `{type_}`")
128140
else:
129-
ttype = C_TYPE_TO_FORMAT.get(type_, None)
130-
if ttype is None:
131-
raise KeyError("Unknow type \"" + type_ + "\"")
132-
else:
133-
return struct.calcsize(ttype)
141+
return get_native_type(type_)
142+
143+
144+
def sizeof(type_: str) -> int:
145+
"""
146+
Return the size of the type.
147+
148+
Examples:
149+
>>> sizeof("struct Position")
150+
16
151+
>>> sizeof("int")
152+
4
153+
154+
Args:
155+
type_: C type, struct or union (e.g. 'short int' or 'struct ZYZ'), enum or native type
156+
157+
Returns:
158+
size: size in bytes
159+
"""
160+
while type_ in TYPEDEFS:
161+
type_ = TYPEDEFS[type_]
162+
data_type = get_type(type_)
163+
return data_type.sizeof()
134164

135165

136166
def parse(

cstruct/base.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
'STRUCTS',
3636
'DEFINES',
3737
'TYPEDEFS',
38-
'C_TYPE_TO_FORMAT',
3938
'CHAR_ZERO',
39+
'DEFAULT_ENUM_SIZE',
4040
]
4141

4242
LITTLE_ENDIAN = '<'
@@ -68,32 +68,8 @@
6868
'uint64_t': 'uint64',
6969
}
7070

71-
C_TYPE_TO_FORMAT: Dict[str, str] = {
72-
'char': 's',
73-
'signed char': 'b',
74-
'unsigned char': 'B',
75-
'short': 'h',
76-
'unsigned short': 'H',
77-
'int': 'i',
78-
'unsigned int': 'I',
79-
'long': 'l',
80-
'unsigned long': 'L',
81-
'long long': 'q',
82-
'unsigned long long': 'Q',
83-
'float': 'f',
84-
'double': 'd',
85-
'void *': 'P',
86-
'int8': 'b',
87-
'uint8': 'B',
88-
'int16': 'h',
89-
'uint16': 'H',
90-
'int32': 'i',
91-
'uint32': 'I',
92-
'int64': 'q',
93-
'uint64': 'Q',
94-
}
95-
9671
ENUM_SIZE_TO_C_TYPE: Dict[int, str] = {1: 'int8', 2: 'int16', 4: 'int32', 8: 'int64'}
9772

9873
CHAR_ZERO = bytes('\0', 'ascii')
74+
9975
DEFAULT_ENUM_SIZE = 4

cstruct/field.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
import struct
2727
from enum import Enum
2828
from typing import Optional, Any, List, Type, TYPE_CHECKING
29-
from .base import NATIVE_ORDER, C_TYPE_TO_FORMAT, ENUM_SIZE_TO_C_TYPE
29+
from .base import NATIVE_ORDER, ENUM_SIZE_TO_C_TYPE
30+
from .native_types import get_native_type
3031
from .exceptions import ParserError
3132

3233
if TYPE_CHECKING:
@@ -188,12 +189,12 @@ def native_format(self) -> str:
188189
"Field format (struct library format)"
189190
if self.is_native:
190191
try:
191-
return C_TYPE_TO_FORMAT[self.c_type]
192+
return get_native_type(self.c_type).native_format
192193
except KeyError:
193-
raise ParserError("Unknow type {}".format(self.c_type))
194+
raise ParserError(f"Unknow type `{self.c_type}`")
194195
elif self.is_enum:
195196
try:
196-
return C_TYPE_TO_FORMAT[ENUM_SIZE_TO_C_TYPE[self.ref.size]]
197+
return get_native_type(ENUM_SIZE_TO_C_TYPE[self.ref.size]).native_format
197198
except KeyError:
198199
raise ParserError(f"Enum has invalid size. Needs to be in {ENUM_SIZE_TO_C_TYPE.keys()}")
199200
else:

0 commit comments

Comments
 (0)