documentation - brief descriptions for bpy api files.
[blender.git] / source / blender / python / intern / bpy_rna_array.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Arystanbek Dyussenov, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/intern/bpy_rna_array.c
24  *  \ingroup pythonintern
25  *
26  * This file deals with array access for 'BPy_PropertyArrayRNA' from bpy_rna.c
27  */
28
29 #include <Python.h>
30
31 #include "RNA_types.h"
32
33 #include "bpy_rna.h"
34 #include "BKE_global.h"
35 #include "MEM_guardedalloc.h"
36
37 #include "RNA_access.h"
38
39 #define MAX_ARRAY_DIMENSION 10
40
41 typedef void (*ItemConvertFunc)(PyObject *, char *);
42 typedef int  (*ItemTypeCheckFunc)(PyObject *);
43 typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *);
44 typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *);
45
46 /*
47   arr[3][4][5]
48           0  1  2  <- dimension index
49 */
50
51 /*
52   arr[2]= x
53
54   py_to_array_index(arraydim=0, arrayoffset=0, index=2)
55         validate_array(lvalue_dim=0)
56         ... make real index ...
57 */
58
59 /* arr[3]=x, self->arraydim is 0, lvalue_dim is 1 */
60 /* Ensures that a python sequence has expected number of items/sub-items and items are of desired type. */
61 static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[],
62                                                            ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix)
63 {
64         Py_ssize_t i;
65
66         /* not the last dimension */
67         if (dim + 1 < totdim) {
68                 /* check that a sequence contains dimsize[dim] items */
69                 const Py_ssize_t seq_size= PySequence_Size(seq);
70                 if (seq_size == -1) {
71                         PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
72                                      error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
73                         return -1;
74                 }
75                 for (i= 0; i < seq_size; i++) {
76                         PyObject *item;
77                         int ok= 1;
78                         item= PySequence_GetItem(seq, i);
79
80                         if (item == NULL) {
81                                 PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
82                                              error_prefix, Py_TYPE(seq)->tp_name, i);
83                                 ok= 0;
84                         }
85                         else if (!PySequence_Check(item)) {
86                                 /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */
87                                 PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s",
88                                              error_prefix, item_type_str, Py_TYPE(item)->tp_name);
89                                 ok= 0;
90                         }
91                         /* arr[3][4][5]
92                            dimsize[1]=4
93                            dimsize[2]=5
94                    
95                            dim=0 */
96                         else if (PySequence_Size(item) != dimsize[dim + 1]) {
97                                 /* BLI_snprintf(error_str, error_str_size, "sequences of dimension %d should contain %d items", (int)dim + 1, (int)dimsize[dim + 1]); */
98                                 PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items",
99                                              error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
100                                 ok= 0;
101                         }
102                         else if (validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1) {
103                                 ok= 0;
104                         }
105
106                         Py_XDECREF(item);
107
108                         if (!ok)
109                                 return -1;
110                 }
111         }
112         else {
113                 /* check that items are of correct type */
114                 const int seq_size= PySequence_Size(seq);
115                 if (seq_size == -1) {
116                         PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
117                                      error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
118                         return -1;
119                 }
120                 for (i= 0; i < seq_size; i++) {
121                         PyObject *item= PySequence_GetItem(seq, i);
122
123                         if (item == NULL) {
124                                 PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
125                                              error_prefix, Py_TYPE(seq)->tp_name, i);
126                                 return -1;
127                         }
128                         else if (!check_item_type(item)) {
129                                 Py_DECREF(item);
130
131                                 /* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */
132                                 PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s",
133                                              error_prefix, item_type_str, Py_TYPE(item)->tp_name);
134                                 return -1;
135                         }
136
137                         Py_DECREF(item);
138                 }
139         }
140
141         return 0; /* ok */
142 }
143
144 /* Returns the number of items in a single- or multi-dimensional sequence. */
145 static int count_items(PyObject *seq, int dim)
146 {
147         int totitem= 0;
148
149         if (dim > 1) {
150                 const Py_ssize_t seq_size= PySequence_Size(seq);
151                 Py_ssize_t i;
152                 for (i= 0; i < seq_size; i++) {
153                         PyObject *item= PySequence_GetItem(seq, i);
154                         if (item) {
155                                 const int tot= count_items(item, dim - 1);
156                                 Py_DECREF(item);
157                                 if (tot != -1) {
158                                         totitem += tot;
159                                 }
160                                 else {
161                                         totitem= -1;
162                                         break;
163                                 }
164                         }
165                         else {
166                                 totitem= -1;
167                                 break;
168                         }
169                 }
170         }
171         else {
172                 totitem= PySequence_Size(seq);
173         }
174
175         return totitem;
176 }
177
178 /* Modifies property array length if needed and PROP_DYNAMIC flag is set. */
179 static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int *totitem, const char *error_prefix)
180 {
181         int dimsize[MAX_ARRAY_DIMENSION];
182         int tot, totdim, len;
183
184         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
185         tot= count_items(rvalue, totdim - lvalue_dim);
186
187         if (tot == -1) {
188                 PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length",
189                              error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
190                 return -1;
191         }
192         else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
193                 if (RNA_property_array_length(ptr, prop) != tot) {
194 #if 0
195                         /* length is flexible */
196                         if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
197                                 /* BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
198                                 PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d",
199                                              error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
200                                 return -1;
201                         }
202 #else
203                         *totitem= tot;
204                         return 0;
205
206 #endif
207                 }
208
209                 len= tot;
210         }
211         else {
212                 /* length is a constraint */
213                 if (!lvalue_dim) {
214                         len= RNA_property_array_length(ptr, prop);
215                 }
216                 /* array item assignment */
217                 else {
218                         int i;
219
220                         len= 1;
221
222                         /* arr[3][4][5]
223
224                            arr[2]= x
225                            dimsize={4, 5}
226                            dimsize[1]= 4
227                            dimsize[2]= 5
228                            lvalue_dim=0, totdim=3
229
230                            arr[2][3]= x
231                            lvalue_dim=1
232
233                            arr[2][3][4]= x
234                            lvalue_dim=2 */
235                         for (i= lvalue_dim; i < totdim; i++)
236                                 len *= dimsize[i];
237                 }
238
239                 if (tot != len) {
240                         /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
241                         PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d",
242                                      error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
243                         return -1;
244                 }
245         }
246
247         *totitem= len;
248
249         return 0;
250 }
251
252 static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix)
253 {
254         int dimsize[MAX_ARRAY_DIMENSION];
255         int totdim= RNA_property_array_dimension(ptr, prop, dimsize);
256
257         /* validate type first because length validation may modify property array length */
258
259         if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1)
260                 return -1;
261
262         return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix);
263 }
264
265 static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
266 {
267         if (!data) {
268                 char value[sizeof(int)];
269
270                 convert_item(item, value);
271                 rna_set_index(ptr, prop, *index, value);
272                 *index= *index + 1;
273         }
274         else {
275                 convert_item(item, data);
276                 data += item_size;
277         }
278
279         return data;
280 }
281
282 static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
283 {
284         int totdim= RNA_property_array_dimension(ptr, prop, NULL);
285         const Py_ssize_t seq_size= PySequence_Size(seq);
286         Py_ssize_t i;
287
288         /* Regarding PySequence_GetItem() failing.
289          *
290          * This should never be NULL since we validated it, _but_ some triky python
291          * developer could write their own sequence type which succeeds on
292          * validating but fails later somehow, so include checks for safety.
293          */
294
295         /* Note that 'data can be NULL' */
296
297         if (seq_size == -1) {
298                 return NULL;
299         }
300
301         for (i= 0; i < seq_size; i++) {
302                 PyObject *item= PySequence_GetItem(seq, i);
303                 if (item) {
304                         if (dim + 1 < totdim) {
305                                 data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
306                         }
307                         else {
308                                 data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
309                         }
310
311                         Py_DECREF(item);
312
313                         /* data may be NULL, but the for loop checks */
314                 }
315                 else {
316                         return NULL;
317                 }
318         }
319
320         return data;
321 }
322
323 static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
324 {
325         /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
326         int totitem;
327         char *data= NULL;
328
329         /*totdim= RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/
330
331         if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
332                 return -1;
333         }
334
335         if (totitem) {
336                 /* note: this code is confusing */
337                 if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) {
338                         /* not freeing allocated mem, RNA_parameter_list_free() will do this */
339                         ParameterDynAlloc *param_alloc= (ParameterDynAlloc *)param_data;
340                         param_alloc->array_tot= (int)totitem;
341                         param_alloc->array= MEM_callocN(item_size * totitem, "py_to_array dyn"); /* freeing param list will free */
342
343                         data= param_alloc->array;
344                 }
345                 else if (param_data) {
346                         data= param_data;
347                 }
348                 else {
349                         data= PyMem_MALLOC(item_size * totitem);
350                 }
351
352                 /* will only fail in very rare cases since we already validated the
353                  * python data, the check here is mainly for completeness. */
354                 if (copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) {
355                         if (param_data==NULL) {
356                                 /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
357                                 rna_set_array(ptr, prop, data);
358                                 PyMem_FREE(data);
359                         }
360                 }
361                 else {
362                         if (param_data==NULL) {
363                                 PyMem_FREE(data);
364                         }
365
366                         PyErr_Format(PyExc_TypeError, "%s internal error parsing sequence of type '%s' after successful validation",
367                                      error_prefix, Py_TYPE(seq)->tp_name);
368                         return -1;
369                 }
370         }
371
372         return 0;
373 }
374
375 static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
376 {
377         int totdim, dimsize[MAX_ARRAY_DIMENSION];
378         int totitem, i;
379
380         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
381
382         /* convert index */
383
384         /* arr[3][4][5]
385
386            arr[2]= x
387            lvalue_dim=0, index= 0 + 2 * 4 * 5
388
389            arr[2][3]= x
390            lvalue_dim=1, index= 40 + 3 * 5 */
391
392         lvalue_dim++;
393
394         for (i= lvalue_dim; i < totdim; i++)
395                 index *= dimsize[i];
396
397         index += arrayoffset;
398
399         if (lvalue_dim == totdim) { /* single item, assign directly */
400                 if (!check_item_type(py)) {
401                         PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s",
402                                      error_prefix, RNA_struct_identifier(ptr->type),
403                                      RNA_property_identifier(prop), item_type_str,
404                                      Py_TYPE(py)->tp_name);
405                         return -1;
406                 }
407                 copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
408         }
409         else {
410                 if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
411                         return -1;
412                 }
413
414                 if (totitem) {
415                         copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
416                 }
417         }
418         return 0;
419 }
420
421 static void py_to_float(PyObject *py, char *data)
422 {
423         *(float*)data= (float)PyFloat_AsDouble(py);
424 }
425
426 static void py_to_int(PyObject *py, char *data)
427 {
428         *(int*)data= (int)PyLong_AsSsize_t(py);
429 }
430
431 static void py_to_bool(PyObject *py, char *data)
432 {
433         *(int*)data= (int)PyObject_IsTrue(py);
434 }
435
436 static int py_float_check(PyObject *py)
437 {
438         /* accept both floats and integers */
439         return PyNumber_Check(py);
440 }
441
442 static int py_int_check(PyObject *py)
443 {
444         /* accept only integers */
445         return PyLong_Check(py);
446 }
447
448 static int py_bool_check(PyObject *py)
449 {
450         return PyBool_Check(py);
451 }
452
453 static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
454 {
455         RNA_property_float_set_index(ptr, prop, index, *(float*)value);
456 }
457
458 static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
459 {
460         RNA_property_int_set_index(ptr, prop, index, *(int*)value);
461 }
462
463 static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
464 {
465         RNA_property_boolean_set_index(ptr, prop, index, *(int*)value);
466 }
467
468 int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
469 {
470         int ret;
471         switch (RNA_property_type(prop)) {
472         case PROP_FLOAT:
473                 ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
474                 break;
475         case PROP_INT:
476                 ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
477                 break;
478         case PROP_BOOLEAN:
479                 ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
480                 break;
481         default:
482                 PyErr_SetString(PyExc_TypeError, "not an array type");
483                 ret= -1;
484         }
485
486         return ret;
487 }
488
489 int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix)
490 {
491         int ret;
492         switch (RNA_property_type(prop)) {
493         case PROP_FLOAT:
494                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_float_check, "float", py_to_float, float_set_index, error_prefix);
495                 break;
496         case PROP_INT:
497                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_int_check, "int", py_to_int, int_set_index, error_prefix);
498                 break;
499         case PROP_BOOLEAN:
500                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix);
501                 break;
502         default:
503                 PyErr_SetString(PyExc_TypeError, "not an array type");
504                 ret= -1;
505         }
506
507         return ret;
508 }
509
510 PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index)
511 {
512         PyObject *item;
513
514         switch (RNA_property_type(prop)) {
515         case PROP_FLOAT:
516                 item= PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index));
517                 break;
518         case PROP_BOOLEAN:
519                 item= PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index));
520                 break;
521         case PROP_INT:
522                 item= PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index));
523                 break;
524         default:
525                 PyErr_SetString(PyExc_TypeError, "not an array type");
526                 item= NULL;
527         }
528
529         return item;
530 }
531
532 #if 0
533 /* XXX this is not used (and never will?) */
534 /* Given an array property, creates an N-dimensional tuple of values. */
535 static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr, PropertyRNA *prop, int dim, int *index)
536 {
537         PyObject *tuple;
538         int i, len;
539         int totdim= RNA_property_array_dimension(ptr, prop, NULL);
540
541         len= RNA_property_multi_array_length(ptr, prop, dim);
542
543         tuple= PyTuple_New(len);
544
545         for (i= 0; i < len; i++) {
546                 PyObject *item;
547
548                 if (dim + 1 < totdim)
549                         item= pyrna_py_from_array_internal(ptr, prop, dim + 1, index);
550                 else {
551                         item= pyrna_array_index(ptr, prop, *index);
552                         *index= *index + 1;
553                 }
554
555                 if (!item) {
556                         Py_DECREF(tuple);
557                         return NULL;
558                 }
559
560                 PyTuple_SET_ITEM(tuple, i, item);
561         }
562
563         return tuple;
564 }
565 #endif
566
567 PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index)
568 {
569         int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len;
570         BPy_PropertyArrayRNA *ret= NULL;
571
572         arraydim= self ? self->arraydim : 0;
573         arrayoffset= self ? self->arrayoffset : 0;
574
575         /* just in case check */
576         len= RNA_property_multi_array_length(ptr, prop, arraydim);
577         if (index >= len || index < 0) {
578                 /* this shouldn't happen because higher level funcs must check for invalid index */
579                 if (G.f & G_DEBUG) printf("pyrna_py_from_array_index: invalid index %d for array with length=%d\n", index, len);
580
581                 PyErr_SetString(PyExc_IndexError, "out of range");
582                 return NULL;
583         }
584
585         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
586
587         if (arraydim + 1 < totdim) {
588                 ret= (BPy_PropertyArrayRNA*)pyrna_prop_CreatePyObject(ptr, prop);
589                 ret->arraydim= arraydim + 1;
590
591                 /* arr[3][4][5]
592
593                    x= arr[2]
594                    index= 0 + 2 * 4 * 5
595
596                    x= arr[2][3]
597                    index= offset + 3 * 5 */
598
599                 for (i= arraydim + 1; i < totdim; i++)
600                         index *= dimsize[i];
601
602                 ret->arrayoffset= arrayoffset + index;
603         }
604         else {
605                 index= arrayoffset + index;
606                 ret= (BPy_PropertyArrayRNA *)pyrna_array_index(ptr, prop, index);
607         }
608
609         return (PyObject*)ret;
610 }
611
612 PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop)
613 {
614         PyObject *ret;
615
616         ret= pyrna_math_object_from_array(ptr, prop);
617
618         /* is this a maths object? */
619         if (ret) return ret;
620
621         return pyrna_prop_CreatePyObject(ptr, prop);
622 }
623
624 /* TODO, multi-dimensional arrays */
625 int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
626 {
627         int len= RNA_property_array_length(ptr, prop);
628         int type;
629         int i;
630
631         if (len==0) /* possible with dynamic arrays */
632                 return 0;
633
634         if (RNA_property_array_dimension(ptr, prop, NULL) > 1) {
635                 PyErr_SetString(PyExc_TypeError, "PropertyRNA - multi dimensional arrays not supported yet");
636                 return -1;
637         }
638
639         type= RNA_property_type(prop);
640
641         switch (type) {
642                 case PROP_FLOAT:
643                 {
644                         float value_f= PyFloat_AsDouble(value);
645                         if (value_f==-1 && PyErr_Occurred()) {
646                                 PyErr_Clear();
647                                 return 0;
648                         }
649                         else {
650                                 float tmp[32];
651                                 float *tmp_arr;
652
653                                 if (len * sizeof(float) > sizeof(tmp)) {
654                                         tmp_arr= PyMem_MALLOC(len * sizeof(float));
655                                 }
656                                 else {
657                                         tmp_arr= tmp;
658                                 }
659
660                                 RNA_property_float_get_array(ptr, prop, tmp_arr);
661
662                                 for (i=0; i<len; i++) {
663                                         if (tmp_arr[i] == value_f) {
664                                                 break;
665                                         }
666                                 }
667
668                                 if (tmp_arr != tmp)
669                                         PyMem_FREE(tmp_arr);
670
671                                 return i<len ? 1 : 0;
672                         }
673                         break;
674                 }
675                 case PROP_BOOLEAN:
676                 case PROP_INT:
677                 {
678                         int value_i= PyLong_AsSsize_t(value);
679                         if (value_i==-1 && PyErr_Occurred()) {
680                                 PyErr_Clear();
681                                 return 0;
682                         }
683                         else {
684                                 int tmp[32];
685                                 int *tmp_arr;
686
687                                 if (len * sizeof(int) > sizeof(tmp)) {
688                                         tmp_arr= PyMem_MALLOC(len * sizeof(int));
689                                 }
690                                 else {
691                                         tmp_arr= tmp;
692                                 }
693
694                                 if (type==PROP_BOOLEAN)
695                                         RNA_property_boolean_get_array(ptr, prop, tmp_arr);
696                                 else
697                                         RNA_property_int_get_array(ptr, prop, tmp_arr);
698
699                                 for (i=0; i<len; i++) {
700                                         if (tmp_arr[i] == value_i) {
701                                                 break;
702                                         }
703                                 }
704
705                                 if (tmp_arr != tmp)
706                                         PyMem_FREE(tmp_arr);
707
708                                 return i<len ? 1 : 0;
709                         }
710                         break;
711                 }
712         }
713
714         /* should never reach this */
715         PyErr_SetString(PyExc_TypeError, "PropertyRNA - type not in float/bool/int");
716         return -1;
717 }