Blender V4.5
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(prop), uint(std::max(0, prop->len - 1)));
100 break;
101 }
102 case IDP_INT: {
103 if (const IDPropertyUIDataEnumItem *item = IDP_EnumItemFind(prop)) {
104 STR_APPEND_FMT("%s", item->name);
105 }
106 STR_APPEND_FMT("%d", IDP_Int(prop));
107 break;
108 }
109 case IDP_FLOAT: {
110 STR_APPEND_FMT("%g", double(IDP_Float(prop)));
111 break;
112 }
113 case IDP_DOUBLE: {
114 STR_APPEND_FMT("%g", IDP_Double(prop));
115 break;
116 }
117 case IDP_BOOLEAN: {
118 STR_APPEND_FMT("%s", IDP_Bool(prop) ? "True" : "False");
119 break;
120 }
121 case IDP_ARRAY: {
122 STR_APPEND_STR("[");
123 switch (prop->subtype) {
124 case IDP_INT:
125 for (const int *v = static_cast<const int *>(prop->data.pointer), *v_end = v + prop->len;
126 v != v_end;
127 v++)
128 {
129 if (v != prop->data.pointer) {
130 STR_APPEND_STR(", ");
131 }
132 STR_APPEND_FMT("%d", *v);
133 }
134 break;
135 case IDP_FLOAT:
136 for (const float *v = static_cast<const float *>(prop->data.pointer),
137 *v_end = v + prop->len;
138 v != v_end;
139 v++)
140 {
141 if (v != prop->data.pointer) {
142 STR_APPEND_STR(", ");
143 }
144 STR_APPEND_FMT("%g", double(*v));
145 }
146 break;
147 case IDP_DOUBLE:
148 for (const double *v = static_cast<const double *>(prop->data.pointer),
149 *v_end = v + prop->len;
150 v != v_end;
151 v++)
152 {
153 if (v != prop->data.pointer) {
154 STR_APPEND_STR(", ");
155 }
156 STR_APPEND_FMT("%g", *v);
157 }
158 break;
159 case IDP_BOOLEAN:
160 for (const double *v = static_cast<const double *>(prop->data.pointer),
161 *v_end = v + prop->len;
162 v != v_end;
163 v++)
164 {
165 if (v != prop->data.pointer) {
166 STR_APPEND_STR(", ");
167 }
168 STR_APPEND_FMT("%s", IDP_Bool(prop) ? "True" : "False");
169 }
170 break;
171 }
172 STR_APPEND_STR("]");
173 break;
174 }
175 case IDP_IDPARRAY: {
176 STR_APPEND_STR("[");
177 for (const IDProperty *v = static_cast<const IDProperty *>(prop->data.pointer),
178 *v_end = v + prop->len;
179 v != v_end;
180 v++)
181 {
182 if (v != prop->data.pointer) {
183 STR_APPEND_STR(", ");
184 }
186 }
187 STR_APPEND_STR("]");
188 break;
189 }
190 case IDP_GROUP: {
191 STR_APPEND_STR("{");
192 LISTBASE_FOREACH (const IDProperty *, subprop, &prop->data.group) {
193 if (subprop != prop->data.group.first) {
194 STR_APPEND_STR(", ");
195 }
196 STR_APPEND_STR_QUOTE(subprop->name);
197 STR_APPEND_STR(": ");
199 }
200 STR_APPEND_STR("}");
201 break;
202 }
203 case IDP_ID: {
204 const ID *id = static_cast<const ID *>(prop->data.pointer);
205 if (id != nullptr) {
206 STR_APPEND_STR("bpy.data.");
208 STR_APPEND_STR("[");
209 STR_APPEND_STR_QUOTE(id->name + 2);
210 STR_APPEND_STR("]");
211 }
212 else {
213 STR_APPEND_STR("None");
214 }
215 break;
216 }
217 default: {
219 break;
220 }
221 }
222
223#undef STR_APPEND_STR
224#undef STR_APPEND_STR_QUOTE
225#undef STR_APPEND_STR_LEN_QUOTE
226#undef STR_APPEND_FMT
227}
228
229void IDP_repr_fn(const IDProperty *prop,
230 void (*str_append_fn)(void *user_data, const char *str, uint str_len),
231 void *user_data)
232{
234 state.str_append_fn = str_append_fn;
235 state.user_data = user_data;
237}
238
239static void repr_str(void *user_data, const char *str, uint len)
240{
241 BLI_dynstr_nappend(static_cast<DynStr *>(user_data), str, int(len));
242}
243
244char *IDP_reprN(const IDProperty *prop, uint *r_len)
245{
246 DynStr *ds = BLI_dynstr_new();
247 IDP_repr_fn(prop, repr_str, ds);
248 char *cstring = BLI_dynstr_get_cstring(ds);
249 if (r_len != nullptr) {
250 *r_len = uint(BLI_dynstr_get_len(ds));
251 }
252 BLI_dynstr_free(ds);
253 return cstring;
254}
255
256void IDP_print(const IDProperty *prop)
257{
258 char *repr = IDP_reprN(prop, nullptr);
259 printf("IDProperty(%p): ", prop);
260 puts(repr);
261 MEM_freeN(repr);
262}
263
264const char *IDP_type_str(const eIDPropertyType type, const short sub_type)
265{
266 switch (type) {
267 case IDP_STRING:
268 switch (sub_type) {
270 return "String";
272 return "Bytes";
273 default:
274 return "String";
275 }
276 case IDP_INT:
277 return "Int";
278 case IDP_FLOAT:
279 return "Float";
280 case IDP_ARRAY:
281 switch (sub_type) {
282 case IDP_INT:
283 return "Array (Int)";
284 case IDP_FLOAT:
285 return "Array (Float)";
286 case IDP_DOUBLE:
287 return "Array (Double)";
288 case IDP_BOOLEAN:
289 return "Array (Boolean)";
290 default:
291 return "Array";
292 }
293 case IDP_GROUP:
294 return "Group";
295 case IDP_ID:
296 return "ID";
297 case IDP_DOUBLE:
298 return "Double";
299 case IDP_IDPARRAY:
300 return "Array of Properties";
301 case IDP_BOOLEAN:
302 return "Boolean";
303 }
305 return "Unknown";
306}
307
308const char *IDP_type_str(const IDProperty *prop)
309{
310 return IDP_type_str(eIDPropertyType(prop->type), prop->subtype);
311}
312
#define IDP_Float(prop)
#define IDP_Int(prop)
#define IDP_Bool(prop)
#define IDP_String(prop)
#define IDP_Double(prop)
const IDPropertyUIDataEnumItem * IDP_EnumItemFind(const IDProperty *prop)
Definition idprop.cc:463
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition idtype.cc:172
#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:74
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:36
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
#define LISTBASE_FOREACH(type, var, list)
#define SNPRINTF_RLEN(dst, format,...)
Definition BLI_string.h:600
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 printf(...)
#define GS(a)
#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:138
void * pointer
Definition DNA_ID.h:137
int len
Definition DNA_ID.h:165
IDPropertyData data
Definition DNA_ID.h:159
char subtype
Definition DNA_ID.h:151
char type
Definition DNA_ID.h:146
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
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