#!/usr/bin/env python
# Julian Rockey 2003
# Generate marshall/demarshal functions from marshal_funcs.data file
import sys
import re
def cap_first(str):
"""Capitalise first letter of string."""
return str[0].upper() + str[1:]
def set_method(attr):
"""Return the name for a QT class setter method for an attribute."""
return "set" + cap_first(attr)
class DictMaker:
"""Generate code for marshalling/demarshalling types using Python dictionaries."""
supported_types = ['string']
re_dictmap = re.compile("%dict\-map(.*)")
re_dictmap_constructor = re.compile("%constructor (.+)")
def __init__(self):
self.attr_list = []
self.current_type = None
self.operation = None
self.constructor = None
self.type_handlers = {}
for type in self.supported_types:
self.type_handlers[type] = (eval('self.handle_%s_marsh' % type),
eval('self.handle_%s_demarsh' % type))
def handle_string_marsh(self, attribute):
"""Handle marshalling of string item from the dictionary."""
return ["if (%s && !PyString_Check(%s)) return false;" % (attribute, attribute),
"if (%s) { qobj.%s(QString(PyString_AsString(%s)));" % (attribute, set_method(attribute), attribute),
"PyDict_DelItemString(dict,(char*)\"%s\"); } " % (attribute)]
def handle_string_demarsh(self, attribute):
"""Handle demarshalling of string items into the dictionary."""
return ["PyObject *%s = PyString_FromString(qobj.%s().utf8().data() );" % (attribute ,attribute),
"PyDict_SetItemString(dict, (char*)\"%s\", %s);" % (attribute, attribute)
]
def pre_code_for(self, operation, attribute):
if operation==MARSHAL:
return ["PyObject *%s = PyDict_GetItemString(dict,(char*)\"%s\");" % (attribute, attribute) ]
return []
def post_code_for(self, operation, attribute):
return []
def code_for(self, operation, type, attribute):
if operation!=None and (type in self.type_handlers):
return self.pre_code_for(operation, attribute) + \
self.type_handlers[type][not not operation](attribute) + \
self.post_code_for(operation, attribute)
return []
def set_current_type(self, current_type):
self.current_type = current_type
self.constructor = "";
def set_operation(self, operation):
if operation in [None, MARSHAL, DEMARSHAL]:
self.operation = operation
def check_dictmap(self, line):
if self.operation not in [MARSHAL,DEMARSHAL]: return []
m=self.re_dictmap_constructor.match(line)
if m:
self.constructor = m.groups()[0]
return ['']
m=self.re_dictmap.match(line)
if not m: return []
if self.operation==MARSHAL:
result = ["{",
"if (!PyDict_Check(obj)) return false;",
"%s qobj%s;" % (self.current_type,self.constructor),
"PyObject *dict = PyDict_Copy(obj);"
]
if self.operation==DEMARSHAL:
result = ["{",
"PyObject *dict = PyDict_New();",
"if (!dict) return NULL;",
"%s qobj%s;" % (self.current_type,self.constructor),
"(*str) >> qobj;"
]
if m.groups()[0].strip():
self.attr_list = [tuple(x.split(':')) for x in m.groups()[0].strip().split(',') ]
for attribute, type in self.attr_list:
result += self.code_for(self.operation, type, attribute)
if self.operation==MARSHAL:
result += ["if (str) (*str) << qobj;",
"Py_DECREF(dict);",
"return true;",
"}"
]
if self.operation==DEMARSHAL:
result += ["return dict;",
"}"
]
return result
class DocType:
"""A class to hold documentation information for each type."""
def __init__(self, type):
self.type = type
self.demarshal_asme = None
self.asme = []
self.info = []
def add_asme(self, asme):
if self.demarshal_asme == None: self.demarshal_asme = asme
self.asme += [asme]
def add_info(self,info):
self.info += [info]
def xml(self):
return ['' % self.type,
' %s' % self.demarshal_asme] + \
[' %s' % asme for asme in self.asme ] + \
[' %s' % info for info in self.info ] + \
['']
MARSHAL, DEMARSHAL, TOPYOBJ, FROMPYOBJ = 0,1,2,3
if len(sys.argv)!=4:
print "Use: gen_marshal_code.py