Commit d5370b4b authored by Robert Bradshaw's avatar Robert Bradshaw

Refactor conversion utility code.

parent a6bb9c17
......@@ -1562,7 +1562,15 @@ class CIntType(CNumericType):
if self.to_py_function is None:
self.to_py_function = self.get_to_py_type_conversion()
if self.from_py_function is None:
self.from_py_function = self.get_from_py_type_conversion()
# Inject specializatioin used elsewhere.
self.get_from_py_type_conversion()
def create_from_py_utility_code(self, env):
self.from_py_function = "__Pyx_PyInt_As" + self.specialization_name()
env.use_utility_code(TempitaUtilityCode.load(
"CIntFromPy", "TypeConversion.c",
context={"TYPE": self.declaration_code(''), "FROM_PY_FUNCTION": self.from_py_function}))
return True
def get_to_py_type_conversion(self):
if self.rank < list(rank_to_type_name).index('int'):
......
......@@ -64,7 +64,7 @@ class TreeVisitor(object):
self.access_path = []
def dump_node(self, node, indent=0):
ignored = list(node.child_attrs) + [u'child_attrs', u'pos',
ignored = list(node.child_attrs or []) + [u'child_attrs', u'pos',
u'gil_message', u'cpp_message',
u'subexprs']
values = []
......
......@@ -448,3 +448,130 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
}
return (Py_UNICODE)ival;
}
/////////////// CIntToPy.proto ///////////////
/////////////// CIntToPy ///////////////
/////////////// CIntFromPy.proto ///////////////
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *);
/////////////// CIntFromPy ///////////////
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
#include "longintrepr.h"
#endif
#endif
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
long val = PyInt_AS_LONG(x);
if (sizeof({{TYPE}}) < sizeof(long)) {
if (unlikely(val != ({{TYPE}}) val)) {
PyErr_SetString(PyExc_OverflowError,
(is_unsigned && unlikely(val < 0)) ?
"can't convert negative value to {{TYPE}}" :
"value too large to convert to {{TYPE}}");
return ({{TYPE}}) -1;
} else {
return ({{TYPE}}) val;
}
} else {
if (is_unsigned && unlikely(val < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to {{TYPE}}");
return ({{TYPE}}) -1;
} else {
return ({{TYPE}}) val;
}
}
} else
#endif
if (likely(PyLong_Check(x))) {
if (is_unsigned) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof({{TYPE}})) {
switch (Py_SIZE(x)) {
case 0: return 0;
case 1: return (%(type)s) ((PyLongObject*)x)->ob_digit[0];
}
}
#endif
#endif
if (unlikely(Py_SIZE(x) < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to {{TYPE}}");
return ({{TYPE}}) -1;
}
if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
unsigned long val = PyLong_AsUnsignedLong(x);
if (sizeof({{TYPE}}) < sizeof(unsigned long)
&& unlikely(val != ({{TYPE}}) val)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to {{TYPE}}");
return ({{TYPE}}) -1;
}
return ({{TYPE}}) val;
} else if (sizeof({{TYPE}}) <= sizeof(unsigned long long)) {
unsigned long long val = PyLong_AsUnsignedLongLong(x);
if (sizeof({{TYPE}}) < sizeof(unsigned long long)
&& unlikely(val != ({{TYPE}}) val)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to {{TYPE}}");
return ({{TYPE}}) -1;
}
return ({{TYPE}}) val;
} else {
// Huh?
return ({{TYPE}}) PyLong_AsUnsignedLongLong(x);
}
} else {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof({{TYPE}}) {
switch (Py_SIZE(x)) {
case 0: return 0;
case 1: return +({{TYPE}}) ((PyLongObject*)x)->ob_digit[0];
case -1: return -({{TYPE}}) ((PyLongObject*)x)->ob_digit[0];
}
}
#endif
#endif
if (sizeof({{TYPE}}) <= sizeof(long)) {
long val = PyLong_AsLong(x);
if (sizeof({{TYPE}}) < sizeof(long)
&& unlikely(val != ({{TYPE}}) val)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to {{TYPE}}");
return ({{TYPE}}) -1;
}
return ({{TYPE}}) val;
} else if (sizeof({{TYPE}}) <= sizeof(long long)) {
long long val = PyLong_AsLongLong(x);
if (sizeof({{TYPE}}) < sizeof(long long)
&& unlikely(val != ({{TYPE}}) val)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to {{TYPE}}");
return ({{TYPE}}) -1;
}
return ({{TYPE}}) val;
} else {
// Huh?
return ({{TYPE}}) PyLong_AsLongLong(x);
}
}
} else {
{{TYPE}} val;
PyObject *tmp = __Pyx_PyNumber_Int(x);
if (!tmp) return ({{TYPE}}) -1;
val = {{FROM_PY_FUNCTION}}(tmp);
Py_DECREF(tmp);
return val;
}
}
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