Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 1 | """This module generate Python code for C structs. |
| 2 | |
| 3 | Date January 2010 |
| 4 | Created by ykk |
| 5 | """ |
| 6 | import cheader |
| 7 | import c2py |
| 8 | import datetime |
| 9 | import struct |
| 10 | import re |
| 11 | from config import * |
| 12 | |
| 13 | def _space_to(n, str): |
| 14 | """ |
| 15 | Generate a string of spaces to achieve width n given string str |
| 16 | If length of str >= n, return one space |
| 17 | """ |
| 18 | spaces = n - len(str) |
| 19 | if spaces > 0: |
| 20 | return " " * spaces |
| 21 | return " " |
| 22 | |
| 23 | class rules: |
| 24 | """Class that specify rules for pythonization |
| 25 | |
| 26 | Date January 2010 |
| 27 | Created by ykk |
| 28 | """ |
| 29 | def __init__(self): |
| 30 | """Initialize rules |
| 31 | """ |
| 32 | ##Default values for members |
| 33 | self.default_values = {} |
| 34 | #Default values for struct |
| 35 | self.struct_default = {} |
| 36 | ##What is a tab |
| 37 | self.tab = " " |
| 38 | ##Macros to exclude |
| 39 | self.excluded_macros = [] |
| 40 | ##Enforce mapping |
| 41 | self.enforced_maps = {} |
| 42 | |
| 43 | def get_enforced_map(self, structname): |
| 44 | """Get code to enforce mapping |
| 45 | """ |
| 46 | code = [] |
| 47 | try: |
| 48 | mapping = self.enforced_maps[structname] |
| 49 | except KeyError: |
| 50 | return None |
| 51 | for (x,xlist) in mapping: |
| 52 | code.append("if (not (self."+x+" in "+xlist+")):") |
| 53 | code.append(self.tab+"return (False, \""+x+" must have values from "+xlist+"\")") |
| 54 | return code |
| 55 | |
| 56 | |
| 57 | def get_struct_default(self, structname, fieldname): |
| 58 | """Get code to set defaults for member struct |
| 59 | """ |
| 60 | try: |
| 61 | return "."+fieldname+self.struct_default[(structname, fieldname)] |
| 62 | except KeyError: |
| 63 | return None |
| 64 | |
| 65 | def get_default_value(self, structname, fieldname): |
| 66 | """Get default value for struct's field |
| 67 | """ |
| 68 | try: |
| 69 | return self.default_values[(structname, fieldname)] |
| 70 | except KeyError: |
| 71 | return 0 |
| 72 | |
| 73 | def include_macro(self, name): |
| 74 | """Check if macro should be included |
| 75 | """ |
| 76 | return not (name in self.excluded_macros) |
| 77 | |
| 78 | class pythonizer: |
| 79 | """Class that pythonize C structures |
| 80 | |
| 81 | Date January 2010 |
| 82 | Created by ykk |
| 83 | """ |
| 84 | def __init__(self, cheaderfile, pyrules = None, tab=" "): |
| 85 | """Initialize |
| 86 | """ |
| 87 | ##Rules |
| 88 | if (pyrules == None): |
| 89 | self.rules = rules() |
| 90 | else: |
| 91 | self.rules = pyrules |
| 92 | ##What is a tab (same as rules) |
| 93 | self.tab = str(tab) |
| 94 | self.rules.tab = self.tab |
| 95 | ##Reference to C header file |
| 96 | self.cheader = cheaderfile |
| 97 | ##Reference to cstruct2py |
| 98 | self.__c2py = c2py.cstruct2py() |
| 99 | ##Code for assertion |
| 100 | self.__assertcode = [] |
| 101 | |
| 102 | def pycode(self,preamble=None): |
| 103 | """Return pythonized code |
| 104 | """ |
| 105 | code = [] |
| 106 | code.append("import struct") |
| 107 | code.append("") |
| 108 | if (preamble != None): |
| 109 | fileRef = open(preamble,"r") |
| 110 | for l in fileRef: |
| 111 | code.append(l[:-1]) |
| 112 | fileRef.close() |
| 113 | code.append("# Structure definitions") |
| 114 | for name,struct in self.cheader.structs.items(): |
| 115 | code.extend(self.pycode_struct(struct)) |
| 116 | code.append("") |
| 117 | code.append("# Enumerated type definitions") |
| 118 | for name,enum in self.cheader.enums.items(): |
| 119 | code.extend(self.pycode_enum(name,enum)) |
| 120 | if GEN_ENUM_DICTIONARY: |
| 121 | code.extend(self.pycode_enum_map(name,enum)) |
| 122 | code.append("") |
| 123 | code.append("# Values from macro definitions") |
| 124 | for name,macro in self.cheader.macros.items(): |
| 125 | code.extend(self.pycode_macro(name)) |
| 126 | code.append("") |
| 127 | code.append("# Basic structure size definitions.") |
| 128 | if IGNORE_OFP_HEADER: |
| 129 | code.append("# Does not include ofp_header members.") |
| 130 | if IGNORE_ZERO_ARRAYS: |
| 131 | code.append("# Does not include variable length arrays.") |
| 132 | struct_keys = self.cheader.structs.keys() |
| 133 | struct_keys.sort() |
| 134 | for name in struct_keys: |
| 135 | struct = self.cheader.structs[name] |
| 136 | code.append(self.pycode_struct_size(name, struct)) |
Dan Talayco | ac1cb81 | 2010-02-06 20:34:18 -0800 | [diff] [blame] | 137 | if GEN_AUX_INFO: |
| 138 | self.gen_struct_map() |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 139 | |
| 140 | return code |
| 141 | |
| 142 | def pycode_enum(self, name, enum): |
| 143 | """Return Python array for enum |
| 144 | """ |
| 145 | code=[] |
| 146 | code.append(name+" = "+str(enum)) |
| 147 | ev = [] |
| 148 | for e in enum: |
| 149 | v = self.cheader.get_value(e) |
| 150 | ev.append(v) |
| 151 | code.append(e+"%s= "%_space_to(36,e)+str(v)) |
| 152 | if GEN_ENUM_VALUES_LIST: |
| 153 | code.append(name+"_values = "+str(ev)) |
| 154 | return code |
| 155 | |
| 156 | def pycode_enum_map(self, name, enum): |
| 157 | """Return Python dictionary for enum |
| 158 | """ |
| 159 | code = [] |
| 160 | code.append(name+"_map = {") |
| 161 | first = 1 |
| 162 | for e in enum: |
| 163 | v = self.cheader.get_value(e) |
| 164 | if first: |
| 165 | prev_e = e |
| 166 | prev_v = v |
| 167 | first = 0 |
| 168 | else: |
| 169 | code.append(self.tab + "'%s'%s: %s," % |
| 170 | (prev_e, _space_to(30, prev_e), prev_v)) |
| 171 | prev_e = e |
| 172 | prev_v = v |
| 173 | code.append(self.tab + "'%s'%s: %s" % |
| 174 | (prev_e, _space_to(30, prev_e), prev_v)) |
| 175 | code.append("}") |
| 176 | return code |
| 177 | |
| 178 | def pycode_macro(self,name): |
| 179 | """Return Python dict for macro |
| 180 | """ |
| 181 | code = [] |
| 182 | if (self.rules.include_macro(name)): |
| 183 | code.append(name+" = "+str(self.cheader.get_value(name))) |
| 184 | return code |
| 185 | |
| 186 | def pycode_struct_size(self, name, struct): |
| 187 | """Return one liner giving the structure size in bytes |
| 188 | """ |
| 189 | pattern = '!' + self.__c2py.get_pattern(struct) |
| 190 | bytes = self.__c2py.get_size(pattern) |
| 191 | code = name.upper() + "_BYTES = " + str(bytes) |
| 192 | return code |
| 193 | |
| 194 | def pycode_struct(self, struct_in): |
| 195 | """Return Python class code given C struct. |
| 196 | |
| 197 | Returns None if struct_in is not cheader.cstruct. |
| 198 | Else return list of strings that codes Python class. |
| 199 | """ |
| 200 | if (not isinstance(struct_in, cheader.cstruct)): |
| 201 | return None |
| 202 | |
| 203 | code=[] |
| 204 | self.__assertcode = [] |
| 205 | code.extend(self.codeheader(struct_in)) |
| 206 | code.extend(self.codeinit(struct_in)) |
| 207 | code.append("") |
| 208 | code.extend(self.codeassert(struct_in)) |
| 209 | code.append("") |
| 210 | code.extend(self.codepack(struct_in)) |
| 211 | code.append("") |
| 212 | code.extend(self.codeunpack(struct_in)) |
| 213 | code.append("") |
| 214 | code.extend(self.codelen(struct_in)) |
| 215 | code.append("") |
| 216 | if GEN_OBJ_EQUALITY: |
| 217 | code.extend(self.codeeq(struct_in)) |
| 218 | code.append("") |
| 219 | if GEN_OBJ_SHOW: |
| 220 | code.extend(self.codeshow(struct_in)) |
| 221 | code.append("") |
| 222 | return code |
| 223 | |
| 224 | def codeheader(self, struct_in): |
| 225 | """Return Python code for header |
| 226 | """ |
| 227 | code=[] |
| 228 | code.append("class "+struct_in.typename+":") |
| 229 | code.append(self.tab+"\"\"\"Automatically generated Python class for "+struct_in.typename) |
| 230 | code.append("") |
| 231 | code.append(self.tab+"Date "+str(datetime.date.today())) |
| 232 | code.append(self.tab+"Created by "+self.__module__+"."+self.__class__.__name__) |
| 233 | if IGNORE_OFP_HEADER: |
| 234 | code.append(self.tab+"Core structure: Messages do not include ofp_header") |
| 235 | if IGNORE_ZERO_ARRAYS: |
| 236 | code.append(self.tab+"Does not include var-length arrays") |
| 237 | code.append(self.tab+"\"\"\"") |
| 238 | return code |
| 239 | |
| 240 | def codeinit(self, struct_in): |
| 241 | """Return Python code for init function |
| 242 | """ |
| 243 | code = [] |
| 244 | code.append(self.tab+"def __init__(self):") |
| 245 | code.append(self.tab*2+"\"\"\"Initialize") |
| 246 | code.append(self.tab*2+"Declare members and default values") |
| 247 | code.append(self.tab*2+"\"\"\"") |
| 248 | code.extend(self.codemembers(struct_in,self.tab*2+"self")) |
| 249 | return code |
| 250 | |
| 251 | def codemembers(self, struct_in, prepend=""): |
| 252 | """Return members of class |
| 253 | """ |
| 254 | code = [] |
| 255 | for member in struct_in.members: |
| 256 | if (isinstance(member, cheader.cstruct)): |
| 257 | code.append(prepend+"."+member.name+" = "+member.typename+"()") |
| 258 | struct_default = self.rules.get_struct_default(struct_in.typename, member.name) |
| 259 | if (struct_default != None): |
| 260 | code.append(prepend+struct_default) |
| 261 | self.__structassert(member, (prepend+"."+member.name).strip()) |
| 262 | elif (isinstance(member, cheader.carray)): |
| 263 | if (member.typename == "char"): |
| 264 | initvalue = "\"\"" |
| 265 | self.__stringassert(member, (prepend+"."+member.name).strip()) |
| 266 | else: |
| 267 | if (isinstance(member.object, cheader.cprimitive)): |
| 268 | initvalue="0" |
| 269 | else: |
| 270 | initvalue="None" |
| 271 | initvalue=(initvalue+",")*member.size |
| 272 | initvalue="["+initvalue[:-1]+"]" |
| 273 | self.__arrayassert(member, (prepend+"."+member.name).strip()) |
| 274 | code.append(prepend+"."+member.name+"= "+initvalue) |
| 275 | else: |
| 276 | code.append(prepend+"."+member.name+" = "+ |
| 277 | str(self.rules.get_default_value(struct_in.typename, member.name))) |
| 278 | return code |
| 279 | |
Dan Talayco | ac1cb81 | 2010-02-06 20:34:18 -0800 | [diff] [blame] | 280 | def gen_struct_map(self): |
| 281 | print |
| 282 | print "# Class to array member map" |
| 283 | print "class_to_members_map = {" |
| 284 | for name, struct in self.cheader.structs.items(): |
| 285 | if not len(struct.members): |
| 286 | continue |
| 287 | s = " '" + name + "'" |
| 288 | print s + _space_to(36, s) + ": [" |
| 289 | prev = None |
| 290 | for member in struct.members: |
| 291 | if re.search('pad', member.name): |
| 292 | continue |
| 293 | if prev: |
| 294 | print _space_to(39, "") + "'" + prev + "'," |
| 295 | prev = member.name |
| 296 | print _space_to(39, "") + "'" + prev + "'" |
| 297 | print _space_to(38, "") + "]," |
| 298 | print " '_ignore' : []" |
| 299 | print "}" |
| 300 | |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 301 | def __structassert(self, cstruct, cstructname): |
| 302 | """Return code to check for C array |
| 303 | """ |
| 304 | self.__assertcode.append(self.tab*2+"if(not isinstance("+cstructname+", "+cstruct.typename+")):") |
| 305 | self.__assertcode.append(self.tab*3+"return (False, \""+cstructname+" is not class "+cstruct.typename+" as expected.\")") |
| 306 | |
| 307 | def __addassert(self, prefix): |
| 308 | code = [] |
| 309 | code.append(prefix+"if(not self.__assert()[0]):") |
| 310 | code.append(prefix+self.tab+"return None") |
| 311 | return code |
| 312 | |
| 313 | def __stringassert(self, carray, carrayname): |
| 314 | """Return code to check for C array |
| 315 | """ |
| 316 | self.__assertcode.append(self.tab*2+"if(not isinstance("+carrayname+", str)):") |
| 317 | self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not string as expected.\")") |
| 318 | self.__assertcode.append(self.tab*2+"if(len("+carrayname+") > "+str(carray.size)+"):") |
| 319 | self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not of size "+str(carray.size)+" as expected.\")") |
| 320 | |
| 321 | def __arrayassert(self, carray, carrayname): |
| 322 | """Return code to check for C array |
| 323 | """ |
| 324 | if (carray.size == 0): |
| 325 | return |
| 326 | self.__assertcode.append(self.tab*2+"if(not isinstance("+carrayname+", list)):") |
| 327 | self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not list as expected.\")") |
| 328 | self.__assertcode.append(self.tab*2+"if(len("+carrayname+") != "+str(carray.size)+"):") |
| 329 | self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not of size "+str(carray.size)+" as expected.\")") |
| 330 | |
| 331 | def codeassert(self, struct_in): |
| 332 | """Return code for sanity checking |
| 333 | """ |
| 334 | code = [] |
| 335 | code.append(self.tab+"def __assert(self):") |
| 336 | code.append(self.tab*2+"\"\"\"Sanity check") |
| 337 | code.append(self.tab*2+"\"\"\"") |
| 338 | enforce = self.rules.get_enforced_map(struct_in.typename) |
| 339 | if (enforce != None): |
| 340 | for line in enforce: |
| 341 | code.append(self.tab*2+line) |
| 342 | code.extend(self.__assertcode) |
| 343 | code.append(self.tab*2+"return (True, None)") |
| 344 | return code |
| 345 | |
| 346 | def codepack(self, struct_in, prefix="!"): |
| 347 | """Return code that pack struct |
| 348 | """ |
| 349 | code = [] |
| 350 | code.append(self.tab+"def pack(self, assertstruct=True):") |
| 351 | code.append(self.tab*2+"\"\"\"Pack message") |
| 352 | code.append(self.tab*2+"Packs empty array used as placeholder") |
| 353 | code.append(self.tab*2+"\"\"\"") |
| 354 | code.append(self.tab*2+"if(assertstruct):") |
| 355 | code.extend(self.__addassert(self.tab*3)) |
| 356 | code.append(self.tab*2+"packed = \"\"") |
| 357 | primPattern = "" |
| 358 | primMemberNames = [] |
| 359 | for member in struct_in.members: |
| 360 | if (isinstance(member, cheader.cprimitive)): |
| 361 | #Primitives |
| 362 | primPattern += self.__c2py.structmap[member.typename] |
| 363 | primMemberNames.append("self."+member.name) |
| 364 | else: |
| 365 | (primPattern, primMemberNames) = \ |
| 366 | self.__codepackprimitive(code, primPattern, |
| 367 | primMemberNames, prefix) |
| 368 | if (isinstance(member, cheader.cstruct)): |
| 369 | #Struct |
| 370 | code.append(self.tab*2+"packed += self."+member.name+".pack()") |
| 371 | elif (isinstance(member, cheader.carray) and member.typename == "char"): |
| 372 | #String |
| 373 | code.append(self.tab*2+"packed += self."+member.name+".ljust("+\ |
| 374 | str(member.size)+",'\\0')") |
| 375 | elif (isinstance(member, cheader.carray) and \ |
| 376 | isinstance(member.object, cheader.cprimitive)): |
| 377 | #Array of Primitives |
| 378 | expandedarr = "" |
| 379 | if (member.size != 0): |
| 380 | for x in range(0, member.size): |
| 381 | expandedarr += ", self."+member.name+"["+\ |
| 382 | str(x).strip()+"]" |
| 383 | code.append(self.tab*2+"packed += struct.pack(\""+prefix+\ |
| 384 | self.__c2py.structmap[member.object.typename]*member.size+\ |
| 385 | "\""+expandedarr+")") |
| 386 | else: |
| 387 | code.append(self.tab*2+"for i in self."+member.name+":") |
| 388 | code.append(self.tab*3+"packed += struct.pack(\""+\ |
| 389 | prefix+self.__c2py.get_pattern(member.object)+\ |
| 390 | "\",i)") |
| 391 | elif (isinstance(member, cheader.carray) and \ |
| 392 | isinstance(member.object, cheader.cstruct)): |
| 393 | #Array of struct |
| 394 | if (member.size != 0): |
| 395 | for x in range(0, member.size): |
| 396 | code.append(self.tab*2+"packed += self."+member.name+"["+\ |
| 397 | str(x).strip()+"].pack()") |
| 398 | else: |
| 399 | code.append(self.tab*2+"for i in self."+member.name+":") |
| 400 | code.append(self.tab*3+"packed += i.pack(assertstruct)") |
| 401 | #Clear remaining fields |
| 402 | (primPattern, primMemberNames) = \ |
| 403 | self.__codepackprimitive(code, primPattern, |
| 404 | primMemberNames, prefix) |
| 405 | code.append(self.tab*2+"return packed") |
| 406 | return code |
| 407 | |
| 408 | def __codepackprimitive(self, code, primPattern, primMemberNames, prefix): |
| 409 | """Return code for packing primitives |
| 410 | """ |
| 411 | if (primPattern != ""): |
| 412 | #Clear prior primitives |
| 413 | code.append(self.tab*2+"packed += struct.pack(\""+\ |
| 414 | prefix+primPattern+"\", "+\ |
| 415 | str(primMemberNames).replace("'","")[1:-1]+")") |
| 416 | return ("",[]) |
| 417 | |
| 418 | def codelen(self, struct_in): |
| 419 | """Return code to return length |
| 420 | """ |
| 421 | pattern = "!" + self.__c2py.get_pattern(struct_in) |
| 422 | code = [] |
| 423 | code.append(self.tab+"def __len__(self):") |
| 424 | code.append(self.tab*2+"\"\"\"Return length of message") |
| 425 | code.append(self.tab*2+"\"\"\"") |
| 426 | code.append(self.tab*2+"l = "+str(self.__c2py.get_size(pattern))) |
| 427 | for member in struct_in.members: |
| 428 | if (isinstance(member, cheader.carray) and member.size == 0): |
| 429 | if (isinstance(member.object, cheader.cstruct)): |
| 430 | code.append(self.tab*2+"for i in self."+member.name+":") |
Dan Talayco | 10fe5c2 | 2010-02-07 23:05:29 -0800 | [diff] [blame] | 431 | # FIXME: Is this right? Doesn't seem to be called |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 432 | code.append(self.tab*3+"l += i.length()") |
| 433 | else: |
| 434 | pattern="!"+self.__c2py.get_pattern(member.object) |
| 435 | size=self.__c2py.get_size(pattern) |
| 436 | code.append(self.tab*2+"l += len(self."+member.name+")*"+str(size)) |
| 437 | code.append(self.tab*2+"return l") |
| 438 | return code |
| 439 | |
| 440 | def codeeq(self, struct_in): |
| 441 | """Return code to return equality comparisons |
| 442 | """ |
| 443 | code = [] |
| 444 | code.append(self.tab+"def __eq__(self, other):") |
| 445 | code.append(self.tab*2+"\"\"\"Return True if self and other have same values") |
| 446 | code.append(self.tab*2+"\"\"\"") |
| 447 | code.append(self.tab*2+"if type(self) != type(other): return False") |
| 448 | for member in struct_in.members: |
| 449 | code.append(self.tab*2 + "if self." + member.name + " != other." + |
| 450 | member.name + ": return False") |
| 451 | code.append(self.tab*2+"return True") |
| 452 | code.append("") |
| 453 | code.append(self.tab+"def __ne__(self, other): return not self.__eq__(other)") |
| 454 | return code |
| 455 | |
| 456 | def codeshow(self, struct_in): |
| 457 | """Return code to print basic members of structure |
| 458 | """ |
| 459 | code = [] |
| 460 | code.append(self.tab+"def show(self, prefix=''):") |
| 461 | code.append(self.tab*2+"\"\"\"" + "Print basic members of structure") |
| 462 | code.append(self.tab*2+"\"\"\"") |
| 463 | for member in struct_in.members: |
| 464 | if re.search('pad', member.name): |
| 465 | continue |
| 466 | elif (isinstance(member, cheader.cstruct)): |
| 467 | code.append(self.tab*2 + "print prefix + '" + |
| 468 | member.name + ": ' ") |
| 469 | code.append(self.tab*2 + "self." + member.name + |
| 470 | ".show(prefix + ' ')") |
| 471 | elif (isinstance(member, cheader.carray) and |
| 472 | not isinstance(member.object, cheader.cprimitive)): |
| 473 | code.append(self.tab*2 + "print prefix + '" + member.name + |
| 474 | ": ' ") |
| 475 | code.append(self.tab*2 + "for obj in self." + member.name + ":") |
| 476 | code.append(self.tab*3 + "obj.show(prefix + ' ')") |
| 477 | else: |
| 478 | code.append(self.tab*2 + "print prefix + '" + member.name + |
| 479 | ": ' + str(self." + member.name + ")") |
| 480 | return code |
| 481 | |
| 482 | def codeunpack(self, struct_in, prefix="!"): |
| 483 | """Return code that unpack struct |
| 484 | """ |
| 485 | pattern = self.__c2py.get_pattern(struct_in) |
| 486 | structlen = self.__c2py.get_size(prefix + pattern) |
| 487 | code = [] |
| 488 | code.append(self.tab+"def unpack(self, binaryString):") |
| 489 | code.append(self.tab*2+"\"\"\"Unpack message") |
| 490 | code.append(self.tab*2+"Do not unpack empty array used as placeholder") |
| 491 | code.append(self.tab*2+"since they can contain heterogeneous type") |
| 492 | code.append(self.tab*2+"\"\"\"") |
| 493 | code.append(self.tab*2+"if (len(binaryString) < "+str(structlen)+"):") |
| 494 | code.append(self.tab*3+"return binaryString") |
| 495 | offset = 0 |
| 496 | primPattern = "" |
| 497 | primMemberNames = [] |
| 498 | for member in struct_in.members: |
| 499 | if (isinstance(member, cheader.cprimitive)): |
| 500 | #Primitives |
| 501 | primPattern += self.__c2py.structmap[member.typename] |
| 502 | primMemberNames.append("self."+member.name) |
| 503 | else: |
| 504 | (primPattern, primMemberNames, offset) = \ |
| 505 | self.__codeunpackprimitive(code, offset, primPattern, |
| 506 | primMemberNames, prefix) |
| 507 | if (isinstance(member, cheader.cstruct)): |
| 508 | #Struct |
| 509 | code.append(self.tab*2+"self."+member.name+\ |
| 510 | ".unpack(binaryString["+str(offset)+":])") |
| 511 | pattern = self.__c2py.get_pattern(member) |
| 512 | offset += self.__c2py.get_size(prefix+pattern) |
| 513 | elif (isinstance(member, cheader.carray) and member.typename == "char"): |
| 514 | #String |
| 515 | code.append(self.tab*2+"self."+member.name+\ |
| 516 | " = binaryString["+str(offset)+":"+\ |
| 517 | str(offset+member.size)+"].replace(\"\\0\",\"\")") |
| 518 | offset += member.size |
| 519 | elif (isinstance(member, cheader.carray) and \ |
| 520 | isinstance(member.object, cheader.cprimitive)): |
| 521 | #Array of Primitives |
| 522 | expandedarr = "" |
| 523 | if (member.size != 0): |
| 524 | arrpattern = self.__c2py.structmap[member.object.typename]*member.size |
| 525 | for x in range(0, member.size): |
| 526 | expandedarr += "self."+member.name+"["+\ |
| 527 | str(x).strip()+"], " |
| 528 | code.append(self.tab*2+"("+expandedarr[:-2]+") = struct.unpack_from(\""+\ |
| 529 | prefix+arrpattern+\ |
| 530 | "\", binaryString, "+str(offset)+")") |
| 531 | offset += struct.calcsize(prefix + arrpattern) |
| 532 | elif (isinstance(member, cheader.carray) and \ |
| 533 | isinstance(member.object, cheader.cstruct)): |
| 534 | #Array of struct |
| 535 | astructlen = self.__c2py.get_size("!"+self.__c2py.get_pattern(member.object)) |
| 536 | for x in range(0, member.size): |
| 537 | code.append(self.tab*2+"self."+member.name+"["+str(x)+"]"+\ |
| 538 | ".unpack(binaryString["+str(offset)+":])") |
| 539 | offset += astructlen |
| 540 | #Clear remaining fields |
| 541 | (primPattern, primMemberNames, offset) = \ |
| 542 | self.__codeunpackprimitive(code, offset, primPattern, |
| 543 | primMemberNames, prefix) |
| 544 | code.append(self.tab*2+"return binaryString["+str(structlen)+":]"); |
| 545 | return code |
| 546 | |
| 547 | def __codeunpackprimitive(self, code, offset, primPattern, |
| 548 | primMemberNames, prefix): |
| 549 | """Return code for unpacking primitives |
| 550 | """ |
| 551 | if (primPattern != ""): |
| 552 | #Clear prior primitives |
Dan Talayco | 10fe5c2 | 2010-02-07 23:05:29 -0800 | [diff] [blame] | 553 | if len(primMemberNames) == 1: |
| 554 | code.append(self.tab*2 + "(" + str(primMemberNames[0]) + |
| 555 | ",) = struct.unpack_from(\"" + prefix+primPattern |
| 556 | + "\", binaryString, " + str(offset) + ")") |
| 557 | else: |
| 558 | code.append(self.tab*2+"("+str(primMemberNames).replace("'","")[1:-1]+ |
| 559 | ") = struct.unpack_from(\""+ |
| 560 | prefix+primPattern+"\", binaryString, "+str(offset)+")") |
| 561 | |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 562 | return ("",[], offset+struct.calcsize(prefix+primPattern)) |
| 563 | |