Blender  V2.93
idprop_utils.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "BLI_dynstr.h"
25 #include "BLI_listbase.h"
26 #include "BLI_string.h"
27 #include "BLI_utildefines.h"
28 
29 #include "DNA_ID.h"
30 
31 #include "BKE_idprop.h"
32 #include "BKE_idtype.h"
33 
34 #include "MEM_guardedalloc.h"
35 
36 #include "BLI_strict_flags.h"
37 
38 /* -------------------------------------------------------------------- */
47 struct ReprState {
48  void (*str_append_fn)(void *user_data, const char *str, uint str_len);
49  void *user_data;
50  /* Big enough to format any primitive type. */
51  char buf[128];
52 };
53 
55  const char *str,
56  const uint str_len,
57  bool quote)
58 {
59  if (quote) {
60  state->str_append_fn(state->user_data, "\"", 1);
61  }
62  uint i_prev = 0, i = 0;
63  while (i < str_len) {
64  const char c = str[i];
65  if (c == '"') {
66  if (i_prev != i) {
67  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
68  }
69  state->str_append_fn(state->user_data, "\\\"", 2);
70  i_prev = i + 1;
71  }
72  else if (c == '\\') {
73  if (i_prev != i) {
74  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
75  }
76  state->str_append_fn(state->user_data, "\\\\", 2);
77  i_prev = i + 1;
78  }
79  else if (c < 32) {
80  if (i_prev != i) {
81  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
82  }
83  char buf[5];
84  uint len = (uint)BLI_snprintf_rlen(buf, sizeof(buf), "\\x%02x", c);
85  BLI_assert(len == 4);
86  state->str_append_fn(state->user_data, buf, len);
87  i_prev = i + 1;
88  }
89  i++;
90  }
91  state->str_append_fn(state->user_data, str + i_prev, i - i_prev);
92  if (quote) {
93  state->str_append_fn(state->user_data, "\"", 1);
94  }
95 }
96 
97 static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop)
98 {
99  /* Note: 'strlen' will be calculated at compile time for literals. */
100 #define STR_APPEND_STR(str) state->str_append_fn(state->user_data, str, (uint)strlen(str))
101 
102 #define STR_APPEND_STR_QUOTE(str) idp_str_append_escape(state, str, (uint)strlen(str), true)
103 #define STR_APPEND_STR_LEN_QUOTE(str, str_len) idp_str_append_escape(state, str, str_len, true)
104 
105 #define STR_APPEND_FMT(format, ...) \
106  state->str_append_fn( \
107  state->user_data, \
108  state->buf, \
109  (uint)BLI_snprintf_rlen(state->buf, sizeof(state->buf), format, __VA_ARGS__))
110 
111  switch (prop->type) {
112  case IDP_STRING: {
113  STR_APPEND_STR_LEN_QUOTE(IDP_String(prop), (uint)MAX2(0, prop->len - 1));
114  break;
115  }
116  case IDP_INT: {
117  STR_APPEND_FMT("%d", IDP_Int(prop));
118  break;
119  }
120  case IDP_FLOAT: {
121  STR_APPEND_FMT("%g", (double)IDP_Float(prop));
122  break;
123  }
124  case IDP_DOUBLE: {
125  STR_APPEND_FMT("%g", IDP_Double(prop));
126  break;
127  }
128  case IDP_ARRAY: {
129  STR_APPEND_STR("[");
130  switch (prop->subtype) {
131  case IDP_INT:
132  for (const int *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
133  if (v != prop->data.pointer) {
134  STR_APPEND_STR(", ");
135  }
136  STR_APPEND_FMT("%d", *v);
137  }
138  break;
139  case IDP_FLOAT:
140  for (const float *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
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 = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
149  if (v != prop->data.pointer) {
150  STR_APPEND_STR(", ");
151  }
152  STR_APPEND_FMT("%g", *v);
153  }
154  break;
155  }
156  STR_APPEND_STR("]");
157  break;
158  }
159  case IDP_IDPARRAY: {
160  STR_APPEND_STR("[");
161  for (const IDProperty *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) {
162  if (v != prop->data.pointer) {
163  STR_APPEND_STR(", ");
164  }
166  }
167  STR_APPEND_STR("]");
168  break;
169  }
170  case IDP_GROUP: {
171  STR_APPEND_STR("{");
172  LISTBASE_FOREACH (const IDProperty *, subprop, &prop->data.group) {
173  if (subprop != prop->data.group.first) {
174  STR_APPEND_STR(", ");
175  }
176  STR_APPEND_STR_QUOTE(subprop->name);
177  STR_APPEND_STR(": ");
178  idp_repr_fn_recursive(state, subprop);
179  }
180  STR_APPEND_STR("}");
181  break;
182  }
183  case IDP_ID: {
184  const ID *id = prop->data.pointer;
185  if (id != NULL) {
186  STR_APPEND_STR("bpy.data.");
188  STR_APPEND_STR("[");
190  STR_APPEND_STR("]");
191  }
192  else {
193  STR_APPEND_STR("None");
194  }
195  break;
196  }
197  default: {
198  BLI_assert(0);
199  break;
200  }
201  }
202 
203 #undef STR_APPEND_STR
204 #undef STR_APPEND_STR_QUOTE
205 #undef STR_APPEND_STR_LEN_QUOTE
206 #undef STR_APPEND_FMT
207 }
208 
209 void IDP_repr_fn(const IDProperty *prop,
210  void (*str_append_fn)(void *user_data, const char *str, uint str_len),
211  void *user_data)
212 {
213  struct ReprState state = {
214  .str_append_fn = str_append_fn,
215  .user_data = user_data,
216  };
218 }
219 
220 static void repr_str(void *user_data, const char *str, uint len)
221 {
223 }
224 
225 char *IDP_reprN(const IDProperty *prop, uint *r_len)
226 {
227  DynStr *ds = BLI_dynstr_new();
228  IDP_repr_fn(prop, repr_str, ds);
229  char *cstring = BLI_dynstr_get_cstring(ds);
230  if (r_len != NULL) {
231  *r_len = (uint)BLI_dynstr_get_len(ds);
232  }
233  BLI_dynstr_free(ds);
234  return cstring;
235 }
236 
237 void IDP_print(const IDProperty *prop)
238 {
239  char *repr = IDP_reprN(prop, NULL);
240  printf("IDProperty(%p): ", prop);
241  puts(repr);
242  MEM_freeN(repr);
243 }
244 
#define IDP_Float(prop)
Definition: BKE_idprop.h:179
#define IDP_Int(prop)
Definition: BKE_idprop.h:154
#define IDP_String(prop)
Definition: BKE_idprop.h:181
#define IDP_Double(prop)
Definition: BKE_idprop.h:180
const char * BKE_idtype_idcode_to_name_plural(const short idcode)
Definition: idtype.c:182
#define BLI_assert(a)
Definition: BLI_assert.h:58
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
Definition: BLI_dynstr.c:133
int BLI_dynstr_get_len(DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:286
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
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:83
#define MAX2(a, b)
ID and Library types, which are fundamental for sdna.
@ IDP_DOUBLE
Definition: DNA_ID.h:103
@ IDP_FLOAT
Definition: DNA_ID.h:99
@ IDP_STRING
Definition: DNA_ID.h:97
@ IDP_IDPARRAY
Definition: DNA_ID.h:104
@ IDP_INT
Definition: DNA_ID.h:98
@ IDP_GROUP
Definition: DNA_ID.h:101
@ IDP_ARRAY
Definition: DNA_ID.h:100
@ IDP_ID
Definition: DNA_ID.h:102
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * user_data
#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:54
#define STR_APPEND_STR_QUOTE(str)
static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop)
Definition: idprop_utils.c:97
static void repr_str(void *user_data, const char *str, uint len)
Definition: idprop_utils.c:220
char * IDP_reprN(const IDProperty *prop, uint *r_len)
Definition: idprop_utils.c:225
#define STR_APPEND_STR(str)
void IDP_print(const IDProperty *prop)
Definition: idprop_utils.c:237
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:209
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static ulong state[N]
static unsigned c
Definition: RandGen.cpp:97
ListBase group
Definition: DNA_ID.h:64
void * pointer
Definition: DNA_ID.h:63
int len
Definition: DNA_ID.h:84
IDPropertyData data
Definition: DNA_ID.h:80
char subtype
Definition: DNA_ID.h:71
char type
Definition: DNA_ID.h:71
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
void * user_data
Definition: idprop_utils.c:49
void(* str_append_fn)(void *user_data, const char *str, uint str_len)
Definition: idprop_utils.c:48
char buf[128]
Definition: idprop_utils.c:51
uint len