Blender V5.0
py_capi_rna.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
14#define PY_SSIZE_T_CLEAN
15
16#include <Python.h>
17
18#include "py_capi_rna.hh"
19
20#include "BLI_bitmap.h"
21#include "BLI_dynstr.h"
22
23#include "RNA_access.hh"
24
25#include "MEM_guardedalloc.h"
26
27/* -------------------------------------------------------------------- */
30
32{
33 DynStr *dynstr = BLI_dynstr_new();
34
35 /* We can't compare with the first element in the array
36 * since it may be a category (without an identifier). */
37 for (bool is_first = true; item->identifier; item++) {
38 if (item->identifier[0]) {
39 BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier);
40 is_first = false;
41 }
42 }
43
44 char *cstring = BLI_dynstr_get_cstring(dynstr);
45 BLI_dynstr_free(dynstr);
46 return cstring;
47}
48
50
51/* -------------------------------------------------------------------- */
54
56 const char *identifier,
57 int *r_value,
58 const char *error_prefix)
59{
60 if (RNA_enum_value_from_id(item, identifier, r_value) == 0) {
61 const char *enum_str = pyrna_enum_repr(item);
62 PyErr_Format(
63 PyExc_ValueError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str);
64 MEM_freeN(enum_str);
65 return -1;
66 }
67
68 return 0;
69}
70
72 PyObject *value,
73 int type_size,
74 bool type_convert_sign,
75 int bitmap_size,
76 const char *error_prefix)
77{
78 BLI_assert(PySet_Check(value));
79 BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__);
80
81 if (PySet_GET_SIZE(value) > 0) {
82 /* Set looping. */
83 PyObject *it = PyObject_GetIter(value);
84 PyObject *key;
85 while ((key = PyIter_Next(it))) {
86 /* Borrow from the set. */
87 Py_DECREF(key);
88
89 const char *param = PyUnicode_AsUTF8(key);
90 if (param == nullptr) {
91 PyErr_Format(PyExc_TypeError,
92 "%.200s expected a string, not %.200s",
93 error_prefix,
94 Py_TYPE(key)->tp_name);
95 break;
96 }
97
98 int ret;
99 if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) {
100 break;
101 }
102
103 int index = ret;
104
105 if (type_convert_sign) {
106 if (type_size == 2) {
107 union {
108 signed short as_signed;
109 ushort as_unsigned;
110 } ret_convert;
111 ret_convert.as_signed = (signed short)ret;
112 index = int(ret_convert.as_unsigned);
113 }
114 else if (type_size == 1) {
115 union {
116 signed char as_signed;
117 uchar as_unsigned;
118 } ret_convert;
119 ret_convert.as_signed = (signed char)ret;
120 index = int(ret_convert.as_unsigned);
121 }
122 else {
124 }
125 }
126 BLI_assert(index < bitmap_size);
127 BLI_BITMAP_ENABLE(bitmap, index);
128 }
129 Py_DECREF(it);
130
131 if (key) {
132 MEM_freeN(bitmap);
133 bitmap = nullptr;
134 }
135 }
136
137 return bitmap;
138}
139
141 PyObject *value,
142 int *r_value,
143 const char *error_prefix)
144{
145 BLI_assert(PySet_Check(value));
146 /* Set of enum items, concatenate all values with OR. */
147 int flag = 0;
148
149 *r_value = 0;
150
151 PyObject *key = nullptr;
152 if (PySet_GET_SIZE(value) > 0) {
153 /* Set looping. */
154 PyObject *it = PyObject_GetIter(value);
155 while ((key = PyIter_Next(it))) {
156 /* Borrow from the set. */
157 Py_DECREF(key);
158
159 const char *param = PyUnicode_AsUTF8(key);
160 if (param == nullptr) {
161 PyErr_Format(PyExc_TypeError,
162 "%.200s expected a string, not %.200s",
163 error_prefix,
164 Py_TYPE(key)->tp_name);
165 break;
166 }
167
168 int ret;
169 if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) {
170 break;
171 }
172
173 flag |= ret;
174 }
175 Py_DECREF(it);
176 if (key) {
177 return -1;
178 }
179 }
180
181 *r_value = flag;
182 return 0;
183}
184
185PyObject *pyrna_enum_bitfield_as_set(const EnumPropertyItem *items, int value)
186{
187 PyObject *ret = PySet_New(nullptr);
188 const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
189
190 if (RNA_enum_bitflag_identifiers(items, value, identifier)) {
191 PyObject *item;
192 int index;
193 for (index = 0; identifier[index]; index++) {
194 item = PyUnicode_FromString(identifier[index]);
195 PySet_Add(ret, item);
196 Py_DECREF(item);
197 }
198 }
199
200 return ret;
201}
202
204
205/* -------------------------------------------------------------------- */
208
209int pyrna_enum_value_parse_string(PyObject *o, void *p)
210{
211 const char *identifier = PyUnicode_AsUTF8(o);
212 if (identifier == nullptr) {
213 PyErr_Format(PyExc_TypeError, "expected a string enum, not %.200s", Py_TYPE(o)->tp_name);
214 return 0;
215 }
216 BPy_EnumProperty_Parse *parse_data = static_cast<BPy_EnumProperty_Parse *>(p);
218 parse_data->items, identifier, &parse_data->value, "enum identifier") == -1)
219 {
220 return 0;
221 }
222
223 parse_data->value_orig = o;
224 parse_data->is_set = true;
225 return 1;
226}
227
228int pyrna_enum_bitfield_parse_set(PyObject *o, void *p)
229{
230 if (!PySet_Check(o)) {
231 PyErr_Format(PyExc_TypeError, "expected a set, not %.200s", Py_TYPE(o)->tp_name);
232 return 0;
233 }
234
235 BPy_EnumProperty_Parse *parse_data = static_cast<BPy_EnumProperty_Parse *>(p);
237 parse_data->items, o, &parse_data->value, "enum identifier set") == -1)
238 {
239 return 0;
240 }
241 parse_data->value_orig = o;
242 parse_data->is_set = true;
243 return 1;
244}
245
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:37
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition BLI_bitmap.h:78
unsigned int BLI_bitmap
Definition BLI_bitmap.h:13
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.cc:37
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
unsigned char uchar
unsigned short ushort
Read Guarded memory(de)allocation.
#define RNA_ENUM_BITFLAG_SIZE
Definition RNA_types.hh:222
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int pyrna_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value, const char *error_prefix)
int pyrna_enum_bitfield_parse_set(PyObject *o, void *p)
int pyrna_enum_bitfield_from_set(const EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix)
PyObject * pyrna_enum_bitfield_as_set(const EnumPropertyItem *items, int value)
BLI_bitmap * pyrna_enum_bitmap_from_set(const EnumPropertyItem *items, PyObject *value, int type_size, bool type_convert_sign, int bitmap_size, const char *error_prefix)
char * pyrna_enum_repr(const EnumPropertyItem *item)
int pyrna_enum_value_parse_string(PyObject *o, void *p)
Py_DECREF(oname)
return ret
int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item, const int value, const char **r_identifier)
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
const EnumPropertyItem * items
const char * identifier
Definition RNA_types.hh:657
uint8_t flag
Definition wm_window.cc:145