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