131 lines
4.9 KiB
Python
131 lines
4.9 KiB
Python
"""
|
|
Wraps enumerations
|
|
"""
|
|
|
|
from typehandlers import inttype
|
|
from typehandlers.base import return_type_matcher, param_type_matcher
|
|
from cppclass import CppClass
|
|
|
|
class Enum(object):
|
|
"""
|
|
Class that adds support for a C/C++ enum type
|
|
"""
|
|
def __init__(self, name, values, values_prefix='', cpp_namespace=None, outer_class=None):
|
|
"""
|
|
Creates a new enum wrapper, which should be added to a module with module.add_enum().
|
|
|
|
@param name: C name of the enum type
|
|
@param values: a list of strings with all enumeration value names
|
|
@param values_prefix: prefix to add to value names, or None
|
|
@param cpp_namespace: optional C++ namespace identifier, or None.
|
|
Note: this namespace is *in addition to*
|
|
whatever namespace of the module the enum
|
|
belongs to. Typically this parameter is to
|
|
be used when wrapping enums declared inside
|
|
C++ classes.
|
|
"""
|
|
assert isinstance(name, basestring)
|
|
assert '::' not in name
|
|
assert outer_class is None or isinstance(outer_class, CppClass)
|
|
self.outer_class = outer_class
|
|
for val in values:
|
|
if not isinstance(val, basestring):
|
|
raise TypeError
|
|
|
|
#if not name:
|
|
# raise ValueError
|
|
self.name = name
|
|
self.full_name = None
|
|
self.values = list(values)
|
|
self.values_prefix = values_prefix
|
|
self.cpp_namespace = cpp_namespace
|
|
self._module = None
|
|
self.ThisEnumParameter = None
|
|
self.ThisEnumReturn = None
|
|
|
|
def get_module(self):
|
|
"""Get the Module object this class belongs to"""
|
|
return self._module
|
|
|
|
def set_module(self, module):
|
|
"""Set the Module object this class belongs to; can only be set once"""
|
|
assert self._module is None
|
|
self._module = module
|
|
|
|
if not self.name:
|
|
return
|
|
|
|
if self.outer_class is None:
|
|
if self._module.cpp_namespace_prefix:
|
|
if self._module.cpp_namespace_prefix == '::':
|
|
self.full_name = '::' + self.name
|
|
else:
|
|
self.full_name = self._module.cpp_namespace_prefix + '::' + self.name
|
|
else:
|
|
self.full_name = self.name
|
|
else:
|
|
self.full_name = '::'.join([self.outer_class.full_name, self.name])
|
|
|
|
## Register type handlers for the enum type
|
|
assert self.name
|
|
assert self.full_name
|
|
class ThisEnumParameter(inttype.IntParam):
|
|
CTYPES = []
|
|
full_type_name = self.full_name
|
|
def __init__(self, ctype, name):
|
|
super(ThisEnumParameter, self).__init__(self.full_type_name, name)
|
|
class ThisEnumReturn(inttype.IntReturn):
|
|
CTYPES = []
|
|
full_type_name = self.full_name
|
|
def __init__(self, ctype):
|
|
super(ThisEnumReturn, self).__init__(self.full_type_name)
|
|
self.ThisEnumParameter = ThisEnumParameter
|
|
self.ThisEnumReturn = ThisEnumReturn
|
|
param_type_matcher.register(self.full_name, self.ThisEnumParameter)
|
|
return_type_matcher.register(self.full_name, self.ThisEnumReturn)
|
|
|
|
if self.name != self.full_name:
|
|
try:
|
|
param_type_matcher.register(self.name, self.ThisEnumParameter)
|
|
except ValueError:
|
|
pass
|
|
try:
|
|
return_type_matcher.register(self.name, self.ThisEnumReturn)
|
|
except ValueError:
|
|
pass
|
|
|
|
|
|
module = property(get_module, set_module)
|
|
|
|
def generate(self, unused_code_sink):
|
|
module = self.module
|
|
if self.outer_class is None:
|
|
namespace = []
|
|
if module.cpp_namespace_prefix:
|
|
namespace.append(module.cpp_namespace_prefix)
|
|
if self.cpp_namespace:
|
|
namespace.append(self.cpp_namespace)
|
|
for value in self.values:
|
|
module.after_init.write_code(
|
|
"PyModule_AddIntConstant(m, (char *) \"%s\", %s);"
|
|
% (value, '::'.join(namespace + [self.values_prefix + value])))
|
|
else:
|
|
module.after_init.write_code("{")
|
|
module.after_init.indent()
|
|
module.after_init.write_code("PyObject *tmp_value;")
|
|
for value in self.values:
|
|
value_str = "%s::%s" % (self.outer_class.full_name, value)
|
|
module.after_init.write_code(
|
|
' // %s\n'
|
|
'tmp_value = PyInt_FromLong(%s);\n'
|
|
'PyDict_SetItemString((PyObject*) %s.tp_dict, \"%s\", tmp_value);\n'
|
|
'Py_DECREF(tmp_value);'
|
|
% (
|
|
value_str, value_str, self.outer_class.pytypestruct, value))
|
|
module.after_init.unindent()
|
|
module.after_init.write_code("}")
|
|
|
|
def generate_declaration(self, sink, module):
|
|
pass
|
|
|