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