make Cython understand 'size_t' as a native C type (ticket #207)
authorLisandro Dalcin <dalcinl@gmail.com>
Sat, 7 Feb 2009 18:09:06 +0000 (15:09 -0300)
committerLisandro Dalcin <dalcinl@gmail.com>
Sat, 7 Feb 2009 18:09:06 +0000 (15:09 -0300)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
Cython/Includes/python2.5.pxd
Cython/Includes/python_mem.pxd
Cython/Includes/stdlib.pxd
tests/run/size_t.pyx [new file with mode: 0644]

index 847efacf92071e0d4d256528bb9f1af95277173c..0999eeb322abe3f8a3faf5a3577a056bf792a908 100644 (file)
@@ -3892,7 +3892,7 @@ class TypecastNode(NewTempExprNode):
 class SizeofNode(ExprNode):
     #  Abstract base class for sizeof(x) expression nodes.
     
-    type = PyrexTypes.c_int_type
+    type = PyrexTypes.c_size_t_type
 
     def check_const(self):
         pass
index 21b94883c78ec5a2f6ec965aa3350ceadff00135..1ad4f7365adaa185c6b6b8a629f6ca0f42f25a61 100644 (file)
@@ -1810,8 +1810,8 @@ def looking_at_dotted_name(s):
         return result
     else:
         return 0
-        
-basic_c_type_names = ("void", "char", "int", "float", "double", "Py_ssize_t", "bint")
+
+basic_c_type_names = ("void", "char", "int", "float", "double", "Py_ssize_t", "size_t", "bint")
 
 sign_and_longness_words = ("short", "long", "signed", "unsigned")
 
index 7f11935c0508a8c82d7994ec09004d1704f41c77..9d2fce4c270f7f40ba379d3749af2da8a4aeb00e 100644 (file)
@@ -462,9 +462,9 @@ class CNumericType(CType):
     default_value = "0"
     
     parsetuple_formats = ( # rank -> format
-        "BHIkK????", # unsigned
-        "bhilL?fd?", # assumed signed
-        "bhilL?fd?", # explicitly signed
+        "BHIkK?????", # unsigned
+        "bhilL??fd?", # assumed signed
+        "bhilL??fd?", # explicitly signed
     )
     
     sign_words = ("unsigned ", "", "signed ")
@@ -594,6 +594,12 @@ class CPySSizeTType(CIntType):
     from_py_function = "__pyx_PyIndex_AsSsize_t"
 
 
+class CSizeTType(CUIntType):
+
+    to_py_function = "__pyx_PyInt_FromSize_t"
+    from_py_function = "__pyx_PyInt_AsSize_t"
+
+
 class CFloatType(CNumericType):
 
     is_float = 1
@@ -1153,9 +1159,10 @@ rank_to_type_name = (
     "long",         # 3
     "PY_LONG_LONG", # 4
     "Py_ssize_t",   # 5
-    "float",        # 6
-    "double",       # 7
-    "long double",  # 8
+    "size_t",       # 6
+    "float",        # 7
+    "double",       # 8
+    "long double",  # 9
 )
 
 py_object_type = PyObjectType()
@@ -1175,7 +1182,6 @@ c_short_type =       CIntType(1, 1, "T_SHORT")
 c_int_type =         CIntType(2, 1, "T_INT")
 c_long_type =        CIntType(3, 1, "T_LONG")
 c_longlong_type =    CLongLongType(4, 1, "T_LONGLONG")
-c_py_ssize_t_type =  CPySSizeTType(5, 1)
 c_bint_type =        CBIntType(2, 1, "T_INT")
 
 c_schar_type =       CIntType(0, 2, "T_CHAR")
@@ -1184,17 +1190,21 @@ c_sint_type =        CIntType(2, 2, "T_INT")
 c_slong_type =       CIntType(3, 2, "T_LONG")
 c_slonglong_type =   CLongLongType(4, 2, "T_LONGLONG")
 
-c_float_type =       CFloatType(6, "T_FLOAT")
-c_double_type =      CFloatType(7, "T_DOUBLE")
-c_longdouble_type =  CFloatType(8)
+c_py_ssize_t_type =  CPySSizeTType(5, 1)
+c_size_t_type =      CSizeTType(6, 1)
+
+c_float_type =       CFloatType(7, "T_FLOAT")
+c_double_type =      CFloatType(8, "T_DOUBLE")
+c_longdouble_type =  CFloatType(9)
 
 c_null_ptr_type =     CNullPtrType(c_void_type)
 c_char_array_type =   CCharArrayType(None)
 c_char_ptr_type =     CCharPtrType()
 c_utf8_char_array_type = CUTF8CharArrayType(None)
 c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
-c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
 c_int_ptr_type =      CPtrType(c_int_type)
+c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
+c_size_t_ptr_type =  CPtrType(c_size_t_type)
 
 c_returncode_type =   CIntType(2, 1, "T_INT", is_returncode = 1)
 
@@ -1207,28 +1217,31 @@ c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
 error_type =    ErrorType()
 unspecified_type = UnspecifiedType()
 
-lowest_float_rank = 6
-
 sign_and_rank_to_type = {
     #(signed, rank)
-    (0, 0): c_uchar_type, 
+    (0, 0): c_uchar_type, 
     (0, 1): c_ushort_type, 
     (0, 2): c_uint_type, 
-  (0, 3): c_ulong_type,
-  (0, 4): c_ulonglong_type,
-    (0, 5):  c_ulonglong_type,            # I'm not sure about this.  this should be for size_t Py_ssize_t
+    (0, 3): c_ulong_type,
+    (0, 4): c_ulonglong_type,
+    (0, 5): c_ulonglong_type, # XXX I'm not sure about this.
+    
     (1, 0): c_char_type, 
     (1, 1): c_short_type, 
     (1, 2): c_int_type, 
     (1, 3): c_long_type,
     (1, 4): c_longlong_type,
-    (1, 5): c_py_ssize_t_type,
     (2, 0): c_schar_type, 
     (2, 1): c_sshort_type, 
     (2, 2): c_sint_type, 
     (2, 3): c_slong_type,
     (2, 4): c_slonglong_type,
+
+    (1, 5): c_py_ssize_t_type,
     (2, 5): c_py_ssize_t_type,
+    (0, 6): c_size_t_type,
+    (1, 6): c_size_t_type,
+
     (1, 6): c_float_type, 
     (1, 7): c_double_type,
     (1, 8): c_longdouble_type,
@@ -1251,7 +1264,6 @@ modifiers_and_name_to_type = {
     (1, 0, "int"): c_int_type, 
     (1, 1, "int"): c_long_type,
     (1, 2, "int"): c_longlong_type,
-    (1, 0, "Py_ssize_t"): c_py_ssize_t_type,
     (1, 0, "float"): c_float_type, 
     (1, 0, "double"): c_double_type,
     (1, 1, "double"): c_longdouble_type,
@@ -1262,7 +1274,11 @@ modifiers_and_name_to_type = {
     (2, 0, "int"): c_sint_type, 
     (2, 1, "int"): c_slong_type,
     (2, 2, "int"): c_slonglong_type,
+
+    (1, 0, "Py_ssize_t"): c_py_ssize_t_type,
     (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
+    (0, 0, "size_t") : c_size_t_type,
+    (1, 0, "size_t") : c_size_t_type,
     
     (1, 0, "long"): c_long_type,
     (1, 0, "short"): c_short_type,
@@ -1380,6 +1396,9 @@ static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x);
 static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x);
 static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b);
 
+static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t);
+static INLINE size_t __pyx_PyInt_AsSize_t(PyObject*);
+
 #define __pyx_PyInt_AsLong(x) (PyInt_CheckExact(x) ? PyInt_AS_LONG(x) : PyInt_AsLong(x))
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
 """ + type_conversion_predeclarations
@@ -1396,6 +1415,31 @@ static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) {
   return ival;
 }
 
+static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) {
+#if PY_VERSION_HEX < 0x02050000
+   if (ival <= (size_t)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
+}
+
+static INLINE size_t __pyx_PyInt_AsSize_t(PyObject* b) {
+   unsigned PY_LONG_LONG val = __pyx_PyInt_AsUnsignedLongLong(b);
+   if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) {
+       return (size_t)-1;
+   } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
+       PyErr_SetString(PyExc_OverflowError, "value too large to convert to size_t");
+       return (size_t)-1;
+   }
+   return val;
+}
+
 static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
    if (x == Py_True) return 1;
    else if ((x == Py_False) | (x == Py_None)) return 0;
index f478a5d5a3cf4d965186ad57880903728b569af2..5d08db6df48298a81d9d1923523ee7c539ff1150 100644 (file)
@@ -14,9 +14,6 @@
 # - Add unicode calls.\r
 # - Add setobject calls.\r
 \r
-cdef extern from "sys/types.h":\r
-    ctypedef unsigned int size_t\r
-\r
 cdef extern from "stdio.h":\r
     ctypedef struct FILE:\r
         pass\r
index 02cf3972c3ae3d4d0c4761145ea5beb8caebcf4f..6d7b8dac180d8e0691c210a90dc190f0351916d2 100644 (file)
@@ -1,6 +1,5 @@
 cdef extern from "Python.h":
-    ctypedef unsigned long size_t
-    
+
     #####################################################################
     # 9.2 Memory Interface
     #####################################################################
index 3de3cb9e2461aae40ea202d6eb0f6d5969de3eb3..6653b74819a9ed26c0a3c66610a9ff1c5a62ecf6 100644 (file)
@@ -1,6 +1,5 @@
 
 cdef extern from "stdlib.h":
-    ctypedef unsigned long size_t 
     void free(void *ptr)
     void *malloc(size_t size)
     void *realloc(void *ptr, size_t size)
diff --git a/tests/run/size_t.pyx b/tests/run/size_t.pyx
new file mode 100644 (file)
index 0000000..55001e2
--- /dev/null
@@ -0,0 +1,23 @@
+__doc__ = u"""
+>>> test(0)
+0
+>>> test(1)
+1
+>>> test(2)
+2
+>>> str(test((1<<32)-1))
+'4294967295'
+
+>>> test(-1) #doctest: +ELLIPSIS
+Traceback (most recent call last):
+    ...
+OverflowError: ...
+
+>>> test(1<<128) #doctest: +ELLIPSIS
+Traceback (most recent call last):
+    ...
+OverflowError: ...
+"""
+
+def test(size_t i):
+    return i