Skip to content

Commit c58f158

Browse files
committed
Add enum support to cstruct.parse
1 parent e0a1c93 commit c58f158

2 files changed

Lines changed: 25 additions & 14 deletions

File tree

cstruct/__init__.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
__date__ = '15 August 2013'
2929

3030
import struct
31-
from typing import Any, Dict, Optional, Type
31+
from typing import Any, Dict, Optional, Type, Union
3232
from .base import (
3333
LITTLE_ENDIAN,
3434
BIG_ENDIAN,
@@ -39,7 +39,7 @@
3939
C_TYPE_TO_FORMAT,
4040
CHAR_ZERO,
4141
)
42-
from .abstract import CStructMeta, AbstractCStruct
42+
from .abstract import CStructMeta, AbstractCStruct, AbstractCEnum
4343
from .cstruct import CStruct
4444
from .c_parser import parse_struct_def
4545
from .mem_cstruct import MemCStruct
@@ -52,6 +52,7 @@
5252
'CHAR_ZERO',
5353
'CStruct',
5454
'MemCStruct',
55+
'CEnum',
5556
'define',
5657
'undef',
5758
'getdef',
@@ -134,13 +135,13 @@ def sizeof(type_: str) -> int:
134135

135136
def parse(
136137
__struct__: str, __cls__: Optional[Type[AbstractCStruct]] = None, __name__: Optional[str] = None, **kargs: Dict[str, Any]
137-
) -> Optional[Type[AbstractCStruct]]:
138+
) -> Union[Type[AbstractCStruct], Type[AbstractCEnum], None]:
138139
"""
139-
Return a new class mapping a C struct/union definition.
140+
Return a new class mapping a C struct/union/enum definition.
140141
If the string does not contains any definition, return None.
141142
142143
Args:
143-
__struct__ (str): definition of the struct (or union) in C syntax
144+
__struct__ (str): definition of the struct (or union/enum) in C syntax
144145
__cls__ (type): super class - CStruct(default) or MemCStruct
145146
__name__ (str): name of the new class. If empty, a name based on the __struct__ hash is generated
146147
__byte_order__ (str): byte order, valid values are LITTLE_ENDIAN, BIG_ENDIAN, NATIVE_ORDER
@@ -154,5 +155,7 @@ def parse(
154155
cls_def = parse_struct_def(__struct__, __cls__=__cls__, **kargs)
155156
if cls_def is None:
156157
return None
158+
elif cls_def['__is_enum__']:
159+
return AbstractCEnum.parse(cls_def, __name__, **kargs)
157160
else:
158161
return __cls__.parse(cls_def, __name__, **kargs)

cstruct/c_parser.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
from .exceptions import CStructException, ParserError
3232

3333
if TYPE_CHECKING:
34-
from .abstract import AbstractCStruct, AbstractCEnum
34+
from .abstract import AbstractCStruct
3535

36-
__all__ = ['parse_struct', 'parse_struct_def', 'Tokens']
36+
__all__ = ['parse_struct', 'parse_struct_def', 'parse_enum_def', 'Tokens']
3737

3838

3939
class Tokens(object):
@@ -48,7 +48,7 @@ def __init__(self, text: str) -> None:
4848
_, name, value = line.strip().split(maxsplit=2)
4949
DEFINES[name] = c_eval(value)
5050
except Exception:
51-
raise ParserError("Parsing line {}".format(line))
51+
raise ParserError(f"Parsing line {line}")
5252
else:
5353
lines.append(line)
5454
text = " ".join(lines)
@@ -135,9 +135,8 @@ def parse_type(tokens: Tokens, __cls__: Type['AbstractCStruct'], byte_order: Opt
135135
try:
136136
ref = STRUCTS[tail]
137137
except KeyError:
138-
raise ParserError("Unknow {} {}".format(c_type, tail))
138+
raise ParserError(f"Unknown '{c_type}' '{tail}'")
139139
elif c_type.startswith('enum'):
140-
# from .abstract import AbstractCEnum
141140
from .cenum import CEnum
142141

143142
c_type, tail = c_type.split(' ', 1)
@@ -175,8 +174,10 @@ def parse_struct_def(
175174
if not tokens:
176175
return None
177176
kind = tokens.pop()
177+
if kind == 'enum':
178+
return parse_enum_def(__def__, **kargs)
178179
if kind not in ['struct', 'union']:
179-
raise ParserError("struct or union expected - {}".format(kind))
180+
raise ParserError("struct, union, or enum expected - {kind}")
180181
__is_union__ = kind == 'union'
181182
vtype = tokens.pop()
182183
if tokens.get() == '{': # Named nested struct
@@ -185,7 +186,7 @@ def parse_struct_def(
185186
elif vtype == '{': # Unnamed nested struct
186187
return parse_struct(tokens, __cls__=__cls__, __is_union__=__is_union__, __byte_order__=__byte_order__)
187188
else:
188-
raise ParserError("{} definition expected".format(vtype))
189+
raise ParserError(f"{vtype} definition expected")
189190

190191

191192
def parse_enum_def(__def__: Union[str, Tokens], **kargs: Any) -> Optional[Dict[str, Any]]:
@@ -242,7 +243,7 @@ def parse_enum(__enum__: Union[str, Tokens], **kargs: Any) -> Optional[Dict[str,
242243
break
243244

244245
if len(exp_elems) == 0:
245-
raise ParserError(f"enum is missing value expression")
246+
raise ParserError("enum is missing value expression")
246247

247248
int_expr = " ".join(exp_elems)
248249
try:
@@ -259,7 +260,12 @@ def parse_enum(__enum__: Union[str, Tokens], **kargs: Any) -> Optional[Dict[str,
259260
if next_token == "}":
260261
break
261262

262-
result = {'__constants__': constants}
263+
result = {
264+
'__constants__': constants,
265+
'__is_struct__': False,
266+
'__is_union__': False,
267+
'__is_enum__': True,
268+
}
263269
return result
264270

265271

@@ -325,7 +331,9 @@ def parse_struct(
325331
'__fields__': list(fields_types.keys()),
326332
'__fields_types__': fields_types,
327333
'__size__': size,
334+
'__is_struct__': not __is_union__,
328335
'__is_union__': __is_union__,
336+
'__is_enum__': False,
329337
'__byte_order__': __byte_order__,
330338
'__alignment__': max_alignment,
331339
}

0 commit comments

Comments
 (0)