Blender V5.0
idprop_utils.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
8
9#include <algorithm>
10#include <cstdio>
11#include <cstring>
12
13#include "BLI_dynstr.h"
14#include "BLI_listbase.h"
15#include "BLI_string.h"
16
17#include "DNA_ID.h"
18
19#include "BKE_idprop.hh"
20#include "BKE_idtype.hh"
21
22#include "MEM_guardedalloc.h"
23
24#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
25
26/* -------------------------------------------------------------------- */
34
35struct ReprState {
36 void (*str_append_fn)(void *user_data, const char *str, uint str_len);
37 void *user_data;
38 /* Big enough to format any primitive type. */
39 char buf[128];
40};
41
43 const char *str,
44 const uint str_len,
45 bool quote)
46{
47 if (quote) {
48 state->str_append_fn(state->user_data, "\"", 1);
49 }
50 uint i_prev = 0, i = 0;
51 while (i < str_len) {
52 const char c = str[i];
53 if (c == '"') {
54 if (i_prev != i) {
55 state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
56 }
57 state->str_append_fn(state->user_data, "\\\"", 2);
58 i_prev = i + 1;
59 }
60 else if (c == '\\') {
61 if (i_prev != i) {
62 state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
63 }
64 state->str_append_fn(state->user_data, "\\\\", 2);
65 i_prev = i + 1;
66 }
67 else if (c < 32) {
68 if (i_prev != i) {
69 state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
70 }
71 char buf[5];
72 uint len = uint(SNPRINTF_RLEN(buf, "\\x%02x", c));
73 BLI_assert(len == 4);
74 state->str_append_fn(state->user_data, buf, len);
75 i_prev = i + 1;
76 }
77 i++;
78 }
79 state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
80 if (quote) {
81 state->str_append_fn(state->user_data, "\"", 1);
82 }
83}
84
86{
87/* NOTE: 'strlen' will be calculated at compile time for literals. */
88#define STR_APPEND_STR(str) state->str_append_fn(state->user_data, str, uint(strlen(str)))
89
90#define STR_APPEND_STR_QUOTE(str) idp_str_append_escape(state, str, uint(strlen(str)), true)
91#define STR_APPEND_STR_LEN_QUOTE(str, str_len) idp_str_append_escape(state, str, str_len, true)
92
93#define STR_APPEND_FMT(format, ...) \
94 state->str_append_fn( \
95 state->user_data, state->buf, uint(SNPRINTF_RLEN(state->buf, format, __VA_ARGS__)))
96
97 switch (prop->type) {
98 case IDP_STRING: {
99 STR_APPEND_STR_LEN_QUOTE(IDP_string_get(prop), uint(std::max(0, prop->len - 1)));
100 break;
101 }
102 case IDP_INT: {
103 if (const IDPropertyUIDataEnumItem *item = prop->ui_data ? IDP_EnumItemFind(prop) : nullptr)
104 {
105 STR_APPEND_STR_QUOTE(item->name);
106 }
107 else {
108 STR_APPEND_FMT("%d", IDP_int_get(prop));
109 }
110 break;
111 }
112 case IDP_FLOAT: {
113 STR_APPEND_FMT("%g", double(IDP_float_get(prop)));
114 break;
115 }
116 case IDP_DOUBLE: {
117 STR_APPEND_FMT("%g", IDP_double_get(prop));
118 break;
119 }
120 case IDP_BOOLEAN: {
121 STR_APPEND_FMT("%s", IDP_bool_get(prop) ? "True" : "False");
122 break;
123 }
124 case IDP_ARRAY: {
125 STR_APPEND_STR("[");
126 switch (prop->subtype) {
127 case IDP_INT:
128 for (const int *v = static_cast<const int *>(prop->data.pointer), *v_end = v + prop->len;
129 v != v_end;
130 v++)
131 {
132 if (v != prop->data.pointer) {
133 STR_APPEND_STR(", ");
134 }
135 STR_APPEND_FMT("%d", *v);
136 }
137 break;
138 case IDP_FLOAT:
139 for (const float *v = static_cast<const float *>(prop->data.pointer),
140 *v_end = v + prop->len;
141 v != v_end;
142 v++)
143 {
144 if (v != prop->data.pointer) {
145 STR_APPEND_STR(", ");
146 }
147 STR_APPEND_FMT("%g", double(*v));
148 }
149 break;
150 case IDP_DOUBLE:
151 for (const double *v = static_cast<const double *>(prop->data.pointer),
152 *v_end = v + prop->len;
153 v != v_end;
154 v++)
155 {
156 if (v != prop->data.pointer) {
157 STR_APPEND_STR(", ");
158 }
159 STR_APPEND_FMT("%g", *v);
160 }
161 break;
162 case IDP_BOOLEAN:
163 for (const double *v = static_cast<const double *>(prop->data.pointer),
164 *v_end = v + prop->len;
165 v != v_end;
166 v++)
167 {
168 if (v != prop->data.pointer) {
169 STR_APPEND_STR(", ");
170 }
171 STR_APPEND_FMT("%s", IDP_bool_get(prop) ? "True" : "False");
172 }
173 break;
174 }
175 STR_APPEND_STR("]");
176 break;
177 }
178 case IDP_IDPARRAY: {
179 STR_APPEND_STR("[");
180 for (const IDProperty *v = static_cast<const IDProperty *>(prop->data.pointer),
181 *v_end = v + prop->len;
182 v != v_end;
183 v++)
184 {
185 if (v != prop->data.pointer) {
186 STR_APPEND_STR(", ");
187 }
189 }
190 STR_APPEND_STR("]");
191 break;
192 }
193 case IDP_GROUP: {
194 STR_APPEND_STR("{");
195 LISTBASE_FOREACH (const IDProperty *, subprop, &prop->data.group) {
196 if (subprop != prop->data.group.first) {
197 STR_APPEND_STR(", ");
198 }
199 STR_APPEND_STR_QUOTE(subprop->name);
200 STR_APPEND_STR(": ");
202 }
203 STR_APPEND_STR("}");
204 break;
205 }
206 case IDP_ID: {
207 const ID *id = static_cast<const ID *>(prop->data.pointer);
208 if (id != nullptr) {
209 STR_APPEND_STR("bpy.data.");
211 STR_APPEND_STR("[");
212 STR_APPEND_STR_QUOTE(id->name + 2);
213 STR_APPEND_STR("]");
214 }
215 else {
216 STR_APPEND_STR("None");
217 }
218 break;
219 }
220 default: {
222 break;
223 }
224 }
225
226#undef STR_APPEND_STR
227#undef STR_APPEND_STR_QUOTE
228#undef STR_APPEND_STR_LEN_QUOTE
229#undef STR_APPEND_FMT
230}
231
232void IDP_repr_fn(const IDProperty *prop,
233 void (*str_append_fn)(void *user_data, const char *str, uint str_len),
234 void *user_data)
235{
237 state.str_append_fn = str_append_fn;
238 state.user_data = user_data;
240}
241
242static void repr_str(void *user_data, const char *str, uint len)
243{
244 BLI_dynstr_nappend(static_cast<DynStr *>(user_data), str, int(len));
245}
246
247char *IDP_reprN(const IDProperty *prop, uint *r_len)
248{
249 DynStr *ds = BLI_dynstr_new();
250 IDP_repr_fn(prop, repr_str, ds);
251 char *cstring = BLI_dynstr_get_cstring(ds);
252 if (r_len != nullptr) {
253 *r_len = uint(BLI_dynstr_get_len(ds));
254 }
255 BLI_dynstr_free(ds);
256 return cstring;
257}
258
259void IDP_print(const IDProperty *prop)
260{
261 char *repr = IDP_reprN(prop, nullptr);
262 printf("IDProperty(%p): ", prop);
263 puts(repr);
264 MEM_freeN(repr);
265}
266
267const char *IDP_type_str(const eIDPropertyType type, const short sub_type)
268{
269 switch (type) {
270 case IDP_STRING:
271 switch (sub_type) {
273 return "String";
275 return "Bytes";
276 default:
277 return "String";
278 }
279 case IDP_INT:
280 return "Int";
281 case IDP_FLOAT:
282 return "Float";
283 case IDP_ARRAY:
284 switch (sub_type) {
285 case IDP_INT:
286 return "Array (Int)";
287 case IDP_FLOAT:
288 return "Array (Float)";
289 case IDP_DOUBLE:
290 return "Array (Double)";
291 case IDP_BOOLEAN:
292 return "Array (Boolean)";
293 default:
294 return "Array";
295 }
296 case IDP_GROUP:
297 return "Group";
298 case IDP_ID:
299 return "ID";
300 case IDP_DOUBLE:
301 return "Double";
302 case IDP_IDPARRAY:
303 return "Array of Properties";
304 case IDP_BOOLEAN:
305 return "Boolean";
306 }
308 return "Unknown";
309}
310
311const char *IDP_type_str(const IDProperty *prop)
312{
313 return IDP_type_str(eIDPropertyType(prop->type), prop->subtype);
314}
315
#define IDP_float_get(prop)
#define IDP_int_get(prop)
#define IDP_string_get(prop)
#define IDP_double_get(prop)
const IDPropertyUIDataEnumItem * IDP_EnumItemFind(const IDProperty *prop)
Definition idprop.cc:471
#define IDP_bool_get(prop)
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition idtype.cc:171
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
Definition BLI_dynstr.cc:75
int BLI_dynstr_get_len(const DynStr *ds) 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()
#define LISTBASE_FOREACH(type, var, list)
#define SNPRINTF_RLEN(dst, format,...)
Definition BLI_string.h:605
unsigned int uint
ID and Library types, which are fundamental for SDNA.
@ IDP_STRING_SUB_UTF8
@ IDP_STRING_SUB_BYTE
eIDPropertyType
@ IDP_DOUBLE
@ IDP_FLOAT
@ IDP_STRING
@ IDP_BOOLEAN
@ IDP_IDPARRAY
@ IDP_INT
@ IDP_GROUP
@ IDP_ARRAY
@ IDP_ID
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define str(s)
#define GS(x)
#define printf(...)
#define STR_APPEND_STR_LEN_QUOTE(str, str_len)
const char * IDP_type_str(const eIDPropertyType type, const short sub_type)
#define STR_APPEND_FMT(format,...)
#define STR_APPEND_STR_QUOTE(str)
char * IDP_reprN(const IDProperty *prop, uint *r_len)
static void idp_repr_fn_recursive(ReprState *state, const IDProperty *prop)
static void repr_str(void *user_data, const char *str, uint len)
#define STR_APPEND_STR(str)
void IDP_print(const IDProperty *prop)
void IDP_repr_fn(const IDProperty *prop, void(*str_append_fn)(void *user_data, const char *str, uint str_len), void *user_data)
static void idp_str_append_escape(ReprState *state, const char *str, const uint str_len, bool quote)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong state[N]
ListBase group
Definition DNA_ID.h:143
void * pointer
Definition DNA_ID.h:142
int len
Definition DNA_ID.h:175
IDPropertyUIData * ui_data
Definition DNA_ID.h:183
IDPropertyData data
Definition DNA_ID.h:169
char subtype
Definition DNA_ID.h:161
char type
Definition DNA_ID.h:156
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * first
void * user_data
void(* str_append_fn)(void *user_data, const char *str, uint str_len)
char buf[128]
i
Definition text_draw.cc:230
uint len