diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-01-07 08:33:30 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-01-07 08:33:30 +0300 |
commit | 0f2089afa12832d48b9953d317ade4a12d3c5d93 (patch) | |
tree | 0666bd5d21a10447931b89500a5c96b01a9dff28 /source | |
parent | 5d74d65106937608de2833428f7b34979aca3c4b (diff) |
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.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 98 |
1 files changed, 50 insertions, 48 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 74dcc811185..881d71d811f 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -93,7 +93,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item #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_collection_subscript_str(BPy_PropertyRNA *self, cons } /* 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 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject 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 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject } 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_items(BPy_PropertyRNA *self) 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[] = |