[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34140] trunk/blender/source/blender/ python/intern/bpy_rna.c: py/ rna api speedup for collection slicing in all cases, rather then having an exception for [:].

Campbell Barton ideasman42 at gmail.com
Fri Jan 7 06:33:31 CET 2011


Revision: 34140
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=34140
Author:   campbellbarton
Date:     2011-01-07 05:33:30 +0000 (Fri, 07 Jan 2011)
Log Message:
-----------
py/rna api speedup for collection slicing in all cases, rather then having an exception for [:].
- avoid looping over the entire collection unless a negative index is used.
- dont use the get index function for building the slice list, instead loop over the collection until the stop value. 

Modified Paths:
--------------
    trunk/blender/source/blender/python/intern/bpy_rna.c

Modified: trunk/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.c	2011-01-07 04:38:31 UTC (rev 34139)
+++ trunk/blender/source/blender/python/intern/bpy_rna.c	2011-01-07 05:33:30 UTC (rev 34140)
@@ -93,7 +93,7 @@
 #ifdef USE_MATHUTILS
 #include "../generic/mathutils.h" /* so we can have mathutils callbacks */
 
-static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length);
+static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length);
 static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback);
 
 /* bpyrna vector/euler/quat callbacks */
@@ -1470,43 +1470,45 @@
 }
 /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */
 
-static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, int start, int stop, int len)
+static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop)
 {
-	if(start == 0 && stop == len) {
-		/* faster */
-		return pyrna_prop_collection_values(self);
-	}
-	else {
-		PointerRNA *ptr= &self->ptr;
-		PropertyRNA *prop= self->prop;
+	int count= 0;
 
-		PointerRNA newptr;
-		PyObject *list = PyList_New(stop - start);
-		int count;
+	PyObject *list= PyList_New(0);
+	PyObject *item;
 
-		start = MIN2(start,stop); /* values are clamped from  */
+	/* first loop up-until the start */
+	CollectionPropertyIterator rna_macro_iter;
+	for(RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) {
+		/* PointerRNA itemptr= rna_macro_iter.ptr; */
+		if(count == start) {
+			break;
+		}
+		count++;
+	}
 
-		for(count = start; count < stop; count++) {
-			if(RNA_property_collection_lookup_int(ptr, prop, count - start, &newptr)) {
-				PyList_SET_ITEM(list, count - start, pyrna_struct_CreatePyObject(&newptr));
-			}
-			else {
-				Py_DECREF(list);
+	/* add items until stop */
+	for(; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) {
+		item= pyrna_struct_CreatePyObject(&rna_macro_iter.ptr);
+		PyList_Append(list, item);
+		Py_DECREF(item);
 
-				PyErr_Format(PyExc_RuntimeError, "bpy_prop_collection[%d:%d]: internal error RNA_property_collection_lookup_int(...) failed with array index in range.", start, stop);
-				return NULL;
-			}
+		count++;
+		if(count == stop) {
+			break;
 		}
+	}
 
-		return list;
-	}
+	RNA_property_collection_end(&rna_macro_iter);
+
+	return list;
 }
 
 /* TODO - dimensions
  * note: could also use pyrna_prop_array_to_py_index(self, count) in a loop but its a lot slower
  * since at the moment it reads (and even allocates) the entire array for each index.
  */
-static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length)
+static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length)
 {
 	int count, totdim;
 
@@ -1592,30 +1594,38 @@
 		return pyrna_prop_collection_subscript_int(self, i);
 	}
 	else if (PySlice_Check(key)) {
+		PySliceObject *key_slice= (PySliceObject *)key;
 		Py_ssize_t step= 1;
 
-		if(((PySliceObject *)key)->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
+		if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
 			return NULL;
 		}
 		else if (step != 1) {
 			PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
 			return NULL;
 		}
-		else if(((PySliceObject *)key)->start == Py_None && ((PySliceObject *)key)->stop == Py_None) {
-			return pyrna_prop_collection_values(self);
+		else if(key_slice->start == Py_None && key_slice->stop == Py_None) {
+			return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
 		}
 		else {
-			int len= RNA_property_collection_length(&self->ptr, self->prop);
-			Py_ssize_t start, stop, slicelength;
+			Py_ssize_t start= 0, stop= PY_SSIZE_T_MAX;
 
-			if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
-				return NULL;
+			/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
+			if(key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start))	return NULL;
+			if(key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop))		return NULL;
 
-			if (slicelength <= 0) {
+			if(start < 0 || stop < 0) {
+				/* only get the length for negative values */
+				Py_ssize_t len= (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop);
+				if(start < 0) start += len;
+				if(stop < 0) start += len;
+			}
+
+			if (stop - start <= 0) {
 				return PyList_New(0);
 			}
 			else {
-				return pyrna_prop_collection_subscript_slice(self, start, stop, len);
+				return pyrna_prop_collection_subscript_slice(self, start, stop);
 			}
 		}
 	}
@@ -1638,17 +1648,18 @@
 	}
 	else if (PySlice_Check(key)) {
 		Py_ssize_t step= 1;
+		PySliceObject *key_slice= (PySliceObject *)key;
 
-		if(((PySliceObject *)key)->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
+		if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
 			return NULL;
 		}
 		else if (step != 1) {
 			PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported");
 			return NULL;
 		}
-		else if(((PySliceObject *)key)->start == Py_None && ((PySliceObject *)key)->stop == Py_None) {
+		else if(key_slice->start == Py_None && key_slice->stop == Py_None) {
 			/* note, no significant advantage with optimizing [:] slice as with collections but include here for consistency with collection slice func */
-			int len= pyrna_prop_array_length(self);
+			Py_ssize_t len= (Py_ssize_t)pyrna_prop_array_length(self);
 			return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len);
 		}
 		else {
@@ -3153,17 +3164,8 @@
 
 static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self)
 {
-	PyObject *ret= PyList_New(0);
-	PyObject *item;
-	
-	RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
-		item = pyrna_struct_CreatePyObject(&itemptr);
-		PyList_Append(ret, item);
-		Py_DECREF(item);
-	}
-	RNA_PROP_END;
-
-	return ret;
+	/* re-use slice*/
+	return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
 }
 
 static char pyrna_struct_get_doc[] =




More information about the Bf-blender-cvs mailing list