[Python-checkins] r51576 - in python/branches/p3yk-noslice: Modules/_ctypes/_ctypes.c TODO

thomas.wouters python-checkins at python.org
Fri Aug 25 01:37:56 CEST 2006


Author: thomas.wouters
Date: Fri Aug 25 01:37:55 2006
New Revision: 51576

Modified:
   python/branches/p3yk-noslice/Modules/_ctypes/_ctypes.c
   python/branches/p3yk-noslice/TODO
Log:

Add sliceobject support to ctypes objects. All tests pass now. ctypes
objects still lack extended slice support, and the Pointer slicing is
somewhat insane (by nature.)



Modified: python/branches/p3yk-noslice/Modules/_ctypes/_ctypes.c
==============================================================================
--- python/branches/p3yk-noslice/Modules/_ctypes/_ctypes.c	(original)
+++ python/branches/p3yk-noslice/Modules/_ctypes/_ctypes.c	Fri Aug 25 01:37:55 2006
@@ -3757,6 +3757,74 @@
 	return (PyObject *)np;
 }
 
+static PyObject *
+Array_subscript(PyObject *_self, PyObject *item)
+{
+	CDataObject *self = (CDataObject *)_self;
+
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+		if (i < 0)
+			i += self->b_length;
+		return Array_item(_self, i);
+	}
+	else if PySlice_Check(item) {
+		StgDictObject *stgdict, *itemdict;
+		PyObject *proto;
+		PyListObject *np;
+		Py_ssize_t start, stop, step, slicelen, i;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item,
+					 self->b_length, &start, &stop,
+					 &step, &slicelen) < 0) {
+			return NULL;
+		}
+		if (step != 1) {
+			PyErr_Format(PyExc_TypeError, "slice-steps other "
+				"than 1 not supported (%zd given)", step);
+			return NULL;
+		}
+		
+		stgdict = PyObject_stgdict((PyObject *)self);
+		assert(stgdict); /* Cannot be NULL for array object instances */
+		proto = stgdict->proto;
+		itemdict = PyType_stgdict(proto);
+		assert(itemdict); /* proto is the item type of the array, a
+				     ctypes type, so this cannot be NULL */
+
+		if (itemdict->getfunc == getentry("c")->getfunc) {
+			char *ptr = (char *)self->b_ptr;
+			return PyString_FromStringAndSize(ptr + start,
+							  slicelen);
+#ifdef CTYPES_UNICODE
+		} else if (itemdict->getfunc == getentry("u")->getfunc) {
+			wchar_t *ptr = (wchar_t *)self->b_ptr;
+			return PyUnicode_FromWideChar(ptr + start,
+						      slicelen);
+#endif
+		}
+
+		np = (PyListObject *) PyList_New(slicelen);
+		if (np == NULL)
+			return NULL;
+
+		for (i = 0; i < slicelen; i++) {
+			PyObject *v = Array_item(_self, i+start);
+			PyList_SET_ITEM(np, i, v);
+		}
+		return (PyObject *)np;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError, 
+				"indices must be integers");
+		return NULL;
+	}
+
+}
+
 static int
 Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
@@ -3828,6 +3896,69 @@
 	return 0;
 }
 
+static int
+Array_ass_subscript(PyObject *_self, PyObject *item, PyObject *value)
+{
+	CDataObject *self = (CDataObject *)_self;
+	
+	if (value == NULL) {
+		PyErr_SetString(PyExc_TypeError,
+				"Array does not support item deletion");
+		return -1;
+	}
+
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		
+		if (i == -1 && PyErr_Occurred())
+			return -1;
+		if (i < 0)
+			i += self->b_length;
+		return Array_ass_item(_self, i, value);
+	}
+	else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelen, otherlen, i;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item,
+					 self->b_length, &start, &stop,
+					 &step, &slicelen) < 0) {
+			return -1;
+		}
+		/* XXX(twouters) fix this */
+		if (step != 1) {
+			PyErr_Format(PyExc_TypeError, "slice-steps other "
+				"than 1 not supported (%zd given)", step);
+			return -1;
+		}
+		if ((step < 0 && start < stop) ||
+		    (step > 0 && start > stop))
+			stop = start;
+
+		otherlen = PySequence_Length(value);
+		if (otherlen != slicelen) {
+			PyErr_SetString(PyExc_ValueError,
+				"Can only assign sequence of same size");
+			return -1;
+		}
+		for (i = 0; i < otherlen; i++) {
+			PyObject *item = PySequence_GetItem(value, i);
+			int result;
+			if (item == NULL)
+				return -1;
+			result = Array_ass_item(_self, i+start, item);
+			Py_DECREF(item);
+			if (result == -1)
+				return -1;
+		}
+		return 0;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"indices must be integer");
+		return -1;
+	}
+}
+
 static Py_ssize_t
 Array_length(PyObject *_self)
 {
@@ -3849,6 +3980,12 @@
 	0,					/* sq_inplace_repeat; */
 };
 
+static PyMappingMethods Array_as_mapping = {
+	Array_length,
+	Array_subscript,
+	Array_ass_subscript,
+};
+
 PyTypeObject Array_Type = {
 	PyObject_HEAD_INIT(NULL)
 	0,
@@ -3863,7 +4000,7 @@
 	0,					/* tp_repr */
 	0,					/* tp_as_number */
 	&Array_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&Array_as_mapping,			/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */
@@ -4349,6 +4486,94 @@
 	return (PyObject *)np;
 }
 
+static PyObject *
+Pointer_subscript(PyObject *_self, PyObject *item)
+{
+	CDataObject *self = (CDataObject *)_self;
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+		return Pointer_item(_self, i);
+	}
+	else if (PySlice_Check(item)) {
+		/* Since pointers have no length, we cannot use any
+		   of the PySlice API functions, and have to fiddle
+		   with the attributes directly */
+		PySliceObject *slice = (PySliceObject *)item;
+		Py_ssize_t start, stop;
+		PyListObject *np;
+		StgDictObject *stgdict, *itemdict;
+		PyObject *proto;
+		Py_ssize_t i, len;
+
+		if (slice->step != Py_None) {
+			Py_ssize_t step = PyNumber_AsSsize_t(slice->step,
+							PyExc_IndexError);
+			if (step == -1 && PyErr_Occurred())
+				return NULL;
+			if (step != 1) {
+				PyErr_Format(PyExc_TypeError,
+					     "unsupported step size %zd",
+					     step);
+				return NULL;
+			}
+		}
+		if (slice->start == Py_None)
+			start = 0;
+		else {
+			start = PyNumber_AsSsize_t(slice->start,
+						   PyExc_IndexError);
+			if (start == -1 && PyErr_Occurred())
+				return NULL;
+			if (start < 0)
+				start = 0;
+		}
+		if (slice->stop == Py_None)
+			stop = PY_SSIZE_T_MAX;
+		else {
+			stop = PyNumber_AsSsize_t(slice->stop,
+						  PyExc_IndexError);
+			if (stop == -1 && PyErr_Occurred())
+				return NULL;
+		}
+		if (stop < start)
+			stop = start;
+		len = stop - start;
+
+		stgdict = PyObject_stgdict((PyObject *)self);
+		assert(stgdict); /* Cannot be NULL fr pointer instances */
+		proto = stgdict->proto;
+		assert(proto);
+		itemdict = PyType_stgdict(proto);
+		assert(itemdict);
+		if (itemdict->getfunc == getentry("c")->getfunc) {
+			char *ptr = *(char **)self->b_ptr;
+			return PyString_FromStringAndSize(ptr + start, len);
+#ifdef CTYPES_UNICODE
+		} else if (itemdict->getfunc == getentry("u")->getfunc) {
+			wchar_t *ptr = *(wchar_t **)self->b_ptr;
+			return PyUnicode_FromWideChar(ptr + start, len);
+#endif
+		}
+
+		np = (PyListObject *) PyList_New(len);
+		if (np == NULL)
+			return NULL;
+
+		for (i = 0; i < len; i++) {
+			PyObject *v = Pointer_item(_self, i+start);
+			PyList_SET_ITEM(np, i, v);
+		}
+		return (PyObject *)np;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"Pointer indices must be integer");
+		return NULL;
+	}
+}
+
 static PySequenceMethods Pointer_as_sequence = {
 	0,					/* inquiry sq_length; */
 	0,					/* binaryfunc sq_concat; */
@@ -4363,6 +4588,11 @@
 	0,					/* intargfunc sq_inplace_repeat; */
 };
 
+static PyMappingMethods Pointer_as_mapping = {
+	0,
+	Pointer_subscript,
+};
+
 static int
 Pointer_nonzero(CDataObject *self)
 {
@@ -4396,7 +4626,7 @@
 	0,					/* tp_repr */
 	&Pointer_as_number,			/* tp_as_number */
 	&Pointer_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&Pointer_as_mapping,			/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */

Modified: python/branches/p3yk-noslice/TODO
==============================================================================
--- python/branches/p3yk-noslice/TODO	(original)
+++ python/branches/p3yk-noslice/TODO	Fri Aug 25 01:37:55 2006
@@ -6,7 +6,7 @@
     buffer
     mmap.mmap
     structseq
- - Add extended slicing (or at least slice-object support) to ctypes objects
+ - Add actual *extended* slicing to ctypes objects
  - Make list's mp_[ass_]subscr not depend on list_[ass]slice
  - Remove slice API (or emulate it ontop of sliceobject API)
  - Further remove slice/ass_slice PySequenceMethod hooks


More information about the Python-checkins mailing list