custom from_py converter for Py_UNICODE
authorLisandro Dalcin <dalcinl@gmail.com>
Thu, 22 Apr 2010 15:31:52 +0000 (12:31 -0300)
committerLisandro Dalcin <dalcinl@gmail.com>
Thu, 22 Apr 2010 15:31:52 +0000 (12:31 -0300)
Cython/Compiler/PyrexTypes.py
tests/run/py_unicode_type.pyx

index 20e9fc1e9aecf13212c6509c681969d8c7a236a8..2a0113f913d388d5a4dad3275d2d31052fdb1bfb 100755 (executable)
@@ -828,7 +828,7 @@ class CIntType(CNumericType):
         type_name = type_name.replace("PY_LONG_LONG","long long")
         SignWord  = sign_word.title()
         TypeName  = type_name.title().replace(" ", "")
-        if "Long" in TypeName:
+        if self.rank >= list(rank_to_type_name).index('long'):
             utility_code = c_long_from_py_function
         else:
             utility_code = c_int_from_py_function
@@ -874,6 +874,7 @@ class CPyUnicodeIntType(CIntType):
     # 1114111, so PyInt_FromLong() will do just fine here.
 
     to_py_function = "PyInt_FromLong"
+    from_py_function = "__Pyx_PyInt_AsPy_UNICODE"
 
     def sign_and_name(self):
         return "Py_UNICODE"
@@ -2491,6 +2492,10 @@ type_conversion_predeclarations = """
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
 
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject*);
+#endif
+
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
 static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
@@ -2555,6 +2560,26 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   return res;
 }
 
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject* x) {
+   long ival = __Pyx_PyInt_AsLong(x);
+   static long maxval = 0;
+   if (unlikely(!maxval))
+       maxval = (long)PyUnicode_GetMax();
+   if (unlikely(ival < 0)) {
+       if (!PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "can't convert negative value to Py_UNICODE");
+       return (Py_UNICODE)-1;
+   } else if (unlikely(ival > maxval)) {
+       PyErr_SetString(PyExc_OverflowError,
+                       "value too large to convert to Py_UNICODE");
+       return (Py_UNICODE)-1;
+   }
+   return (Py_UNICODE)ival;
+}
+#endif
+
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
   Py_ssize_t ival;
   PyObject* x = PyNumber_Index(b);
index b1bb40e8b831e296a43a3eb05d263192cd52cab4..41fe97d7689be9d99285e9c9a602b953ce83c0a4 100644 (file)
@@ -42,3 +42,28 @@ def index_literal(int i):
     # runtime casts are not currently supported
     #return <Py_UNICODE>(u"12345"[i])
     return u"12345"[i]
+
+
+def unicode_cardinal(Py_UNICODE i):
+    """
+    >>> import sys
+
+    >>> unicode_cardinal(0)
+    0
+    >>> unicode_cardinal(1)
+    1
+    >>> unicode_cardinal(sys.maxunicode) == sys.maxunicode
+    True
+
+    
+    >>> unicode_cardinal(-1) #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    OverflowError: ...
+
+    >>> unicode_cardinal(sys.maxunicode+1) #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    OverflowError: ...
+    """
+    return i