Commit 42777129 authored by Robert Bradshaw's avatar Robert Bradshaw

Generate custom conversion code for enums.

This not only fixes bugs like auto-conversion of std::map[enum, enum] but also
fixes a bug where the compiler-chosen type of int for the enum may not have been
long.
parent 8d073443
......@@ -3600,8 +3600,6 @@ class CEnumType(CType):
is_enum = 1
signed = 1
rank = -1 # Ranks below any integer type
to_py_function = "PyInt_FromLong"
from_py_function = "PyInt_AsLong"
def __init__(self, name, cname, typedef_flag):
self.name = name
......@@ -3629,6 +3627,22 @@ class CEnumType(CType):
base_code = public_decl(base_code, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def create_to_py_utility_code(self, env):
self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
env.use_utility_code(TempitaUtilityCode.load_cached(
"CIntToPy", "TypeConversion.c",
context={"TYPE": self.empty_declaration_code(),
"TO_PY_FUNCTION": self.to_py_function}))
return True
def create_from_py_utility_code(self, env):
self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
env.use_utility_code(TempitaUtilityCode.load_cached(
"CIntFromPy", "TypeConversion.c",
context={"TYPE": self.empty_declaration_code(),
"FROM_PY_FUNCTION": self.from_py_function}))
return True
def from_py_call_code(self, source_code, result_code, error_pos, code,
from_py_function=None, error_condition=None):
rhs = "%s(%s)" % (
......
......@@ -138,7 +138,7 @@ bad:
Py_XDECREF(ascii_chars_b);
return -1;
}
#endif
#endif
#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
......@@ -192,7 +192,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_
#if CYTHON_COMPILING_IN_CPYTHON && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
if (
#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
__Pyx_sys_getdefaultencoding_not_ascii &&
__Pyx_sys_getdefaultencoding_not_ascii &&
#endif
PyUnicode_Check(o)) {
#if PY_VERSION_HEX < 0x03030000
......@@ -353,8 +353,8 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
return PyInt_FromSize_t(ival);
}
/////////////// ToPyCTupleUtility.proto ///////////////
static PyObject* {{funcname}}({{struct_type_decl}});
......@@ -370,27 +370,27 @@ static PyObject* {{funcname}}({{struct_type_decl}} value) {
if (!item) goto bad;
PyTuple_SET_ITEM(result, {{ix}}, item);
{{endfor}}
return result;
bad:
Py_XDECREF(item);
Py_XDECREF(result);
return NULL;
}
/////////////// FromPyCTupleUtility.proto ///////////////
static {{struct_type_decl}} {{funcname}}(PyObject *);
/////////////// FromPyCTupleUtility ///////////////
static {{struct_type_decl}} {{funcname}}(PyObject * o) {
{{struct_type_decl}} result;
if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != {{size}}) {
PyErr_Format(PyExc_TypeError, "Expected %.16s of size %d, got %.200s", "a tuple", {{size}}, Py_TYPE(o)->tp_name);
goto bad;
}
#if CYTHON_COMPILING_IN_CPYTHON
{{for ix, component in enumerate(components):}}
{{py:attr = "result.f%s" % ix}}
......@@ -536,7 +536,7 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value);
/////////////// CIntToPy ///////////////
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0;
const int is_unsigned = neg_one > const_zero;
if (is_unsigned) {
if (sizeof({{TYPE}}) < sizeof(long)) {
......@@ -607,7 +607,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *);
{{py: from Cython.Utility import pylong_join }}
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0;
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
......@@ -627,7 +627,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)x)->ob_digit;
switch (Py_SIZE(x)) {
case 0: return 0;
case 0: return ({{TYPE}}) 0;
case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
{{for _size in (2, 3, 4)}}
case {{_size}}:
......@@ -635,7 +635,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
} else if (8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT) {
return {{pylong_join(_size, 'digits', TYPE)}};
return ({{TYPE}}) {{pylong_join(_size, 'digits', TYPE)}};
}
}
break;
......@@ -666,7 +666,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)x)->ob_digit;
switch (Py_SIZE(x)) {
case 0: return 0;
case 0: return ({{TYPE}}) 0;
case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, -(sdigit) digits[0])
case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, +digits[0])
{{for _size in (2, 3, 4)}}
......@@ -676,7 +676,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
} else if (8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT) {
return {{'-' if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}};
return ({{TYPE}}) {{'-' if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}};
}
}
break;
......
......@@ -207,3 +207,16 @@ def test_nested(o):
"""
cdef map[pair[double, double], vector[int]] m = o
return m
cpdef enum Color:
RED = 0
GREEN
BLUE
def test_enum_map(o):
"""
>>> test_enum_map({RED: GREEN})
{0: 1}
"""
cdef map[Color, Color] m = o
return m
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment