Fix leak in BPy_BMElem_PySeq_As_Array
Also add BPy_BMElem_PySeq_As_Array_FAST
This commit is contained in:
parent
d226a4ba6d
commit
376e4c945e
|
@ -3759,106 +3759,120 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
|
|||
*
|
||||
* The 'bm_r' value is assigned when empty, and used when set.
|
||||
*/
|
||||
void *BPy_BMElem_PySeq_As_Array_FAST(
|
||||
BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
|
||||
const char htype,
|
||||
const bool do_unique_check, const bool do_bm_check,
|
||||
const char *error_prefix)
|
||||
{
|
||||
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
|
||||
const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
|
||||
Py_ssize_t i;
|
||||
|
||||
BPy_BMElem *item;
|
||||
BMElem **alloc;
|
||||
|
||||
*r_size = 0;
|
||||
|
||||
if (seq_len < min || seq_len > max) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: sequence incorrect size, expected [%d - %d], given %d",
|
||||
error_prefix, min, max, seq_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* from now on, use goto */
|
||||
alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
|
||||
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
|
||||
|
||||
if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: expected %.200s, not '%.200s'",
|
||||
error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
|
||||
goto err_cleanup;
|
||||
}
|
||||
else if (!BPY_BM_IS_VALID(item)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: %d %s has been removed",
|
||||
error_prefix, i, Py_TYPE(item)->tp_name);
|
||||
goto err_cleanup;
|
||||
}
|
||||
/* trick so we can ensure all items have the same mesh,
|
||||
* and allows us to pass the 'bm' as NULL. */
|
||||
else if (do_bm_check && (bm && bm != item->bm)) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"%s: %d %s is from another mesh",
|
||||
error_prefix, i, BPy_BMElem_StringFromHType(htype));
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (bm == NULL) {
|
||||
bm = item->bm;
|
||||
}
|
||||
|
||||
alloc[i] = item->ele;
|
||||
|
||||
if (do_unique_check) {
|
||||
BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_unique_check) {
|
||||
/* check for double verts! */
|
||||
bool ok = true;
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
/* ensure we don't leave this enabled */
|
||||
BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
|
||||
}
|
||||
|
||||
if (ok == false) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"%s: found the same %.200s used multiple times",
|
||||
error_prefix, BPy_BMElem_StringFromHType(htype));
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
*r_size = seq_len;
|
||||
if (r_bm) *r_bm = bm;
|
||||
return alloc;
|
||||
|
||||
err_cleanup:
|
||||
PyMem_FREE(alloc);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void *BPy_BMElem_PySeq_As_Array(
|
||||
BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
|
||||
const char htype,
|
||||
const bool do_unique_check, const bool do_bm_check,
|
||||
const char *error_prefix)
|
||||
{
|
||||
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
|
||||
PyObject *seq_fast;
|
||||
*r_size = 0;
|
||||
PyObject *ret;
|
||||
|
||||
if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
Py_ssize_t seq_len;
|
||||
Py_ssize_t i;
|
||||
|
||||
BPy_BMElem *item;
|
||||
BMElem **alloc;
|
||||
ret = BPy_BMElem_PySeq_As_Array_FAST(
|
||||
r_bm, seq_fast, min, max, r_size,
|
||||
htype,
|
||||
do_unique_check, do_bm_check,
|
||||
error_prefix);
|
||||
|
||||
seq_len = PySequence_Fast_GET_SIZE(seq_fast);
|
||||
|
||||
if (seq_len < min || seq_len > max) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: sequence incorrect size, expected [%d - %d], given %d",
|
||||
error_prefix, min, max, seq_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* from now on, use goto */
|
||||
alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
|
||||
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
|
||||
|
||||
if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: expected %.200s, not '%.200s'",
|
||||
error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
|
||||
goto err_cleanup;
|
||||
}
|
||||
else if (!BPY_BM_IS_VALID(item)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: %d %s has been removed",
|
||||
error_prefix, i, Py_TYPE(item)->tp_name);
|
||||
goto err_cleanup;
|
||||
}
|
||||
/* trick so we can ensure all items have the same mesh,
|
||||
* and allows us to pass the 'bm' as NULL. */
|
||||
else if (do_bm_check && (bm && bm != item->bm)) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"%s: %d %s is from another mesh",
|
||||
error_prefix, i, BPy_BMElem_StringFromHType(htype));
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (bm == NULL) {
|
||||
bm = item->bm;
|
||||
}
|
||||
|
||||
alloc[i] = item->ele;
|
||||
|
||||
if (do_unique_check) {
|
||||
BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_unique_check) {
|
||||
/* check for double verts! */
|
||||
bool ok = true;
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
/* ensure we don't leave this enabled */
|
||||
BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
|
||||
}
|
||||
|
||||
if (ok == false) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"%s: found the same %.200s used multiple times",
|
||||
error_prefix, BPy_BMElem_StringFromHType(htype));
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(seq_fast);
|
||||
*r_size = seq_len;
|
||||
if (r_bm) *r_bm = bm;
|
||||
return alloc;
|
||||
|
||||
err_cleanup:
|
||||
Py_DECREF(seq_fast);
|
||||
PyMem_FREE(alloc);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(seq_fast);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
|
||||
{
|
||||
Py_ssize_t i;
|
||||
|
|
|
@ -158,6 +158,11 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm);
|
|||
|
||||
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */
|
||||
|
||||
void *BPy_BMElem_PySeq_As_Array_FAST(
|
||||
BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
|
||||
const char htype,
|
||||
const bool do_unique_check, const bool do_bm_check,
|
||||
const char *error_prefix);
|
||||
void *BPy_BMElem_PySeq_As_Array(
|
||||
BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
|
||||
const char htype,
|
||||
|
|
Loading…
Reference in New Issue