Blender V4.3
dna_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_alloca.h"
16#include "BLI_assert.h"
17#include "BLI_ghash.h"
18#include "BLI_sys_types.h"
19#include "BLI_utildefines.h"
20
21#include "BLI_memarena.h"
22
23#include "dna_utils.h"
24
25/* -------------------------------------------------------------------- */
29int DNA_member_array_num(const char *str)
30{
31 int result = 1;
32 int current = 0;
33 while (true) {
34 char c = *str++;
35 switch (c) {
36 case '\0':
37 return result;
38 case '[':
39 current = 0;
40 break;
41 case ']':
42 result *= current;
43 break;
44 case '0':
45 case '1':
46 case '2':
47 case '3':
48 case '4':
49 case '5':
50 case '6':
51 case '7':
52 case '8':
53 case '9':
54 current = current * 10 + (c - '0');
55 break;
56 default:
57 break;
58 }
59 }
60}
61
64/* -------------------------------------------------------------------- */
68static bool is_identifier(const char c)
69{
70 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
71 (c == '_'));
72}
73
74uint DNA_member_id_offset_start(const char *member_full)
75{
76 uint elem_full_offset = 0;
77 /* NOTE(@ideasman42): checking nil is needed for invalid names such as `*`,
78 * these were written by older versions of Blender (v2.66).
79 * In this case the "name" part will be an empty string.
80 * The member cannot be used, this just prevents a crash. */
81 while (!is_identifier(member_full[elem_full_offset]) && member_full[elem_full_offset]) {
82 elem_full_offset++;
83 }
84 return elem_full_offset;
85}
86
87uint DNA_member_id_offset_end(const char *member_full_trimmed)
88{
89 uint elem_full_offset = 0;
90 while (is_identifier(member_full_trimmed[elem_full_offset])) {
91 elem_full_offset++;
92 }
93 return elem_full_offset;
94}
95
96uint DNA_member_id_strip_copy(char *member_id_dst, const char *member_full_src)
97{
98 const uint member_src_offset = DNA_member_id_offset_start(member_full_src);
99 const char *member_src_trimmed = member_full_src + member_src_offset;
100 const uint member_src_trimmed_len = DNA_member_id_offset_end(member_src_trimmed);
101 memcpy(member_id_dst, member_src_trimmed, member_src_trimmed_len);
102 member_id_dst[member_src_trimmed_len] = '\0';
103 return member_src_trimmed_len;
104}
105
107{
108 const uint member_offset = DNA_member_id_offset_start(member);
109 const char *member_trimmed = member + member_offset;
110 const uint member_trimmed_len = DNA_member_id_offset_end(member_trimmed);
111 memmove(member, member_trimmed, member_trimmed_len);
112 member[member_trimmed_len] = '\0';
113 return member_trimmed_len;
114}
115
116bool DNA_member_id_match(const char *member_id,
117 const int member_id_len,
118 const char *member_full,
119 uint *r_member_full_offset)
120{
121 BLI_assert(strlen(member_id) == member_id_len);
122 const uint elem_full_offset = DNA_member_id_offset_start(member_full);
123 const char *elem_full_trim = member_full + elem_full_offset;
124 if (strncmp(member_id, elem_full_trim, member_id_len) == 0) {
125 const char c = elem_full_trim[member_id_len];
126 if (c == '\0' || !is_identifier(c)) {
127 *r_member_full_offset = elem_full_offset;
128 return true;
129 }
130 }
131 return false;
132}
133
135 const char *member_id_src,
136 const int member_id_src_len,
137 const char *member_id_dst,
138 const int member_id_dst_len,
139 const char *member_full_src,
140 const int member_full_src_len,
141 const uint member_full_src_offset_len)
142{
143 BLI_assert(strlen(member_id_src) == member_id_src_len);
144 BLI_assert(strlen(member_id_dst) == member_id_dst_len);
145 BLI_assert(strlen(member_full_src) == member_full_src_len);
146 BLI_assert(DNA_member_id_offset_start(member_full_src) == member_full_src_offset_len);
147 UNUSED_VARS_NDEBUG(member_id_src);
148
149 const int member_full_dst_len = (member_full_src_len - member_id_src_len) + member_id_dst_len;
150 char *member_full_dst = static_cast<char *>(
151 BLI_memarena_alloc(mem_arena, member_full_dst_len + 1));
152 uint i = 0;
153 if (member_full_src_offset_len != 0) {
154 memcpy(member_full_dst, member_full_src, member_full_src_offset_len);
155 i = member_full_src_offset_len;
156 }
157 memcpy(&member_full_dst[i], member_id_dst, member_id_dst_len + 1);
158 i += member_id_dst_len;
159 const uint member_full_src_offset_end = member_full_src_offset_len + member_id_src_len;
160 BLI_assert(DNA_member_id_offset_end(member_full_src + member_full_src_offset_len) ==
161 (member_full_src_offset_end - member_full_src_offset_len));
162 if (member_full_src[member_full_src_offset_end] != '\0') {
163 const int member_full_tail_len = (member_full_src_len - member_full_src_offset_end);
164 memcpy(&member_full_dst[i],
165 &member_full_src[member_full_src_offset_end],
166 member_full_tail_len + 1);
167 i += member_full_tail_len;
168 }
169 BLI_assert((strlen(member_full_dst) == member_full_dst_len) && (i == member_full_dst_len));
171 return member_full_dst;
172}
173
176/* -------------------------------------------------------------------- */
180static uint strhash_pair_p(const void *ptr)
181{
182 const char *const *pair = static_cast<const char *const *>(ptr);
183 return (BLI_ghashutil_strhash_p(pair[0]) ^ BLI_ghashutil_strhash_p(pair[1]));
184}
185
186static bool strhash_pair_cmp(const void *a, const void *b)
187{
188 const char *const *pair_a = static_cast<const char *const *>(a);
189 const char *const *pair_b = static_cast<const char *const *>(b);
190 return (STREQ(pair_a[0], pair_b[0]) && STREQ(pair_a[1], pair_b[1])) ? false : true;
191}
192
193void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_type_map, GHash **r_member_map)
194{
195 GHash *type_map_local = nullptr;
196 if (r_type_map) {
197 const char *type_data[][2] = {
198#define DNA_STRUCT_RENAME(old, new) {#old, #new},
199#define DNA_STRUCT_RENAME_MEMBER(struct_name, old, new)
200#include "dna_rename_defs.h"
201#undef DNA_STRUCT_RENAME
202#undef DNA_STRUCT_RENAME_MEMBER
203 };
204
205 int elem_key, elem_val;
206 if (version_dir == DNA_RENAME_ALIAS_FROM_STATIC) {
207 elem_key = 0;
208 elem_val = 1;
209 }
210 else {
211 elem_key = 1;
212 elem_val = 0;
213 }
214 GHash *type_map = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(type_data));
215 for (int i = 0; i < ARRAY_SIZE(type_data); i++) {
216 BLI_ghash_insert(type_map, (void *)type_data[i][elem_key], (void *)type_data[i][elem_val]);
217 }
218
219 if (version_dir == DNA_RENAME_STATIC_FROM_ALIAS) {
220 const char *renames[][2] = {
221 /* {old, new}, like in #DNA_STRUCT_RENAME */
222 {"uchar", "uint8_t"},
223 {"short", "int16_t"},
224 {"ushort", "uint16_t"},
225 {"int", "int32_t"},
226 {"int", "uint32_t"},
227 };
228 for (int i = 0; i < ARRAY_SIZE(renames); i++) {
229 BLI_ghash_insert(type_map, (void *)renames[i][elem_key], (void *)renames[i][elem_val]);
230 }
231 }
232
233 *r_type_map = type_map;
234
235 /* We know the direction of this, for local use. */
236 type_map_local = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(type_data));
237 for (int i = 0; i < ARRAY_SIZE(type_data); i++) {
238 BLI_ghash_insert(type_map_local, (void *)type_data[i][1], (void *)type_data[i][0]);
239 }
240 }
241
242 if (r_member_map != nullptr) {
243 const char *member_data[][3] = {
244#define DNA_STRUCT_RENAME(old, new)
245#define DNA_STRUCT_RENAME_MEMBER(struct_name, old, new) {#struct_name, #old, #new},
246#include "dna_rename_defs.h"
247#undef DNA_STRUCT_RENAME
248#undef DNA_STRUCT_RENAME_MEMBER
249 };
250
251 int elem_key, elem_val;
252 if (version_dir == DNA_RENAME_ALIAS_FROM_STATIC) {
253 elem_key = 1;
254 elem_val = 2;
255 }
256 else {
257 elem_key = 2;
258 elem_val = 1;
259 }
260 GHash *member_map = BLI_ghash_new_ex(
261 strhash_pair_p, strhash_pair_cmp, __func__, ARRAY_SIZE(member_data));
262 for (int i = 0; i < ARRAY_SIZE(member_data); i++) {
263 const char **str_pair = static_cast<const char **>(
264 MEM_mallocN(sizeof(char *) * 2, __func__));
265 str_pair[0] = static_cast<const char *>(
266 BLI_ghash_lookup_default(type_map_local, member_data[i][0], (void *)member_data[i][0]));
267 str_pair[1] = member_data[i][elem_key];
268 BLI_ghash_insert(member_map, (void *)str_pair, (void *)member_data[i][elem_val]);
269 }
270 *r_member_map = member_map;
271 }
272
273 if (type_map_local) {
274 BLI_ghash_free(type_map_local, nullptr, nullptr);
275 }
276}
277
278#undef DNA_MAKESDNA
279
282/* -------------------------------------------------------------------- */
286/* WARNING: Only keep this for compatibility: *NEVER ADD NEW STRINGS HERE*.
287 *
288 * The renaming here isn't complete, references to the old struct names
289 * are still included in DNA, now fixing these struct names properly
290 * breaks forward compatibility. Leave these as-is, but don't add to them!
291 * See D4342#98780. */
292
294{
295 /* 'bScreen' replaces the old IrisGL 'Screen' struct */
296 if (STREQ("bScreen", name)) {
297 return "Screen";
298 }
299 /* Groups renamed to collections in 2.8 */
300 if (STREQ("Collection", name)) {
301 return "Group";
302 }
303 if (STREQ("CollectionObject", name)) {
304 return "GroupObject";
305 }
306 return name;
307}
308
310{
311 /* 'bScreen' replaces the old IrisGL 'Screen' struct */
312 if (STREQ("Screen", name)) {
313 return "bScreen";
314 }
315 /* Groups renamed to collections in 2.8 */
316 if (STREQ("Group", name)) {
317 return "Collection";
318 }
319 if (STREQ("GroupObject", name)) {
320 return "CollectionObject";
321 }
322 return name;
323}
324
327/* -------------------------------------------------------------------- */
331extern "C" void _DNA_internal_memcpy(void *dst, const void *src, size_t size);
332extern "C" void _DNA_internal_memcpy(void *dst, const void *src, const size_t size)
333{
334 memcpy(dst, src, size);
335}
336
337extern "C" void _DNA_internal_memzero(void *dst, size_t size);
338extern "C" void _DNA_internal_memzero(void *dst, const size_t size)
339{
340 memset(dst, 0, size);
341}
342
343extern "C" void _DNA_internal_swap(void *a, void *b, size_t size);
344extern "C" void _DNA_internal_swap(void *a, void *b, const size_t size)
345{
346 void *tmp = alloca(size);
347 memcpy(tmp, a, size);
348 memcpy(a, b, size);
349 memcpy(b, tmp, size);
350}
351
#define BLI_assert(a)
Definition BLI_assert.h:50
void * BLI_ghash_lookup_default(const GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:738
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:678
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
unsigned int uint
#define ARRAY_SIZE(arr)
#define UNUSED_VARS_NDEBUG(...)
#define STREQ(a, b)
Read Guarded memory(de)allocation.
local_group_size(16, 16) .push_constant(Type b
const char * DNA_struct_rename_legacy_hack_static_from_alias(const char *name)
Definition dna_utils.cc:293
const char * DNA_struct_rename_legacy_hack_alias_from_static(const char *name)
Definition dna_utils.cc:309
uint DNA_member_id_offset_end(const char *member_full_trimmed)
Definition dna_utils.cc:87
int DNA_member_array_num(const char *str)
Definition dna_utils.cc:29
static bool strhash_pair_cmp(const void *a, const void *b)
Definition dna_utils.cc:186
void _DNA_internal_memzero(void *dst, size_t size)
Definition dna_utils.cc:338
void _DNA_internal_swap(void *a, void *b, size_t size)
Definition dna_utils.cc:344
void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_type_map, GHash **r_member_map)
Definition dna_utils.cc:193
bool DNA_member_id_match(const char *member_id, const int member_id_len, const char *member_full, uint *r_member_full_offset)
Definition dna_utils.cc:116
uint DNA_member_id_offset_start(const char *member_full)
Definition dna_utils.cc:74
void _DNA_internal_memcpy(void *dst, const void *src, size_t size)
Definition dna_utils.cc:332
uint DNA_member_id_strip(char *member)
Definition dna_utils.cc:106
uint DNA_member_id_strip_copy(char *member_id_dst, const char *member_full_src)
Definition dna_utils.cc:96
static bool is_identifier(const char c)
Definition dna_utils.cc:68
char * DNA_member_id_rename(MemArena *mem_arena, const char *member_id_src, const int member_id_src_len, const char *member_id_dst, const int member_id_dst_len, const char *member_full_src, const int member_full_src_len, const uint member_full_src_offset_len)
Definition dna_utils.cc:134
static uint strhash_pair_p(const void *ptr)
Definition dna_utils.cc:180
eDNA_RenameDir
Definition dna_utils.h:87
@ DNA_RENAME_ALIAS_FROM_STATIC
Definition dna_utils.h:89
@ DNA_RENAME_STATIC_FROM_ALIAS
Definition dna_utils.h:88
#define str(s)
static MemArena * mem_arena
Definition makesdna.cc:62
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
PointerRNA * ptr
Definition wm_files.cc:4126