3333from io import BytesIO
3434from collections import OrderedDict
3535import json
36+ import typing
3637
3738try :
3839 from builtins import bytes as newbytes
@@ -88,6 +89,7 @@ def __repr__(self):
8889 return '<StructureType {name} +compiled>'
8990"""
9091
92+ #common regex values
9193COMMENT_MULTILINE = r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/'
9294COMMENT_INLINE = r'//[^\n]*'
9395COMMENT_MULTILINE_REPEATED = r'(^[ ]*(' + COMMENT_INLINE + r'|' + COMMENT_MULTILINE + r'([ ]*(' + COMMENT_INLINE + r'|' + COMMENT_MULTILINE + r'))*)[ \t\r]*\n?)*^[ ]*(' + COMMENT_INLINE + r'|(?P<commentBlock>' + COMMENT_MULTILINE + r'))+'
@@ -97,6 +99,12 @@ def __repr__(self):
9799#print(f"COMMENT_REGEX_START:{COMMENT_REGEX_START}")
98100#print(f"COMMENT_REGEX_END:{COMMENT_REGEX_END}")
99101
102+ #types
103+ typeCommentAttributes = dict [str ,str ]
104+ typeValuesDetails = dict [str ,dict [str ,typing .Union [str ,int ,typeCommentAttributes ]]]
105+ typeAll = typing .Union [str ,'PackedType' ,'CharType' ,'WcharType' ,'BytesInteger' ,'VoidType' ,'ArrayType' ,'StructureType' ,'EnumType' ]
106+ typeTypedefs = dict [str , typeAll ]
107+
100108class Error (Exception ):
101109 pass
102110
@@ -139,7 +147,7 @@ def __init__(self, endian='<', pointer='uint64'):
139147
140148 self .consts = {}
141149 self .lookups = {}
142- self .typedefs = {
150+ self .typedefs : typeTypedefs = {
143151 'byte' : 'int8' ,
144152 'ubyte' : 'uint8' ,
145153 'uchar' : 'uint8' ,
@@ -186,7 +194,7 @@ def __init__(self, endian='<', pointer='uint64'):
186194
187195 self .pointer = self .resolve (pointer )
188196
189- def addtype (self , name , t , replace = False ):
197+ def addtype (self , name : str , t : typeAll , replace = False ):
190198 """Add a type or type reference.
191199
192200 Args:
@@ -197,8 +205,7 @@ def addtype(self, name, t, replace=False):
197205 Raises:
198206 ValueError: If the type already exists.
199207 """
200- name = name .lower ()
201- if not replace and name .lower () in self .typedefs :
208+ if not replace and name in self .typedefs :
202209 raise ValueError ("Duplicate type: %s" % name )
203210
204211 self .typedefs [name ] = t
@@ -223,7 +230,7 @@ def load(self, s, deftype=None, **kwargs):
223230
224231 parser .parse (s )
225232
226- def loadfile (self , s , deftype = None , ** kwargs ):
233+ def loadfile (self , s : str , deftype : typing . Optional [ int ] = None , ** kwargs : typing . Union [ 'cstruct' , bool ] ):
227234 """Load structure definitions from a file.
228235
229236 The given path will be read and parsed using the .load() function.
@@ -268,25 +275,61 @@ def resolve(self, name):
268275 return t
269276
270277 for i in xrange (10 ):
271- if t . lower () not in self .typedefs :
278+ if t not in self .typedefs :
272279 raise ResolveError ("Unknown type %s" % name )
273280
274- t = self . typedefs [ t . lower () ]
281+ t = self [ t ]
275282
276283 if not isinstance (t , str ):
277284 return t
278285
279286 raise ResolveError ("Recursion limit exceeded while resolving type %s" % name )
280287
281288 def __getattr__ (self , attr ):
282- if attr . lower () in self .typedefs :
283- return self .typedefs [attr . lower () ]
289+ if attr in self .typedefs :
290+ return self .typedefs [attr ]
284291
285292 if attr in self .consts :
286293 return self .consts [attr ]
287294
295+ for enum in self .getEnumTypes ():
296+ for enumMember in enum .values .items ():
297+ if enumMember [0 ] == attr :
298+ return enumMember [1 ]
299+
300+
288301 raise AttributeError ("Invalid Attribute: %s" % attr )
289302
303+ def __getitem__ (self , item ):
304+ return self .__getattr__ (item )
305+
306+ def keys (self ):
307+ return self .typedefs .keys ()
308+
309+ def values (self ):
310+ return self .typedefs .values ()
311+
312+ def items (self ):
313+ return self .typedefs .items ()
314+
315+ def getEnumTypes (self ):
316+ retVal : list [EnumType ] = []
317+ allTypes = self .typedefs
318+ for currentType in allTypes .values ():
319+ if isinstance (currentType , EnumType ):
320+ retVal .append (currentType )
321+
322+ return retVal
323+
324+ def getStructTypes (self ):
325+ retVal : list [StructureType ] = []
326+ allTypes = self .typedefs
327+ for currentType in allTypes .values ():
328+ if isinstance (currentType , StructureType ):
329+ retVal .append (currentType )
330+
331+ return retVal
332+
290333
291334class Parser (object ):
292335 """Base class for definition parsers.
@@ -428,7 +471,7 @@ def _parse_fields_struct(self, s):
428471 COMMENT_REGEX_START + r'(?P<type>[^\s]+)\s+(?P<name>[^\s\[:]+)(\s*:\s*(?P<bits>\d+))?(\[(?P<count>[^;\n]*)\])?;' + COMMENT_REGEX_END ,
429472 s , re .MULTILINE
430473 )
431- r = []
474+ r : list [ StructureFieldType ] = []
432475 for f in fields :
433476 d = f .groupdict ()
434477 if d ['type' ].startswith ('//' ):
@@ -458,13 +501,13 @@ def _parse_fields_struct(self, s):
458501 d ['name' ] = d ['name' ][1 :]
459502 type_ = Pointer (self .cstruct , type_ )
460503
461- field = StructureField (d ['name' ], type_ , int (d ['bits' ]) if d ['bits' ] else None , commentAttributes = commentAttributes )
504+ field = StructureFieldType (d ['name' ], type_ , int (d ['bits' ]) if d ['bits' ] else None , commentAttributes = commentAttributes )
462505 r .append (field )
463506
464507 return r
465508
466509 def parse_comment_block (self ,s ):
467- commentAttributes = {}
510+ commentAttributes : typeCommentAttributes = {}
468511
469512 #parse the comment header
470513 if s is not None and s .startswith ('/*' ):
@@ -622,7 +665,7 @@ class Expression(object):
622665 ('<<' , lambda a , b : a << b ),
623666 ]
624667
625- def __init__ (self , cstruct , expr ):
668+ def __init__ (self , cstruct : cstruct , expr ):
626669 self .cstruct = cstruct
627670 self .expr = expr
628671
@@ -667,6 +710,11 @@ def evaluate_part(self, e, v):
667710 if e in self .cstruct .consts :
668711 return self .cstruct .consts [e ]
669712
713+ for enum in self .cstruct .getEnumTypes ():
714+ for enumMember in enum .values .items ():
715+ if enumMember [0 ] == e :
716+ return enumMember [1 ]
717+
670718 return int (e )
671719
672720 def __repr__ (self ):
@@ -778,9 +826,9 @@ def __call__(self, *args, **kwargs):
778826class RawType (BaseType ):
779827 """Base class for raw types that have a name and size."""
780828
781- def __init__ (self , cstruct , name = None , size = 0 ):
782- self .name = name
783- self .size = size
829+ def __init__ (self , cstruct , name : typing . Union [ str , None ] = None , size : int = 0 ):
830+ self .name : typing . Union [ str , None ] = name
831+ self .size : int = size
784832 super (RawType , self ).__init__ (cstruct )
785833
786834 def __len__ (self ):
@@ -796,12 +844,12 @@ def __repr__(self):
796844class StructureType (BaseType ):
797845 """Type class for structures."""
798846
799- def __init__ (self , cstruct , name , fields = None , commentAttributes = {}):
800- self .name = name
801- self .size = None
847+ def __init__ (self , cstruct , name : str , fields : list [ 'StructureFieldType' ] = [] , commentAttributes : typeCommentAttributes = {}):
848+ self .name : str = name
849+ self .size : typing . Union [ int , None ] = None
802850 self .lookup = OrderedDict ()
803- self .fields = fields if fields else []
804- self .commentAttributes = commentAttributes
851+ self .fields : list [ StructureFieldType ] = fields
852+ self .commentAttributes : typeCommentAttributes = commentAttributes
805853
806854
807855 for f in self .fields :
@@ -917,15 +965,15 @@ def _write(self, stream, data):
917965
918966 return num
919967
920- def add_fields (self , name , type_ , offset = None , commentAttributes = {}):
968+ def add_fields (self , name , type_ , offset = None , commentAttributes : typeCommentAttributes = {}):
921969 """Add a field to this structure.
922970
923971 Args:
924972 name: The field name.
925973 type_: The field type.
926974 offset: The field offset.
927975 """
928- field = StructureField (name , type_ , offset = offset , commentAttributes = commentAttributes )
976+ field = StructureFieldType (name , type_ , offset = offset , commentAttributes = commentAttributes )
929977 self .fields .append (field )
930978 self .lookup [name ] = field
931979 self .size = None
@@ -1023,15 +1071,15 @@ def reset(self):
10231071 self ._remaining = 0
10241072
10251073
1026- class StructureField (object ):
1074+ class StructureFieldType (object ):
10271075 """Holds a structure field."""
10281076
1029- def __init__ (self , name , type_ , bits = None , offset = None , commentAttributes = {}):
1030- self .name = name
1031- self .type = type_
1077+ def __init__ (self , name : str , type_ : typeAll , bits = None , offset : typing . Union [ int , None ] = None , commentAttributes : typeCommentAttributes = {}):
1078+ self .name : str = name
1079+ self .type : typeAll = type_
10321080 self .bits = bits
1033- self .offset = offset
1034- self .commentAttributes = commentAttributes
1081+ self .offset : typing . Union [ int , None ] = offset
1082+ self .commentAttributes : typeCommentAttributes = commentAttributes
10351083
10361084 def __repr__ (self ):
10371085 return '<Field {} {} {}>' .format (self .name , self .type , self .commentAttributes )
@@ -1048,8 +1096,8 @@ class ArrayType(BaseType):
10481096 x[expr] -> expr -> dynamic length.
10491097 """
10501098
1051- def __init__ (self , cstruct , type_ , count ):
1052- self .type = type_
1099+ def __init__ (self , cstruct , type_ : typeAll , count ):
1100+ self .type : typeAll = type_
10531101 self .count = count
10541102 self .dynamic = isinstance (self .count , Expression ) or self .count is None
10551103
@@ -1352,11 +1400,11 @@ class EnumType(RawType):
13521400 };
13531401 """
13541402
1355- def __init__ (self , cstruct , name , type_ , values , valuesDetails , commentAttributes = {}):
1356- self .type = type_
1357- self .values = values
1358- self .valuesDetails = valuesDetails
1359- self .commentAttributes = commentAttributes
1403+ def __init__ (self , cstruct , name : str , type_ : typeAll , values : dict [ str , int ], valuesDetails : typeValuesDetails , commentAttributes : typeCommentAttributes = {}):
1404+ self .type : typeAll = type_
1405+ self .values : dict [ str , int ] = values
1406+ self .valuesDetails : typeValuesDetails = valuesDetails
1407+ self .commentAttributes : typeCommentAttributes = commentAttributes
13601408 self .reverse = {}
13611409
13621410 for k , v in values .items ():
@@ -1449,10 +1497,10 @@ def __call__(self):
14491497 return self .value
14501498
14511499
1452- class Union (RawType ):
1500+ class UnionType (RawType ):
14531501 def __init__ (self , cstruct ):
14541502 self .cstruct = cstruct
1455- super (Union , self ).__init__ (cstruct )
1503+ super (UnionType , self ).__init__ (cstruct )
14561504
14571505 def _read (self , stream ):
14581506 raise NotImplementedError ()
0 commit comments