Blender  V3.3
idprop_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include "BLI_dynstr.h"
11 #include "BLI_listbase.h"
12 #include "BLI_string.h"
13 #include "BLI_utildefines.h"
14 
15 #include "DNA_ID.h"
16 
17 #include "BKE_idprop.h"
18 #include "BKE_idtype.h"
19 
20 #include "MEM_guardedalloc.h"
21 
22 #include "BLI_strict_flags.h"
23 
24 /* -------------------------------------------------------------------- */
33 struct ReprState {
34  void (*str_append_fn)(void *user_data, const char *str, uint str_len);
35  void *user_data;
36  /* Big enough to format any primitive type. */
37  char buf[128];
38 };
39 
41  const char *str,
42  const uint str_len,
43  bool quote)
44 {
45  if (quote) {
46  state->str_append_fn(state->user_data, "\"", 1);
47  }
48  uint i_prev = 0, i = 0;
49  while (i < str_len) {
50  const char c = str[i];
51  if (c == '"') {
52  if (i_prev != i) {
53  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
54  }
55  state->str_append_fn(state->user_data, "\\\"", 2);
56  i_prev = i + 1;
57  }
58  else if (c == '\\') {
59  if (i_prev != i) {
60  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
61  }
62  state->str_append_fn(state->user_data, "\\\\", 2);
63  i_prev = i + 1;
64  }
65  else if (c < 32) {
66  if (i_prev != i) {
67  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
68  }
69  char buf[5];
70  uint len = (uint)BLI_snprintf_rlen(buf, sizeof(buf), "\\x%02x", c);
71  BLI_assert(len == 4);
72  state->str_append_fn(state->user_data, buf, len);
73  i_prev = i + 1;
74  }
75  i++;
76  }
77  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
78  if (quote) {
79  state->str_append_fn(state->user_data, "\"", 1);
80  }
81 }
82 
83 static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop)
84 {
85  /* NOTE: 'strlen' will be calculated at compile time for literals. */
86 #define STR_APPEND_STR(str) state->str_append_fn(state->user_data, str, (uint)strlen(str))
87 
88 #define STR_APPEND_STR_QUOTE(str) idp_str_append_escape(state, str, (uint)strlen(str), true)
89 #define STR_APPEND_STR_LEN_QUOTE(str, str_len) idp_str_append_escape(state, str, str_len, true)
90 
91 #define STR_APPEND_FMT(format, ...) \
92  state->str_append_fn( \
93  state->user_data, \
94  state->buf, \
95  (uint)BLI_snprintf_rlen(state->buf, sizeof(state->buf), format, __VA_ARGS__))
96 
97  switch (prop->type) {
98  case IDP_STRING: {
99  STR_APPEND_STR_LEN_QUOTE(IDP_String(prop), (uint)MAX2(0, prop->len - 1));
100  break;
101  }
102  case IDP_INT: {
103  STR_APPEND_FMT("%d", IDP_Int(prop));
104  break;
105  }
106  case IDP_FLOAT: {
107  STR_APPEND_FMT("%g", (double)IDP_Float(prop));
108  break;
109  }
110  case IDP_DOUBLE: {
111  STR_APPEND_FMT("%g", IDP_Double(prop));
112  break;
113  }
114  case IDP_ARRAY: {
115  STR_APPEND_STR("[");
116  switch (prop->subtype) {
117  case IDP_INT:
118  for (const int *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
119  if (v != prop->data.pointer) {
120  STR_APPEND_STR(", ");
121  }
122  STR_APPEND_FMT("%d", *v);
123  }
124  break;
125  case IDP_FLOAT:
126  for (const float *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
127  if (v != prop->data.pointer) {
128  STR_APPEND_STR(", ");
129  }
130  STR_APPEND_FMT("%g", (double)*v);
131  }
132  break;
133  case IDP_DOUBLE:
134  for (const double *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
135  if (v != prop->data.pointer) {
136  STR_APPEND_STR(", ");
137  }
138  STR_APPEND_FMT("%g", *v);
139  }
140  break;
141  }
142  STR_APPEND_STR("]");
143  break;
144  }
145  case IDP_IDPARRAY: {
146  STR_APPEND_STR("[");
147  for (const IDProperty *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
148  if (v != prop->data.pointer) {
149  STR_APPEND_STR(", ");
150  }
152  }
153  STR_APPEND_STR("]");
154  break;
155  }
156  case IDP_GROUP: {
157  STR_APPEND_STR("{");
158  LISTBASE_FOREACH (const IDProperty *, subprop, &prop->data.group) {
159  if (subprop != prop->data.group.first) {
160  STR_APPEND_STR(", ");
161  }
162  STR_APPEND_STR_QUOTE(subprop->name);
163  STR_APPEND_STR(": ");
164  idp_repr_fn_recursive(state, subprop);
165  }
166  STR_APPEND_STR("}");
167  break;
168  }
169  case IDP_ID: {
170  const ID *id = prop->data.pointer;
171  if (id != NULL) {
172  STR_APPEND_STR("bpy.data.");
174  STR_APPEND_STR("[");
176  STR_APPEND_STR("]");
177  }
178  else {
179  STR_APPEND_STR("None");
180  }
181  break;
182  }
183  default: {
185  break;
186  }
187  }
188 
189 #undef STR_APPEND_STR
190 #undef STR_APPEND_STR_QUOTE
191 #undef STR_APPEND_STR_LEN_QUOTE
192 #undef STR_APPEND_FMT
193 }
194 
195 void IDP_repr_fn(const IDProperty *prop,
196  void (*str_append_fn)(void *user_data, const char *str, uint str_len),
197  void *user_data)
198 {
199  struct ReprState state = {
200  .str_append_fn = str_append_fn,
201  .user_data = user_data,
202  };
204 }
205 
206 static void repr_str(void *user_data, const char *str, uint len)
207 {
209 }
210 
211 char *IDP_reprN(const IDProperty *prop, uint *r_len)
212 {
213  DynStr *ds = BLI_dynstr_new();
214  IDP_repr_fn(prop, repr_str, ds);
215  char *cstring = BLI_dynstr_get_cstring(ds);
216  if (r_len != NULL) {
217  *r_len = (uint)BLI_dynstr_get_len(ds);
218  }
219  BLI_dynstr_free(ds);
220  return cstring;
221 }
222 
223 void IDP_print(const IDProperty *prop)
224 {
225  char *repr = IDP_reprN(prop, NULL);
226  printf("IDProperty(%p): ", prop);
227  puts(repr);
228  MEM_freeN(repr);
229 }
230 
#define IDP_Float(prop)
Definition: BKE_idprop.h:269
#define IDP_Int(prop)
Definition: BKE_idprop.h:244
#define IDP_String(prop)
Definition: BKE_idprop.h:271
#define IDP_Double(prop)
Definition: BKE_idprop.h:270
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition: idtype.c:149
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
Definition: BLI_dynstr.c:94
int BLI_dynstr_get_len(const DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:235
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
#define MAX2(a, b)
ID and Library types, which are fundamental for sdna.
@ IDP_DOUBLE
Definition: DNA_ID.h:143
@ IDP_FLOAT
Definition: DNA_ID.h:138
@ IDP_STRING
Definition: DNA_ID.h:136
@ IDP_IDPARRAY
Definition: DNA_ID.h:144
@ IDP_INT
Definition: DNA_ID.h:137
@ IDP_GROUP
Definition: DNA_ID.h:141
@ IDP_ARRAY
Definition: DNA_ID.h:140
@ IDP_ID
Definition: DNA_ID.h:142
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * user_data
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
#define str(s)
#define STR_APPEND_STR_LEN_QUOTE(str, str_len)
#define STR_APPEND_FMT(format,...)
static void idp_str_append_escape(struct ReprState *state, const char *str, const uint str_len, bool quote)
Definition: idprop_utils.c:40
#define STR_APPEND_STR_QUOTE(str)
static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop)
Definition: idprop_utils.c:83
static void repr_str(void *user_data, const char *str, uint len)
Definition: idprop_utils.c:206
char * IDP_reprN(const IDProperty *prop, uint *r_len)
Definition: idprop_utils.c:211
#define STR_APPEND_STR(str)
void IDP_print(const IDProperty *prop)
Definition: idprop_utils.c:223
void IDP_repr_fn(const IDProperty *prop, void(*str_append_fn)(void *user_data, const char *str, uint str_len), void *user_data)
Definition: idprop_utils.c:195
#define GS(x)
Definition: iris.c:225
const int state
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static unsigned c
Definition: RandGen.cpp:83
ListBase group
Definition: DNA_ID.h:101
void * pointer
Definition: DNA_ID.h:100
int len
Definition: DNA_ID.h:121
IDPropertyData data
Definition: DNA_ID.h:117
char subtype
Definition: DNA_ID.h:108
char type
Definition: DNA_ID.h:108
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
void * user_data
Definition: idprop_utils.c:35
void(* str_append_fn)(void *user_data, const char *str, uint str_len)
Definition: idprop_utils.c:34
char buf[128]
Definition: idprop_utils.c:37