From 3e5fc3ce0699e4ecdc143d995746f2d8ca80c104 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Mon, 26 Aug 2013 10:48:32 -0700 Subject: [PATCH] Fix some integer conversion tests. --- Cython/Compiler/ExprNodes.py | 1 + Cython/Compiler/ModuleNode.py | 4 +++ Cython/Compiler/PyrexTypes.py | 26 +++++++++++++------ Cython/Utility/TypeConversion.c | 19 ++++++++++++-- tests/run/cpp_nonstdint.h | 56 +++++++++++++++++++++++++++++++++++------ tests/run/int_literals.pyx | 7 ++++-- tests/run/wundram1.pyx | 2 +- 7 files changed, 94 insertions(+), 21 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 7f1fdcb..b6d614e 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -3019,6 +3019,7 @@ class IndexNode(ExprNode): else: self.is_temp = 1 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env) + self.original_index_type.create_to_py_utility_code(env) else: self.index = self.index.coerce_to_pyobject(env) self.is_temp = 1 diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 6ae12a7..a19124f 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -589,6 +589,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln('#define __Pyx_PyObject_FromStringAndSize __Pyx_Py%s_FromStringAndSize' % c_string_type.title()) code.put(UtilityCode.load_as_string("TypeConversions", "TypeConversion.c")[0]) + # These utility functions are assumed to exist and used elsewhere. + PyrexTypes.c_long_type.create_to_py_utility_code(env) + PyrexTypes.c_long_type.create_from_py_utility_code(env) + code.put(Nodes.branch_prediction_macros) code.putln('') code.putln('static PyObject *%s;' % env.module_cname) diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 492ae56..3d9b77b 100755 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -368,11 +368,11 @@ class CTypedefType(BaseType): if not self.to_py_utility_code: base_type = self.typedef_base_type if type(base_type) is CIntType: - self.from_py_function = "__Pyx_PyInt_from_py_" + self.specialization_name() + self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name() env.use_utility_code(TempitaUtilityCode.load( - "CIntFromPy", "TypeConversion.c", + "CIntToPy", "TypeConversion.c", context={"TYPE": self.declaration_code(''), - "FROM_PY_FUNCTION": self.from_py_function})) + "TO_PY_FUNCTION": self.to_py_function})) return True elif base_type.is_float: pass # XXX implement! @@ -390,11 +390,11 @@ class CTypedefType(BaseType): if not self.from_py_utility_code: base_type = self.typedef_base_type if type(base_type) is CIntType: - self.to_py_function = "__Pyx_PyInt_to_py_" + self.specialization_name() + self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name() env.use_utility_code(TempitaUtilityCode.load( - "CIntToPy", "TypeConversion.c", + "CIntFromPy", "TypeConversion.c", context={"TYPE": self.declaration_code(''), - "TO_PY_FUNCTION": self.to_py_function})) + "FROM_PY_FUNCTION": self.from_py_function})) return True elif base_type.is_float: pass # XXX implement! @@ -1366,6 +1366,14 @@ class CNumericType(CType): return "float" +class ForbidUseClass: + def __repr__(self): + raise RuntimeError() + def __str__(self): + raise RuntimeError() +ForbidUse = ForbidUseClass() + + class CIntType(CNumericType): is_int = 1 @@ -1376,7 +1384,7 @@ class CIntType(CNumericType): def create_to_py_utility_code(self, env): if type(self).to_py_function is None: - self.to_py_function = "__Pyx_PyInt_to_py_" + self.specialization_name() + self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name() env.use_utility_code(TempitaUtilityCode.load( "CIntToPy", "TypeConversion.c", context={"TYPE": self.declaration_code(''), @@ -1385,7 +1393,7 @@ class CIntType(CNumericType): def create_from_py_utility_code(self, env): if type(self).from_py_function is None: - self.from_py_function = "__Pyx_PyInt_from_py_" + self.specialization_name() + self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name() env.use_utility_code(TempitaUtilityCode.load( "CIntFromPy", "TypeConversion.c", context={"TYPE": self.declaration_code(''), @@ -1588,6 +1596,8 @@ class CSSizeTType(CIntType): class CSizeTType(CIntType): + to_py_function = "__Pyx_PyInt_FromSize_t" + def sign_and_name(self): return "size_t" diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c index 0a62234..b6b8e1d 100644 --- a/Cython/Utility/TypeConversion.c +++ b/Cython/Utility/TypeConversion.c @@ -44,6 +44,7 @@ static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); #if CYTHON_COMPILING_IN_CPYTHON #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) @@ -262,6 +263,20 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { return ival; } +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { +#if PY_VERSION_HEX < 0x02050000 + if (ival <= LONG_MAX) + return PyInt_FromLong((long)ival); + else { + unsigned char *bytes = (unsigned char *) &ival; + int one = 1; int little = (int)*(unsigned char*)&one; + return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); + } +#else + return PyInt_FromSize_t(ival); +#endif +} + /////////////// FromPyStructUtility.proto /////////////// {{struct_type_decl}}; @@ -336,7 +351,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) { "got length %" CYTHON_FORMAT_SSIZE_T "d", length); return (Py_UCS4)-1; } - ival = __Pyx_PyInt_AsLong(x); + ival = __Pyx_PyInt_As_long(x); if (unlikely(ival < 0)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_OverflowError, @@ -384,7 +399,7 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) { if (unlikely(!maxval)) maxval = (long)PyUnicode_GetMax(); #endif - ival = __Pyx_PyInt_AsLong(x); + ival = __Pyx_PyInt_As_long(x); } if (unlikely(ival < 0)) { if (!PyErr_Occurred()) diff --git a/tests/run/cpp_nonstdint.h b/tests/run/cpp_nonstdint.h index 12c4960..6155ab8 100644 --- a/tests/run/cpp_nonstdint.h +++ b/tests/run/cpp_nonstdint.h @@ -14,16 +14,16 @@ class Integral { for (unsigned int i=0; i N ? sizeof(long long) : N; + unsigned char* extended = new unsigned char[len]; + unsigned char* other; + if (sizeof(long long) < N) { + resize_signed_int((unsigned char*)&value, sizeof(value), extended, len); + other = bytes; + } else { + resize_signed_int(bytes, N, extended, len); + } + bool res = memcmp(extended, other, len); + delete extended; + return res; + } + bool operator!=(const long long val) const + { return !(*this == val); } private: static bool is_le() { @@ -81,7 +98,30 @@ class Integral { if (sI) return -cmpabs; else return +cmpabs; } - + + static void resize_signed_int(const unsigned char* src, size_t src_len, unsigned char* dst, size_t dst_len) { + unsigned char msb; + size_t dst_offset = 0; + size_t src_offset = 0; + if (is_le()) { + dst_offset = 0; + src_offset = 0; + msb = ((unsigned char*) src)[src_len - 1]; + } else { + if (dst_len > src_len) { + dst_offset = dst_len - src_len; + } else { + src_offset = src_len - dst_len; + } + msb = ((unsigned char*) src)[0]; + } + if (msb & 0x80) { + memset(dst, 0xFF, dst_len); + } else { + memset(dst, 0, dst_len); + } + memcpy(dst + dst_offset, src + src_offset, src_len); + } }; typedef Integral<3> Int24; diff --git a/tests/run/int_literals.pyx b/tests/run/int_literals.pyx index 770b60a..74a4700 100644 --- a/tests/run/int_literals.pyx +++ b/tests/run/int_literals.pyx @@ -1,6 +1,6 @@ __doc__ = u""" >>> c_longs() -(1, 1L, -1L, 18446744073709551615L) +(1, 1L, -1, 18446744073709551615L) >>> negative_c_longs() (-1, -9223285636854775809L) >>> py_longs() @@ -19,6 +19,9 @@ import sys if sys.version_info[0] >= 3: __doc__ = __doc__.replace(u'L', u'') +elif sys.maxint > 2**31: + # sizeof(long) == sizeof(long long) + __doc__ = __doc__.replace("9223285636854775809L", "9223285636854775809") @cython.test_assert_path_exists( '//IntNode[@longness = "LL"]', @@ -30,7 +33,7 @@ def c_longs(): cdef unsigned long ua = 1UL cdef long long aa = 0xFFFFFFFFFFFFFFFFLL cdef unsigned long long uaa = 0xFFFFFFFFFFFFFFFFULL - return a, ua, aa, uaa + return a, ua, int(aa), uaa @cython.test_assert_path_exists( '//IntNode[@longness = "LL"]', diff --git a/tests/run/wundram1.pyx b/tests/run/wundram1.pyx index 1d39e1a..06295cd 100644 --- a/tests/run/wundram1.pyx +++ b/tests/run/wundram1.pyx @@ -4,7 +4,7 @@ __doc__ = u""" """ import sys -if sys.version_info[0] >= 3: +if sys.version_info[0] >= 3 or sys.maxint > 2**31: __doc__ = __doc__.replace(u"5L", u"5") cdef unsigned int ui -- 2.7.4