Blender  V2.93
dna_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  * Copyright (C) 2018 Blender Foundation.
17  */
18 
25 #include <string.h>
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_assert.h"
30 #include "BLI_ghash.h"
31 #include "BLI_sys_types.h"
32 #include "BLI_utildefines.h"
33 
34 #include "BLI_memarena.h"
35 
36 #include "dna_utils.h"
37 
38 /* -------------------------------------------------------------------- */
46 int DNA_elem_array_size(const char *str)
47 {
48  int result = 1;
49  int current = 0;
50  while (true) {
51  char c = *str++;
52  switch (c) {
53  case '\0':
54  return result;
55  case '[':
56  current = 0;
57  break;
58  case ']':
59  result *= current;
60  break;
61  case '0':
62  case '1':
63  case '2':
64  case '3':
65  case '4':
66  case '5':
67  case '6':
68  case '7':
69  case '8':
70  case '9':
71  current = current * 10 + (c - '0');
72  break;
73  default:
74  break;
75  }
76  }
77 }
78 
81 /* -------------------------------------------------------------------- */
85 static bool is_identifier(const char c)
86 {
87  return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
88  (c == '_'));
89 }
90 
91 uint DNA_elem_id_offset_start(const char *elem_full)
92 {
93  uint elem_full_offset = 0;
94  while (!is_identifier(elem_full[elem_full_offset])) {
95  elem_full_offset++;
96  }
97  return elem_full_offset;
98 }
99 
100 uint DNA_elem_id_offset_end(const char *elem_full)
101 {
102  uint elem_full_offset = 0;
103  while (is_identifier(elem_full[elem_full_offset])) {
104  elem_full_offset++;
105  }
106  return elem_full_offset;
107 }
108 
112 uint DNA_elem_id_strip_copy(char *elem_dst, const char *elem_src)
113 {
114  const uint elem_src_offset = DNA_elem_id_offset_start(elem_src);
115  const char *elem_src_trim = elem_src + elem_src_offset;
116  const uint elem_src_trim_len = DNA_elem_id_offset_end(elem_src_trim);
117  memcpy(elem_dst, elem_src_trim, elem_src_trim_len);
118  elem_dst[elem_src_trim_len] = '\0';
119  return elem_src_trim_len;
120 }
121 
123 {
125  const char *elem_trim = elem + elem_offset;
126  const uint elem_trim_len = DNA_elem_id_offset_end(elem_trim);
127  memmove(elem, elem_trim, elem_trim_len);
128  elem[elem_trim_len] = '\0';
129  return elem_trim_len;
130 }
131 
136 bool DNA_elem_id_match(const char *elem_search,
137  const int elem_search_len,
138  const char *elem_full,
139  uint *r_elem_full_offset)
140 {
141  BLI_assert(strlen(elem_search) == elem_search_len);
142  const uint elem_full_offset = DNA_elem_id_offset_start(elem_full);
143  const char *elem_full_trim = elem_full + elem_full_offset;
144  if (strncmp(elem_search, elem_full_trim, elem_search_len) == 0) {
145  const char c = elem_full_trim[elem_search_len];
146  if (c == '\0' || !is_identifier(c)) {
147  *r_elem_full_offset = elem_full_offset;
148  return true;
149  }
150  }
151  return false;
152 }
153 
158  const char *elem_src,
159  const int elem_src_len,
160  const char *elem_dst,
161  const int elem_dst_len,
162  const char *elem_src_full,
163  const int elem_src_full_len,
164  const uint elem_src_full_offset_len)
165 {
166  BLI_assert(strlen(elem_src) == elem_src_len);
167  BLI_assert(strlen(elem_dst) == elem_dst_len);
168  BLI_assert(strlen(elem_src_full) == elem_src_full_len);
169  BLI_assert(DNA_elem_id_offset_start(elem_src_full) == elem_src_full_offset_len);
170  UNUSED_VARS_NDEBUG(elem_src);
171 
172  const int elem_final_len = (elem_src_full_len - elem_src_len) + elem_dst_len;
173  char *elem_dst_full = BLI_memarena_alloc(mem_arena, elem_final_len + 1);
174  uint i = 0;
175  if (elem_src_full_offset_len != 0) {
176  memcpy(elem_dst_full, elem_src_full, elem_src_full_offset_len);
177  i = elem_src_full_offset_len;
178  }
179  memcpy(&elem_dst_full[i], elem_dst, elem_dst_len + 1);
180  i += elem_dst_len;
181  uint elem_src_full_offset_end = elem_src_full_offset_len + elem_src_len;
182  if (elem_src_full[elem_src_full_offset_end] != '\0') {
183  const int elem_full_tail_len = (elem_src_full_len - elem_src_full_offset_end);
184  memcpy(&elem_dst_full[i], &elem_src_full[elem_src_full_offset_end], elem_full_tail_len + 1);
185  i += elem_full_tail_len;
186  }
187  BLI_assert((strlen(elem_dst_full) == elem_final_len) && (i == elem_final_len));
188  return elem_dst_full;
189 }
190 
193 /* -------------------------------------------------------------------- */
197 static uint strhash_pair_p(const void *ptr)
198 {
199  const char *const *pair = ptr;
200  return (BLI_ghashutil_strhash_p(pair[0]) ^ BLI_ghashutil_strhash_p(pair[1]));
201 }
202 
203 static bool strhash_pair_cmp(const void *a, const void *b)
204 {
205  const char *const *pair_a = a;
206  const char *const *pair_b = b;
207  return (STREQ(pair_a[0], pair_b[0]) && STREQ(pair_a[1], pair_b[1])) ? false : true;
208 }
209 
210 void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_struct_map, GHash **r_elem_map)
211 {
212  GHash *struct_map_local = NULL;
213  if (r_struct_map) {
214  const char *data[][2] = {
215 #define DNA_STRUCT_RENAME(old, new) {#old, #new},
216 #define DNA_STRUCT_RENAME_ELEM(struct_name, old, new)
217 #include "dna_rename_defs.h"
218 #undef DNA_STRUCT_RENAME
219 #undef DNA_STRUCT_RENAME_ELEM
220  };
221 
222  int elem_key, elem_val;
223  if (version_dir == DNA_RENAME_ALIAS_FROM_STATIC) {
224  elem_key = 0;
225  elem_val = 1;
226  }
227  else {
228  elem_key = 1;
229  elem_val = 0;
230  }
231  GHash *struct_map = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(data));
232  for (int i = 0; i < ARRAY_SIZE(data); i++) {
233  BLI_ghash_insert(struct_map, (void *)data[i][elem_key], (void *)data[i][elem_val]);
234  }
235 
236  if (version_dir == DNA_RENAME_STATIC_FROM_ALIAS) {
237  const char *renames[][2] = {
238  {"uint8_t", "uchar"},
239  {"int16_t", "short"},
240  {"uint16_t", "ushort"},
241  {"int32_t", "int"},
242  {"uint32_t", "int"},
243  };
244  for (int i = 0; i < ARRAY_SIZE(renames); i++) {
245  BLI_ghash_insert(struct_map, (void *)renames[i][0], (void *)renames[i][1]);
246  }
247  }
248 
249  *r_struct_map = struct_map;
250 
251  /* We know the direction of this, for local use. */
252  struct_map_local = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(data));
253  for (int i = 0; i < ARRAY_SIZE(data); i++) {
254  BLI_ghash_insert(struct_map_local, (void *)data[i][1], (void *)data[i][0]);
255  }
256  }
257 
258  if (r_elem_map != NULL) {
259  const char *data[][3] = {
260 #define DNA_STRUCT_RENAME(old, new)
261 #define DNA_STRUCT_RENAME_ELEM(struct_name, old, new) {#struct_name, #old, #new},
262 #include "dna_rename_defs.h"
263 #undef DNA_STRUCT_RENAME
264 #undef DNA_STRUCT_RENAME_ELEM
265  };
266 
267  int elem_key, elem_val;
268  if (version_dir == DNA_RENAME_ALIAS_FROM_STATIC) {
269  elem_key = 1;
270  elem_val = 2;
271  }
272  else {
273  elem_key = 2;
274  elem_val = 1;
275  }
276  GHash *elem_map = BLI_ghash_new_ex(
278  for (int i = 0; i < ARRAY_SIZE(data); i++) {
279  const char **str_pair = MEM_mallocN(sizeof(char *) * 2, __func__);
280  str_pair[0] = BLI_ghash_lookup_default(struct_map_local, data[i][0], (void *)data[i][0]);
281  str_pair[1] = data[i][elem_key];
282  BLI_ghash_insert(elem_map, (void *)str_pair, (void *)data[i][elem_val]);
283  }
284  *r_elem_map = elem_map;
285  }
286 
287  if (struct_map_local) {
288  BLI_ghash_free(struct_map_local, NULL, NULL);
289  }
290 }
291 
292 #undef DNA_MAKESDNA
293 
296 /* -------------------------------------------------------------------- */
312 {
313  /* 'bScreen' replaces the old IrisGL 'Screen' struct */
314  if (STREQ("bScreen", name)) {
315  return "Screen";
316  }
317  /* Groups renamed to collections in 2.8 */
318  if (STREQ("Collection", name)) {
319  return "Group";
320  }
321  if (STREQ("CollectionObject", name)) {
322  return "GroupObject";
323  }
324  return name;
325 }
326 
328 {
329  /* 'bScreen' replaces the old IrisGL 'Screen' struct */
330  if (STREQ("Screen", name)) {
331  return "bScreen";
332  }
333  /* Groups renamed to collections in 2.8 */
334  if (STREQ("Group", name)) {
335  return "Collection";
336  }
337  if (STREQ("GroupObject", name)) {
338  return "CollectionObject";
339  }
340  return name;
341 }
342 
#define BLI_assert(a)
Definition: BLI_assert.h:58
GHash * BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:707
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:813
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
unsigned int uint
Definition: BLI_sys_types.h:83
#define ARRAY_SIZE(arr)
#define UNUSED_VARS_NDEBUG(...)
#define STREQ(a, b)
Read Guarded memory(de)allocation.
static int elem_offset(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
Definition: dna_genfile.c:988
static bool strhash_pair_cmp(const void *a, const void *b)
Definition: dna_utils.c:203
uint DNA_elem_id_strip(char *elem)
Definition: dna_utils.c:122
const char * DNA_struct_rename_legacy_hack_static_from_alias(const char *name)
Definition: dna_utils.c:311
char * DNA_elem_id_rename(struct MemArena *mem_arena, const char *elem_src, const int elem_src_len, const char *elem_dst, const int elem_dst_len, const char *elem_src_full, const int elem_src_full_len, const uint elem_src_full_offset_len)
Definition: dna_utils.c:157
void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_struct_map, GHash **r_elem_map)
Definition: dna_utils.c:210
uint DNA_elem_id_offset_start(const char *elem_full)
Definition: dna_utils.c:91
uint DNA_elem_id_offset_end(const char *elem_full)
Definition: dna_utils.c:100
bool DNA_elem_id_match(const char *elem_search, const int elem_search_len, const char *elem_full, uint *r_elem_full_offset)
Definition: dna_utils.c:136
const char * DNA_struct_rename_legacy_hack_alias_from_static(const char *name)
Definition: dna_utils.c:327
uint DNA_elem_id_strip_copy(char *elem_dst, const char *elem_src)
Definition: dna_utils.c:112
int DNA_elem_array_size(const char *str)
Definition: dna_utils.c:46
static bool is_identifier(const char c)
Definition: dna_utils.c:85
static uint strhash_pair_p(const void *ptr)
Definition: dna_utils.c:197
eDNA_RenameDir
Definition: dna_utils.h:50
@ DNA_RENAME_ALIAS_FROM_STATIC
Definition: dna_utils.h:52
@ DNA_RENAME_STATIC_FROM_ALIAS
Definition: dna_utils.h:51
#define str(s)
static MemArena * mem_arena
Definition: makesdna.c:155
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
PointerRNA * ptr
Definition: wm_files.c:3157