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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * DNA handling
19  */
20 
21 /** \file
22  * \ingroup DNA
23  *
24  * Lowest-level functions for decoding the parts of a saved .blend
25  * file, including interpretation of its SDNA block and conversion of
26  * contents of other parts according to the differences between that
27  * SDNA and the SDNA of the current (running) version of Blender.
28  */
29 
30 #include <limits.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "MEM_guardedalloc.h" /* for MEM_freeN MEM_mallocN MEM_callocN */
36 
37 #include "BLI_endian_switch.h"
38 #include "BLI_memarena.h"
39 #include "BLI_string.h"
40 #include "BLI_utildefines.h"
41 
42 #include "BLI_ghash.h"
43 
44 #include "DNA_genfile.h"
45 #include "DNA_sdna_types.h" /* for SDNA ;-) */
46 
47 /**
48  * \section dna_genfile Overview
49  *
50  * - please note: no builtin security to detect input of double structs
51  * - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`.
52  *
53  * Structure DNA data is added to each blender file and to each executable, this to detect
54  * in .blend files new variables in structs, changed array sizes, etc. It's also used for
55  * converting endian and pointer size (32-64 bits)
56  * As an extra, Python uses a call to detect run-time the contents of a blender struct.
57  *
58  * Create a structDNA: only needed when one of the input include (.h) files change.
59  * File Syntax:
60  * \code{.unparsed}
61  *     SDNA (4 bytes) (magic number)
62  *     NAME (4 bytes)
63  *     <nr> (4 bytes) amount of names (int)
64  *     <string>
65  *     <string>
66  *     ...
67  *     ...
68  *     TYPE (4 bytes)
69  *     <nr> amount of types (int)
70  *     <string>
71  *     <string>
72  *     ...
73  *     ...
74  *     TLEN (4 bytes)
75  *     <len> (short) the lengths of types
76  *     <len>
77  *     ...
78  *     ...
79  *     STRC (4 bytes)
80  *     <nr> amount of structs (int)
81  *     <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
82  * \endcode
83  *
84  * **Remember to read/write integer and short aligned!**
85  *
86  * While writing a file, the names of a struct is indicated with a type number,
87  * to be found with: ``type = DNA_struct_find_nr(SDNA *, const char *)``
88  * The value of ``type`` corresponds with the index within the structs array
89  *
90  * For the moment: the complete DNA file is included in a .blend file. For
91  * the future we can think of smarter methods, like only included the used
92  * structs. Only needed to keep a file short though...
93  *
94  * ALLOWED AND TESTED CHANGES IN STRUCTS:
95  *  - Type change (a char to float will be divided by 255).
96  *  - Location within a struct (everything can be randomly mixed up).
97  *  - Struct within struct (within struct etc), this is recursive.
98  *  - Adding new elements, will be default initialized zero.
99  *  - Removing elements.
100  *  - Change of array sizes.
101  *  - Change of a pointer type: when the name doesn't change the contents is copied.
102  *
103  * NOT YET:
104  *  - array (``vec[3]``) to float struct (``vec3f``).
105  *
106  * DONE:
107  *  - Endian compatibility.
108  *  - Pointer conversion (32-64 bits).
109  *
110  * IMPORTANT:
111  *  - Do not use #defines in structs for array lengths, this cannot be read by the dna functions.
112  *  - Do not use `uint`, but unsigned int instead, `ushort` and `ulong` are allowed.
113  *  - Only use a long in Blender if you want this to be the size of a pointer. so it is
114  *    32 bits or 64 bits, dependent at the cpu architecture.
115  *  - Chars are always unsigned
116  *  - Alignment of variables has to be done in such a way, that any system does
117  *    not create 'padding' (gaps) in structures. So make sure that:
118  *    - short: 2 aligned.
119  *    - int: 4 aligned.
120  *    - float: 4 aligned.
121  *    - double: 8 aligned.
122  *    - long: 8 aligned.
123  *    - int64: 8 aligned.
124  *    - struct: 8 aligned.
125  *  - the sdna functions have several error prints builtin,
126  *    always check blender running from a console.
127  */
128 
129 #ifdef __BIG_ENDIAN__
130 /* Big Endian */
131 #  define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
132 #else
133 /* Little Endian */
134 #  define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
135 #endif
136 
137 /* ************************* DIV ********************** */
138 
DNA_sdna_free(SDNA * sdna)139 void DNA_sdna_free(SDNA *sdna)
140 {
141   if (sdna->data_alloc) {
142     MEM_freeN((void *)sdna->data);
143   }
144 
145   MEM_freeN((void *)sdna->names);
146   MEM_freeN((void *)sdna->names_array_len);
147   MEM_freeN((void *)sdna->types);
148   MEM_freeN(sdna->structs);
149 
150 #ifdef WITH_DNA_GHASH
151   if (sdna->structs_map) {
152     BLI_ghash_free(sdna->structs_map, NULL, NULL);
153   }
154 #endif
155 
156   if (sdna->mem_arena) {
157     BLI_memarena_free(sdna->mem_arena);
158   }
159 
160   MEM_SAFE_FREE(sdna->alias.names);
161   MEM_SAFE_FREE(sdna->alias.types);
162 #ifdef WITH_DNA_GHASH
163   if (sdna->alias.structs_map) {
164     BLI_ghash_free(sdna->alias.structs_map, NULL, NULL);
165   }
166 #endif
167 
168   MEM_freeN(sdna);
169 }
170 
171 /**
172  * Return true if the name indicates a pointer of some kind.
173  */
ispointer(const char * name)174 static bool ispointer(const char *name)
175 {
176   /* check if pointer or function pointer */
177   return (name[0] == '*' || (name[0] == '(' && name[1] == '*'));
178 }
179 
180 /**
181  * Returns the size of struct fields of the specified type and name.
182  *
183  * \param type: Index into sdna->types/types_size
184  * \param name: Index into sdna->names,
185  * needed to extract possible pointer/array information.
186  */
DNA_elem_size_nr(const SDNA * sdna,short type,short name)187 int DNA_elem_size_nr(const SDNA *sdna, short type, short name)
188 {
189   const char *cp = sdna->names[name];
190   int len = 0;
191 
192   /* is it a pointer or function pointer? */
193   if (ispointer(cp)) {
194     /* has the name an extra length? (array) */
195     len = sdna->pointer_size * sdna->names_array_len[name];
196   }
197   else if (sdna->types_size[type]) {
198     /* has the name an extra length? (array) */
199     len = (int)sdna->types_size[type] * sdna->names_array_len[name];
200   }
201 
202   return len;
203 }
204 
205 #if 0
206 static void printstruct(SDNA *sdna, short strnr)
207 {
208   /* is for debug */
209 
210   SDNA_Struct *struct_info = sdna->structs[strnr];
211   printf("struct %s\n", sdna->types[struct_info->type]);
212 
213   for (int b = 0; b < struct_info->members_len; b++) {
214     SDNA_StructMember *struct_member = &struct_info->members[b];
215     printf("   %s %s\n",
216            sdna->types[struct_member->type],
217            sdna->names[struct_member->name]);
218   }
219 }
220 #endif
221 
222 /**
223  * Returns the index of the struct info for the struct with the specified name.
224  */
dna_struct_find_nr_ex_impl(const char ** types,const int UNUSED (types_len),SDNA_Struct ** const structs,const int structs_len,GHash * structs_map,const char * str,unsigned int * index_last)225 static int dna_struct_find_nr_ex_impl(
226     /* From SDNA struct. */
227     const char **types,
228     const int UNUSED(types_len),
229     SDNA_Struct **const structs,
230     const int structs_len,
231 #ifdef WITH_DNA_GHASH
232     GHash *structs_map,
233 #endif
234     /* Regular args. */
235     const char *str,
236     unsigned int *index_last)
237 {
238   if (*index_last < structs_len) {
239     const SDNA_Struct *struct_info = structs[*index_last];
240     if (STREQ(types[struct_info->type], str)) {
241       return *index_last;
242     }
243   }
244 
245 #ifdef WITH_DNA_GHASH
246   {
247     void **index_p = BLI_ghash_lookup_p(structs_map, str);
248     if (index_p) {
249       const int index = POINTER_AS_INT(*index_p);
250       *index_last = index;
251       return index;
252     }
253   }
254 #else
255   {
256     for (int index = 0; index < structs_len; index++) {
257       const SDNA_Struct *struct_info = structs[index];
258       if (STREQ(types[struct_info->type], str)) {
259         *index_last = index;
260         return index;
261       }
262     }
263   }
264 #endif
265   return -1;
266 }
267 
268 /**
269  * Returns the index of the struct info for the struct with the specified name.
270  */
DNA_struct_find_nr_ex(const SDNA * sdna,const char * str,unsigned int * index_last)271 int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
272 {
273   return dna_struct_find_nr_ex_impl(
274       /* Expand SDNA. */
275       sdna->types,
276       sdna->types_len,
277       sdna->structs,
278       sdna->structs_len,
279 #ifdef WITH_DNA_GHASH
280       sdna->structs_map,
281 #endif
282       /* Regular args. */
283       str,
284       index_last);
285 }
286 
287 /** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
DNA_struct_alias_find_nr_ex(const SDNA * sdna,const char * str,unsigned int * index_last)288 int DNA_struct_alias_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
289 {
290 #ifdef WITH_DNA_GHASH
291   BLI_assert(sdna->alias.structs_map != NULL);
292 #endif
293   return dna_struct_find_nr_ex_impl(
294       /* Expand SDNA. */
295       sdna->alias.types,
296       sdna->types_len,
297       sdna->structs,
298       sdna->structs_len,
299 #ifdef WITH_DNA_GHASH
300       sdna->alias.structs_map,
301 #endif
302       /* Regular args. */
303       str,
304       index_last);
305 }
306 
DNA_struct_find_nr(const SDNA * sdna,const char * str)307 int DNA_struct_find_nr(const SDNA *sdna, const char *str)
308 {
309   unsigned int index_last_dummy = UINT_MAX;
310   return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy);
311 }
312 
313 /** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
DNA_struct_alias_find_nr(const SDNA * sdna,const char * str)314 int DNA_struct_alias_find_nr(const SDNA *sdna, const char *str)
315 {
316   unsigned int index_last_dummy = UINT_MAX;
317   return DNA_struct_alias_find_nr_ex(sdna, str, &index_last_dummy);
318 }
319 
320 /* ************************* END DIV ********************** */
321 
322 /* ************************* READ DNA ********************** */
323 
pad_up_4(const char * ptr)324 BLI_INLINE const char *pad_up_4(const char *ptr)
325 {
326   return (const char *)((((uintptr_t)ptr) + 3) & ~3);
327 }
328 
329 /**
330  * In sdna->data the data, now we convert that to something understandable
331  */
init_structDNA(SDNA * sdna,bool do_endian_swap,const char ** r_error_message)332 static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error_message)
333 {
334   int gravity_fix = -1;
335 
336   int *data = (int *)sdna->data;
337 
338   /* Clear pointers in case of error. */
339   sdna->names = NULL;
340   sdna->types = NULL;
341   sdna->structs = NULL;
342 #ifdef WITH_DNA_GHASH
343   sdna->structs_map = NULL;
344 #endif
345   sdna->mem_arena = NULL;
346 
347   /* Lazy initialize. */
348   memset(&sdna->alias, 0, sizeof(sdna->alias));
349 
350   /* Struct DNA ('SDNA') */
351   if (*data != MAKE_ID('S', 'D', 'N', 'A')) {
352     *r_error_message = "SDNA error in SDNA file";
353     return false;
354   }
355 
356   const char *cp;
357 
358   data++;
359   /* Names array ('NAME') */
360   if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
361     data++;
362 
363     sdna->names_len = *data;
364     if (do_endian_swap) {
365       BLI_endian_switch_int32(&sdna->names_len);
366     }
367     sdna->names_len_alloc = sdna->names_len;
368 
369     data++;
370     sdna->names = MEM_callocN(sizeof(void *) * sdna->names_len, "sdnanames");
371   }
372   else {
373     *r_error_message = "NAME error in SDNA file";
374     return false;
375   }
376 
377   cp = (char *)data;
378   for (int nr = 0; nr < sdna->names_len; nr++) {
379     sdna->names[nr] = cp;
380 
381     /* "float gravity [3]" was parsed wrong giving both "gravity" and
382      * "[3]"  members. we rename "[3]", and later set the type of
383      * "gravity" to "void" so the offsets work out correct */
384     if (*cp == '[' && STREQ(cp, "[3]")) {
385       if (nr && STREQ(sdna->names[nr - 1], "Cvi")) {
386         sdna->names[nr] = "gravity[3]";
387         gravity_fix = nr;
388       }
389     }
390     while (*cp) {
391       cp++;
392     }
393     cp++;
394   }
395 
396   cp = pad_up_4(cp);
397 
398   /* Type names array ('TYPE') */
399   data = (int *)cp;
400   if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
401     data++;
402 
403     sdna->types_len = *data;
404     if (do_endian_swap) {
405       BLI_endian_switch_int32(&sdna->types_len);
406     }
407 
408     data++;
409     sdna->types = MEM_callocN(sizeof(void *) * sdna->types_len, "sdnatypes");
410   }
411   else {
412     *r_error_message = "TYPE error in SDNA file";
413     return false;
414   }
415 
416   cp = (char *)data;
417   for (int nr = 0; nr < sdna->types_len; nr++) {
418     /* WARNING! See: DNA_struct_rename_legacy_hack_static_from_alias docs. */
419     sdna->types[nr] = DNA_struct_rename_legacy_hack_static_from_alias(cp);
420     while (*cp) {
421       cp++;
422     }
423     cp++;
424   }
425 
426   cp = pad_up_4(cp);
427 
428   /* Type lengths array ('TLEN') */
429   data = (int *)cp;
430   short *sp;
431   if (*data == MAKE_ID('T', 'L', 'E', 'N')) {
432     data++;
433     sp = (short *)data;
434     sdna->types_size = sp;
435 
436     if (do_endian_swap) {
437       BLI_endian_switch_int16_array(sp, sdna->types_len);
438     }
439 
440     sp += sdna->types_len;
441   }
442   else {
443     *r_error_message = "TLEN error in SDNA file";
444     return false;
445   }
446   /* prevent BUS error */
447   if (sdna->types_len & 1) {
448     sp++;
449   }
450 
451   /* Struct array ('STRC') */
452   data = (int *)sp;
453   if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
454     data++;
455 
456     sdna->structs_len = *data;
457     if (do_endian_swap) {
458       BLI_endian_switch_int32(&sdna->structs_len);
459     }
460 
461     data++;
462     sdna->structs = MEM_callocN(sizeof(SDNA_Struct *) * sdna->structs_len, "sdnastrcs");
463   }
464   else {
465     *r_error_message = "STRC error in SDNA file";
466     return false;
467   }
468 
469   sp = (short *)data;
470   for (int nr = 0; nr < sdna->structs_len; nr++) {
471     SDNA_Struct *struct_info = (SDNA_Struct *)sp;
472     sdna->structs[nr] = struct_info;
473 
474     if (do_endian_swap) {
475       BLI_endian_switch_int16(&struct_info->type);
476       BLI_endian_switch_int16(&struct_info->members_len);
477 
478       for (short a = 0; a < struct_info->members_len; a++) {
479         SDNA_StructMember *member = &struct_info->members[a];
480         BLI_endian_switch_int16(&member->type);
481         BLI_endian_switch_int16(&member->name);
482       }
483     }
484     sp += 2 + (sizeof(SDNA_StructMember) / sizeof(short)) * struct_info->members_len;
485   }
486 
487   {
488     /* second part of gravity problem, setting "gravity" type to void */
489     if (gravity_fix > -1) {
490       for (int nr = 0; nr < sdna->structs_len; nr++) {
491         sp = (short *)sdna->structs[nr];
492         if (STREQ(sdna->types[sp[0]], "ClothSimSettings")) {
493           sp[10] = SDNA_TYPE_VOID;
494         }
495       }
496     }
497   }
498 
499 #ifdef WITH_DNA_GHASH
500   {
501     /* create a ghash lookup to speed up */
502     sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->structs_len);
503 
504     for (intptr_t nr = 0; nr < sdna->structs_len; nr++) {
505       SDNA_Struct *struct_info = sdna->structs[nr];
506       BLI_ghash_insert(
507           sdna->structs_map, (void *)sdna->types[struct_info->type], POINTER_FROM_INT(nr));
508     }
509   }
510 #endif
511 
512   /* Calculate 'sdna->pointer_size' */
513   {
514     const int nr = DNA_struct_find_nr(sdna, "ListBase");
515 
516     /* should never happen, only with corrupt file for example */
517     if (UNLIKELY(nr == -1)) {
518       *r_error_message = "ListBase struct error! Not found.";
519       return false;
520     }
521 
522     /* finally pointer_size: use struct ListBase to test it, never change the size of it! */
523     SDNA_Struct *struct_info = sdna->structs[nr];
524     /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
525 
526     sdna->pointer_size = sdna->types_size[struct_info->type] / 2;
527 
528     if (struct_info->members_len != 2 || (sdna->pointer_size != 4 && sdna->pointer_size != 8)) {
529       *r_error_message = "ListBase struct error! Needs it to calculate pointerize.";
530       /* well, at least sizeof(ListBase) is error proof! (ton) */
531       return false;
532     }
533   }
534 
535   /* Cache name size. */
536   {
537     short *names_array_len = MEM_mallocN(sizeof(*names_array_len) * sdna->names_len, __func__);
538     for (int i = 0; i < sdna->names_len; i++) {
539       names_array_len[i] = DNA_elem_array_size(sdna->names[i]);
540     }
541     sdna->names_array_len = names_array_len;
542   }
543 
544   return true;
545 }
546 
547 /**
548  * Constructs and returns a decoded SDNA structure from the given encoded SDNA data block.
549  */
DNA_sdna_from_data(const void * data,const int data_len,bool do_endian_swap,bool data_alloc,const char ** r_error_message)550 SDNA *DNA_sdna_from_data(const void *data,
551                          const int data_len,
552                          bool do_endian_swap,
553                          bool data_alloc,
554                          const char **r_error_message)
555 {
556   SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
557   const char *error_message = NULL;
558 
559   sdna->data_len = data_len;
560   if (data_alloc) {
561     char *data_copy = MEM_mallocN(data_len, "sdna_data");
562     memcpy(data_copy, data, data_len);
563     sdna->data = data_copy;
564   }
565   else {
566     sdna->data = data;
567   }
568   sdna->data_alloc = data_alloc;
569 
570   if (init_structDNA(sdna, do_endian_swap, &error_message)) {
571     return sdna;
572   }
573 
574   if (r_error_message == NULL) {
575     fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
576   }
577   else {
578     *r_error_message = error_message;
579   }
580   DNA_sdna_free(sdna);
581   return NULL;
582 }
583 
584 /**
585  * Using a global is acceptable here,
586  * the data is read-only and only changes between Blender versions.
587  *
588  * So it is safe to create once and reuse.
589  */
590 static SDNA *g_sdna = NULL;
591 
DNA_sdna_current_init(void)592 void DNA_sdna_current_init(void)
593 {
594   g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL);
595 }
596 
DNA_sdna_current_get(void)597 const struct SDNA *DNA_sdna_current_get(void)
598 {
599   BLI_assert(g_sdna != NULL);
600   return g_sdna;
601 }
602 
DNA_sdna_current_free(void)603 void DNA_sdna_current_free(void)
604 {
605   DNA_sdna_free(g_sdna);
606   g_sdna = NULL;
607 }
608 
609 /* ******************** END READ DNA ********************** */
610 
611 /* ******************* HANDLE DNA ***************** */
612 
613 /**
614  * This function changes compare_flags[old_struct_index] from SDNA_CMP_UNKNOWN to something else.
615  * It might call itself recursively.
616  */
set_compare_flags_for_struct(const SDNA * oldsdna,const SDNA * newsdna,char * compare_flags,const int old_struct_index)617 static void set_compare_flags_for_struct(const SDNA *oldsdna,
618                                          const SDNA *newsdna,
619                                          char *compare_flags,
620                                          const int old_struct_index)
621 {
622   if (compare_flags[old_struct_index] != SDNA_CMP_UNKNOWN) {
623     /* This flag has been initialized already. */
624     return;
625   }
626 
627   SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
628   const char *struct_name = oldsdna->types[old_struct->type];
629 
630   const int new_struct_index = DNA_struct_find_nr(newsdna, struct_name);
631   if (new_struct_index == -1) {
632     /* Didn't find a matching new struct, so it has been removed. */
633     compare_flags[old_struct_index] = SDNA_CMP_REMOVED;
634     return;
635   }
636 
637   SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
638   if (old_struct->members_len != new_struct->members_len) {
639     /* Structs with a different amount of members are not equal. */
640     compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
641     return;
642   }
643   if (oldsdna->types_size[old_struct->type] != newsdna->types_size[new_struct->type]) {
644     /* Structs that don't have the same size are not equal. */
645     compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
646     return;
647   }
648 
649   /* Compare each member individually. */
650   for (int member_index = 0; member_index < old_struct->members_len; member_index++) {
651     SDNA_StructMember *old_member = &old_struct->members[member_index];
652     SDNA_StructMember *new_member = &new_struct->members[member_index];
653 
654     const char *old_type_name = oldsdna->types[old_member->type];
655     const char *new_type_name = newsdna->types[new_member->type];
656     if (!STREQ(old_type_name, new_type_name)) {
657       /* If two members have a different type in the same place, the structs are not equal. */
658       compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
659       return;
660     }
661 
662     const char *old_member_name = oldsdna->names[old_member->name];
663     const char *new_member_name = newsdna->names[new_member->name];
664     if (!STREQ(old_member_name, new_member_name)) {
665       /* If two members have a different name in the same place, the structs are not equal. */
666       compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
667       return;
668     }
669 
670     if (ispointer(old_member_name)) {
671       if (oldsdna->pointer_size != newsdna->pointer_size) {
672         /* When the struct contains a pointer, and the pointer sizes differ, the structs are not
673          * equal. */
674         compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
675         return;
676       }
677     }
678     else {
679       const int old_member_struct_index = DNA_struct_find_nr(oldsdna, old_type_name);
680       if (old_member_struct_index >= 0) {
681         set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, old_member_struct_index);
682         if (compare_flags[old_member_struct_index] != SDNA_CMP_EQUAL) {
683           /* If an embedded struct is not equal, the parent struct cannot be equal either. */
684           compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
685           return;
686         }
687       }
688     }
689   }
690 
691   compare_flags[old_struct_index] = SDNA_CMP_EQUAL;
692 }
693 
694 /**
695  * Constructs and returns an array of byte flags with one element for each struct in oldsdna,
696  * indicating how it compares to newsdna.
697  */
DNA_struct_get_compareflags(const SDNA * oldsdna,const SDNA * newsdna)698 const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
699 {
700   if (oldsdna->structs_len == 0) {
701     printf("error: file without SDNA\n");
702     return NULL;
703   }
704 
705   char *compare_flags = MEM_mallocN(oldsdna->structs_len, "compare flags");
706   memset(compare_flags, SDNA_CMP_UNKNOWN, oldsdna->structs_len);
707 
708   /* Set correct flag for every struct. */
709   for (int a = 0; a < oldsdna->structs_len; a++) {
710     set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, a);
711     BLI_assert(compare_flags[a] != SDNA_CMP_UNKNOWN);
712   }
713 
714   /* first struct in util.h is struct Link, this is skipped in compare_flags (als # 0).
715    * was a bug, and this way dirty patched! Solve this later....
716    */
717   compare_flags[0] = SDNA_CMP_EQUAL;
718 
719 /* This code can be enabled to see which structs have changed. */
720 #if 0
721   for (int a = 0; a < oldsdna->structs_len; a++) {
722     if (compare_flags[a] == SDNA_CMP_NOT_EQUAL) {
723       SDNA_Struct *struct_info = oldsdna->structs[a];
724       printf("changed: %s\n", oldsdna->types[struct_info->type]);
725     }
726   }
727 #endif
728 
729   return compare_flags;
730 }
731 
732 /**
733  * Converts a value of one primitive type to another.
734  *
735  * \note there is no optimization for the case where \a otype and \a ctype are the same:
736  * assumption is that caller will handle this case.
737  *
738  * \param old_type: Type to convert from.
739  * \param new_type: Type to convert to.
740  * \param array_len: Number of elements to convert.
741  * \param old_data: Buffer containing the old values.
742  * \param new_data: Buffer the converted values will be written to.
743  */
cast_primitive_type(const eSDNA_Type old_type,const eSDNA_Type new_type,const int array_len,const char * old_data,char * new_data)744 static void cast_primitive_type(const eSDNA_Type old_type,
745                                 const eSDNA_Type new_type,
746                                 const int array_len,
747                                 const char *old_data,
748                                 char *new_data)
749 {
750   /* define lengths */
751   const int oldlen = DNA_elem_type_size(old_type);
752   const int curlen = DNA_elem_type_size(new_type);
753 
754   double old_value_f = 0.0;
755   uint64_t old_value_i = 0;
756 
757   for (int a = 0; a < array_len; a++) {
758     switch (old_type) {
759       case SDNA_TYPE_CHAR:
760         old_value_i = *old_data;
761         old_value_f = (double)old_value_i;
762         break;
763       case SDNA_TYPE_UCHAR:
764         old_value_i = *((unsigned char *)old_data);
765         old_value_f = (double)old_value_i;
766         break;
767       case SDNA_TYPE_SHORT:
768         old_value_i = *((short *)old_data);
769         old_value_f = (double)old_value_i;
770         break;
771       case SDNA_TYPE_USHORT:
772         old_value_i = *((unsigned short *)old_data);
773         old_value_f = (double)old_value_i;
774         break;
775       case SDNA_TYPE_INT:
776         old_value_i = *((int *)old_data);
777         old_value_f = (double)old_value_i;
778         break;
779       case SDNA_TYPE_FLOAT:
780         old_value_f = *((float *)old_data);
781         old_value_i = (uint64_t)(int64_t)old_value_f;
782         break;
783       case SDNA_TYPE_DOUBLE:
784         old_value_f = *((double *)old_data);
785         old_value_i = (uint64_t)(int64_t)old_value_f;
786         break;
787       case SDNA_TYPE_INT64:
788         old_value_i = (uint64_t) * ((int64_t *)old_data);
789         old_value_f = (double)old_value_i;
790         break;
791       case SDNA_TYPE_UINT64:
792         old_value_i = *((uint64_t *)old_data);
793         old_value_f = (double)old_value_i;
794         break;
795     }
796 
797     switch (new_type) {
798       case SDNA_TYPE_CHAR:
799         *new_data = (char)old_value_i;
800         break;
801       case SDNA_TYPE_UCHAR:
802         *((unsigned char *)new_data) = (unsigned char)old_value_i;
803         break;
804       case SDNA_TYPE_SHORT:
805         *((short *)new_data) = (short)old_value_i;
806         break;
807       case SDNA_TYPE_USHORT:
808         *((unsigned short *)new_data) = (unsigned short)old_value_i;
809         break;
810       case SDNA_TYPE_INT:
811         *((int *)new_data) = (int)old_value_i;
812         break;
813       case SDNA_TYPE_FLOAT:
814         if (old_type < 2) {
815           old_value_f /= 255.0;
816         }
817         *((float *)new_data) = old_value_f;
818         break;
819       case SDNA_TYPE_DOUBLE:
820         if (old_type < 2) {
821           old_value_f /= 255.0;
822         }
823         *((double *)new_data) = old_value_f;
824         break;
825       case SDNA_TYPE_INT64:
826         *((int64_t *)new_data) = (int64_t)old_value_i;
827         break;
828       case SDNA_TYPE_UINT64:
829         *((uint64_t *)new_data) = old_value_i;
830         break;
831     }
832 
833     old_data += oldlen;
834     new_data += curlen;
835   }
836 }
837 
cast_pointer_32_to_64(const int array_len,const uint32_t * old_data,uint64_t * new_data)838 static void cast_pointer_32_to_64(const int array_len,
839                                   const uint32_t *old_data,
840                                   uint64_t *new_data)
841 {
842   for (int a = 0; a < array_len; a++) {
843     new_data[a] = old_data[a];
844   }
845 }
846 
cast_pointer_64_to_32(const int array_len,const uint64_t * old_data,uint32_t * new_data)847 static void cast_pointer_64_to_32(const int array_len,
848                                   const uint64_t *old_data,
849                                   uint32_t *new_data)
850 {
851   /* WARNING: 32-bit Blender trying to load file saved by 64-bit Blender,
852    * pointers may lose uniqueness on truncation! (Hopefully this wont
853    * happen unless/until we ever get to multi-gigabyte .blend files...) */
854   for (int a = 0; a < array_len; a++) {
855     new_data[a] = old_data[a] >> 3;
856   }
857 }
858 
859 /**
860  * Equality test on name and oname excluding any array-size suffix.
861  */
elem_streq(const char * name,const char * oname)862 static bool elem_streq(const char *name, const char *oname)
863 {
864   int a = 0;
865 
866   while (1) {
867     if (name[a] != oname[a]) {
868       return false;
869     }
870     if (name[a] == '[' || oname[a] == '[') {
871       break;
872     }
873     if (name[a] == 0 || oname[a] == 0) {
874       break;
875     }
876     a++;
877   }
878   return true;
879 }
880 
881 /**
882  * Returns whether the specified field exists according to the struct format
883  * pointed to by old.
884  *
885  * \param type: Current field type name.
886  * \param name: Current field name.
887  * \param old: Pointer to struct information in sdna.
888  * \return true when existing, false otherwise..
889  */
elem_exists_impl(const char ** types,const char ** names,const char * type,const char * name,const SDNA_Struct * old)890 static bool elem_exists_impl(
891     /* Expand SDNA. */
892     const char **types,
893     const char **names,
894     /* Regular args. */
895     const char *type,
896     const char *name,
897     const SDNA_Struct *old)
898 {
899   /* in old is the old struct */
900   for (int a = 0; a < old->members_len; a++) {
901     const SDNA_StructMember *member = &old->members[a];
902     const char *otype = types[member->type];
903     const char *oname = names[member->name];
904 
905     if (elem_streq(name, oname)) { /* name equal */
906       return STREQ(type, otype);   /* type equal */
907     }
908   }
909   return false;
910 }
911 
912 /**
913  * \param sdna: Old SDNA.
914  */
elem_exists(const SDNA * sdna,const char * type,const char * name,const SDNA_Struct * old)915 static bool elem_exists(const SDNA *sdna,
916                         const char *type,
917                         const char *name,
918                         const SDNA_Struct *old)
919 {
920   return elem_exists_impl(
921       /* Expand SDNA. */
922       sdna->types,
923       sdna->names,
924       /* Regular args. */
925       type,
926       name,
927       old);
928 }
929 
elem_exists_alias(const SDNA * sdna,const char * type,const char * name,const SDNA_Struct * old)930 static bool elem_exists_alias(const SDNA *sdna,
931                               const char *type,
932                               const char *name,
933                               const SDNA_Struct *old)
934 {
935   return elem_exists_impl(
936       /* Expand SDNA. */
937       sdna->alias.types,
938       sdna->alias.names,
939       /* Regular args. */
940       type,
941       name,
942       old);
943 }
944 
945 /**
946  * Return the offset in bytes or -1 on failure to find the struct member with its expected type.
947  *
948  * \param sdna: Old #SDNA.
949  * \param type: Current field type name.
950  * \param name: Current field name.
951  * \param old: Pointer to struct information in #SDNA.
952  * \return The offset or -1 on failure.
953  *
954  * \note Use #elem_exists if additional information provided by this function is not needed.
955  *
956  * \note We could have a version of this function that
957  * returns the #SDNA_StructMember currently it's not needed.
958  */
elem_offset(const SDNA * sdna,const char * type,const char * name,const SDNA_Struct * old)959 static int elem_offset(const SDNA *sdna,
960                        const char *type,
961                        const char *name,
962                        const SDNA_Struct *old)
963 {
964   /* without arraypart, so names can differ: return old namenr and type */
965 
966   /* in old is the old struct */
967   int offset = 0;
968   for (int a = 0; a < old->members_len; a++) {
969     const SDNA_StructMember *member = &old->members[a];
970     const char *otype = sdna->types[member->type];
971     const char *oname = sdna->names[member->name];
972     if (elem_streq(name, oname)) { /* name equal */
973       if (STREQ(type, otype)) {    /* type equal */
974         return offset;
975       }
976       break; /* Fail below. */
977     }
978     offset += DNA_elem_size_nr(sdna, member->type, member->name);
979   }
980   return -1;
981 }
982 
983 /* Each struct member belongs to one of the categories below. */
984 typedef enum eStructMemberCategory {
985   STRUCT_MEMBER_CATEGORY_STRUCT,
986   STRUCT_MEMBER_CATEGORY_PRIMITIVE,
987   STRUCT_MEMBER_CATEGORY_POINTER,
988 } eStructMemberCategory;
989 
get_struct_member_category(const SDNA * sdna,const SDNA_StructMember * member)990 static eStructMemberCategory get_struct_member_category(const SDNA *sdna,
991                                                         const SDNA_StructMember *member)
992 {
993   const char *member_name = sdna->names[member->name];
994   if (ispointer(member_name)) {
995     return STRUCT_MEMBER_CATEGORY_POINTER;
996   }
997   const char *member_type_name = sdna->types[member->type];
998   if (DNA_struct_find(sdna, member_type_name)) {
999     return STRUCT_MEMBER_CATEGORY_STRUCT;
1000   }
1001   return STRUCT_MEMBER_CATEGORY_PRIMITIVE;
1002 }
1003 
get_member_size_in_bytes(const SDNA * sdna,const SDNA_StructMember * member)1004 static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member)
1005 {
1006   const char *name = sdna->names[member->name];
1007   const int array_length = sdna->names_array_len[member->name];
1008   if (ispointer(name)) {
1009     return sdna->pointer_size * array_length;
1010   }
1011   const int type_size = sdna->types_size[member->type];
1012   return type_size * array_length;
1013 }
1014 
1015 /**
1016  * Does endian swapping on the fields of a struct value.
1017  *
1018  * \param sdna: SDNA of the struct_nr belongs to
1019  * \param struct_nr: Index of struct info within sdna
1020  * \param data: Struct data that is to be converted
1021  */
DNA_struct_switch_endian(const SDNA * sdna,int struct_nr,char * data)1022 void DNA_struct_switch_endian(const SDNA *sdna, int struct_nr, char *data)
1023 {
1024   if (struct_nr == -1) {
1025     return;
1026   }
1027 
1028   const SDNA_Struct *struct_info = sdna->structs[struct_nr];
1029 
1030   int offset_in_bytes = 0;
1031   for (int member_index = 0; member_index < struct_info->members_len; member_index++) {
1032     const SDNA_StructMember *member = &struct_info->members[member_index];
1033     const eStructMemberCategory member_category = get_struct_member_category(sdna, member);
1034     char *member_data = data + offset_in_bytes;
1035     const char *member_type_name = sdna->types[member->type];
1036     const int member_array_length = sdna->names_array_len[member->name];
1037 
1038     switch (member_category) {
1039       case STRUCT_MEMBER_CATEGORY_STRUCT: {
1040         const int substruct_size = sdna->types_size[member->type];
1041         const int substruct_nr = DNA_struct_find_nr(sdna, member_type_name);
1042         BLI_assert(substruct_nr != -1);
1043         for (int a = 0; a < member_array_length; a++) {
1044           DNA_struct_switch_endian(sdna, substruct_nr, member_data + a * substruct_size);
1045         }
1046         break;
1047       }
1048       case STRUCT_MEMBER_CATEGORY_PRIMITIVE: {
1049         switch (member->type) {
1050           case SDNA_TYPE_SHORT:
1051           case SDNA_TYPE_USHORT: {
1052             BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length);
1053             break;
1054           }
1055           case SDNA_TYPE_INT:
1056           case SDNA_TYPE_FLOAT: {
1057             /* Note, intentionally ignore long/ulong, because these could be 4 or 8 bytes.
1058              * Fortunately, we only use these types for runtime variables and only once for a
1059              * struct type that is no longer used. */
1060             BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length);
1061             break;
1062           }
1063           case SDNA_TYPE_INT64:
1064           case SDNA_TYPE_UINT64:
1065           case SDNA_TYPE_DOUBLE: {
1066             BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length);
1067             break;
1068           }
1069           default: {
1070             break;
1071           }
1072         }
1073         break;
1074       }
1075       case STRUCT_MEMBER_CATEGORY_POINTER: {
1076         /* See readfile.c (#bh4_from_bh8 swap endian argument),
1077          * this is only done when reducing the size of a pointer from 4 to 8. */
1078         if (sizeof(void *) < 8) {
1079           if (sdna->pointer_size == 8) {
1080             BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length);
1081           }
1082         }
1083         break;
1084       }
1085     }
1086     offset_in_bytes += get_member_size_in_bytes(sdna, member);
1087   }
1088 }
1089 
1090 typedef enum eReconstructStepType {
1091   RECONSTRUCT_STEP_MEMCPY,
1092   RECONSTRUCT_STEP_CAST_PRIMITIVE,
1093   RECONSTRUCT_STEP_CAST_POINTER_TO_32,
1094   RECONSTRUCT_STEP_CAST_POINTER_TO_64,
1095   RECONSTRUCT_STEP_SUBSTRUCT,
1096   RECONSTRUCT_STEP_INIT_ZERO,
1097 } eReconstructStepType;
1098 
1099 typedef struct ReconstructStep {
1100   eReconstructStepType type;
1101   union {
1102     struct {
1103       int old_offset;
1104       int new_offset;
1105       int size;
1106     } memcpy;
1107     struct {
1108       int old_offset;
1109       int new_offset;
1110       int array_len;
1111       eSDNA_Type old_type;
1112       eSDNA_Type new_type;
1113     } cast_primitive;
1114     struct {
1115       int old_offset;
1116       int new_offset;
1117       int array_len;
1118     } cast_pointer;
1119     struct {
1120       int old_offset;
1121       int new_offset;
1122       int array_len;
1123       short old_struct_nr;
1124       short new_struct_nr;
1125     } substruct;
1126   } data;
1127 } ReconstructStep;
1128 
1129 typedef struct DNA_ReconstructInfo {
1130   const SDNA *oldsdna;
1131   const SDNA *newsdna;
1132   const char *compare_flags;
1133 
1134   int *step_counts;
1135   ReconstructStep **steps;
1136 } DNA_ReconstructInfo;
1137 
1138 static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1139                                 const int blocks,
1140                                 const int old_struct_nr,
1141                                 const int new_struct_nr,
1142                                 const char *old_blocks,
1143                                 char *new_blocks);
1144 
1145 /**
1146  * Converts the contents of an entire struct from oldsdna to newsdna format.
1147  *
1148  * \param reconstruct_info: Preprocessed reconstruct information generated by
1149  * #DNA_reconstruct_info_create.
1150  * \param new_struct_nr: Index in newsdna->structs of the struct that is being reconstructed.
1151  * \param old_block: Memory buffer containing the old struct.
1152  * \param new_block: Where to put converted struct contents.
1153  */
reconstruct_struct(const DNA_ReconstructInfo * reconstruct_info,const int new_struct_nr,const char * old_block,char * new_block)1154 static void reconstruct_struct(const DNA_ReconstructInfo *reconstruct_info,
1155                                const int new_struct_nr,
1156                                const char *old_block,
1157                                char *new_block)
1158 {
1159   const ReconstructStep *steps = reconstruct_info->steps[new_struct_nr];
1160   const int step_count = reconstruct_info->step_counts[new_struct_nr];
1161 
1162   /* Execute all preprocessed steps. */
1163   for (int a = 0; a < step_count; a++) {
1164     const ReconstructStep *step = &steps[a];
1165     switch (step->type) {
1166       case RECONSTRUCT_STEP_MEMCPY:
1167         memcpy(new_block + step->data.memcpy.new_offset,
1168                old_block + step->data.memcpy.old_offset,
1169                step->data.memcpy.size);
1170         break;
1171       case RECONSTRUCT_STEP_CAST_PRIMITIVE:
1172         cast_primitive_type(step->data.cast_primitive.old_type,
1173                             step->data.cast_primitive.new_type,
1174                             step->data.cast_primitive.array_len,
1175                             old_block + step->data.cast_primitive.old_offset,
1176                             new_block + step->data.cast_primitive.new_offset);
1177         break;
1178       case RECONSTRUCT_STEP_CAST_POINTER_TO_32:
1179         cast_pointer_64_to_32(step->data.cast_pointer.array_len,
1180                               (const uint64_t *)(old_block + step->data.cast_pointer.old_offset),
1181                               (uint32_t *)(new_block + step->data.cast_pointer.new_offset));
1182         break;
1183       case RECONSTRUCT_STEP_CAST_POINTER_TO_64:
1184         cast_pointer_32_to_64(step->data.cast_pointer.array_len,
1185                               (const uint32_t *)(old_block + step->data.cast_pointer.old_offset),
1186                               (uint64_t *)(new_block + step->data.cast_pointer.new_offset));
1187         break;
1188       case RECONSTRUCT_STEP_SUBSTRUCT:
1189         reconstruct_structs(reconstruct_info,
1190                             step->data.substruct.array_len,
1191                             step->data.substruct.old_struct_nr,
1192                             step->data.substruct.new_struct_nr,
1193                             old_block + step->data.substruct.old_offset,
1194                             new_block + step->data.substruct.new_offset);
1195         break;
1196       case RECONSTRUCT_STEP_INIT_ZERO:
1197         /* Do nothing, because the memory block has been calloced. */
1198         break;
1199     }
1200   }
1201 }
1202 
1203 /** Reconstructs an array of structs. */
reconstruct_structs(const DNA_ReconstructInfo * reconstruct_info,const int blocks,const int old_struct_nr,const int new_struct_nr,const char * old_blocks,char * new_blocks)1204 static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1205                                 const int blocks,
1206                                 const int old_struct_nr,
1207                                 const int new_struct_nr,
1208                                 const char *old_blocks,
1209                                 char *new_blocks)
1210 {
1211   const SDNA_Struct *old_struct = reconstruct_info->oldsdna->structs[old_struct_nr];
1212   const SDNA_Struct *new_struct = reconstruct_info->newsdna->structs[new_struct_nr];
1213 
1214   const int old_block_size = reconstruct_info->oldsdna->types_size[old_struct->type];
1215   const int new_block_size = reconstruct_info->newsdna->types_size[new_struct->type];
1216 
1217   for (int a = 0; a < blocks; a++) {
1218     const char *old_block = old_blocks + a * old_block_size;
1219     char *new_block = new_blocks + a * new_block_size;
1220     reconstruct_struct(reconstruct_info, new_struct_nr, old_block, new_block);
1221   }
1222 }
1223 
1224 /**
1225  * \param reconstruct_info: Information preprocessed by #DNA_reconstruct_info_create.
1226  * \param old_struct_nr: Index of struct info within oldsdna.
1227  * \param blocks: The number of array elements.
1228  * \param old_blocks: Array of struct data.
1229  * \return An allocated reconstructed struct.
1230  */
DNA_struct_reconstruct(const DNA_ReconstructInfo * reconstruct_info,int old_struct_nr,int blocks,const void * old_blocks)1231 void *DNA_struct_reconstruct(const DNA_ReconstructInfo *reconstruct_info,
1232                              int old_struct_nr,
1233                              int blocks,
1234                              const void *old_blocks)
1235 {
1236   const SDNA *oldsdna = reconstruct_info->oldsdna;
1237   const SDNA *newsdna = reconstruct_info->newsdna;
1238 
1239   const SDNA_Struct *old_struct = oldsdna->structs[old_struct_nr];
1240   const char *type_name = oldsdna->types[old_struct->type];
1241   const int new_struct_nr = DNA_struct_find_nr(newsdna, type_name);
1242 
1243   if (new_struct_nr == -1) {
1244     return NULL;
1245   }
1246 
1247   const SDNA_Struct *new_struct = newsdna->structs[new_struct_nr];
1248   const int new_block_size = newsdna->types_size[new_struct->type];
1249 
1250   char *new_blocks = MEM_callocN(blocks * new_block_size, "reconstruct");
1251   reconstruct_structs(
1252       reconstruct_info, blocks, old_struct_nr, new_struct_nr, old_blocks, new_blocks);
1253   return new_blocks;
1254 }
1255 
1256 /** Finds a member in the given struct with the given name. */
find_member_with_matching_name(const SDNA * sdna,const SDNA_Struct * struct_info,const char * name,int * r_offset)1257 static const SDNA_StructMember *find_member_with_matching_name(const SDNA *sdna,
1258                                                                const SDNA_Struct *struct_info,
1259                                                                const char *name,
1260                                                                int *r_offset)
1261 {
1262   int offset = 0;
1263   for (int a = 0; a < struct_info->members_len; a++) {
1264     const SDNA_StructMember *member = &struct_info->members[a];
1265     const char *member_name = sdna->names[member->name];
1266     if (elem_streq(name, member_name)) {
1267       *r_offset = offset;
1268       return member;
1269     }
1270     offset += get_member_size_in_bytes(sdna, member);
1271   }
1272   return NULL;
1273 }
1274 
1275 /** Initializes a single reconstruct step for a member in the new struct. */
init_reconstruct_step_for_member(const SDNA * oldsdna,const SDNA * newsdna,const char * compare_flags,const SDNA_Struct * old_struct,const SDNA_StructMember * new_member,const int new_member_offset,ReconstructStep * r_step)1276 static void init_reconstruct_step_for_member(const SDNA *oldsdna,
1277                                              const SDNA *newsdna,
1278                                              const char *compare_flags,
1279                                              const SDNA_Struct *old_struct,
1280                                              const SDNA_StructMember *new_member,
1281                                              const int new_member_offset,
1282                                              ReconstructStep *r_step)
1283 {
1284 
1285   /* Find the matching old member. */
1286   int old_member_offset;
1287   const char *new_name = newsdna->names[new_member->name];
1288   const SDNA_StructMember *old_member = find_member_with_matching_name(
1289       oldsdna, old_struct, new_name, &old_member_offset);
1290 
1291   if (old_member == NULL) {
1292     /* No matching member has been found in the old struct. */
1293     r_step->type = RECONSTRUCT_STEP_INIT_ZERO;
1294     return;
1295   }
1296 
1297   /* Determine the member category of the old an new members. */
1298   const eStructMemberCategory new_category = get_struct_member_category(newsdna, new_member);
1299   const eStructMemberCategory old_category = get_struct_member_category(oldsdna, old_member);
1300 
1301   if (new_category != old_category) {
1302     /* Can only reconstruct the new member based on the old member, when the belong to the same
1303      * category. */
1304     r_step->type = RECONSTRUCT_STEP_INIT_ZERO;
1305     return;
1306   }
1307 
1308   const int new_array_length = newsdna->names_array_len[new_member->name];
1309   const int old_array_length = oldsdna->names_array_len[old_member->name];
1310   const int shared_array_length = MIN2(new_array_length, old_array_length);
1311 
1312   const char *new_type_name = newsdna->types[new_member->type];
1313   const char *old_type_name = oldsdna->types[old_member->type];
1314 
1315   switch (new_category) {
1316     case STRUCT_MEMBER_CATEGORY_STRUCT: {
1317       if (STREQ(new_type_name, old_type_name)) {
1318         const int old_struct_nr = DNA_struct_find_nr(oldsdna, old_type_name);
1319         BLI_assert(old_struct_nr != -1);
1320         enum eSDNA_StructCompare compare_flag = compare_flags[old_struct_nr];
1321         BLI_assert(compare_flag != SDNA_CMP_REMOVED);
1322         if (compare_flag == SDNA_CMP_EQUAL) {
1323           /* The old and new members are identical, just do a memcpy. */
1324           r_step->type = RECONSTRUCT_STEP_MEMCPY;
1325           r_step->data.memcpy.new_offset = new_member_offset;
1326           r_step->data.memcpy.old_offset = old_member_offset;
1327           r_step->data.memcpy.size = newsdna->types_size[new_member->type] * shared_array_length;
1328         }
1329         else {
1330           const int new_struct_nr = DNA_struct_find_nr(newsdna, new_type_name);
1331           BLI_assert(new_struct_nr != -1);
1332 
1333           /* The old and new members are different, use recursion to reconstruct the
1334            * nested struct. */
1335           BLI_assert(compare_flag == SDNA_CMP_NOT_EQUAL);
1336           r_step->type = RECONSTRUCT_STEP_SUBSTRUCT;
1337           r_step->data.substruct.new_offset = new_member_offset;
1338           r_step->data.substruct.old_offset = old_member_offset;
1339           r_step->data.substruct.array_len = shared_array_length;
1340           r_step->data.substruct.new_struct_nr = new_struct_nr;
1341           r_step->data.substruct.old_struct_nr = old_struct_nr;
1342         }
1343       }
1344       else {
1345         /* Cannot match structs that have different names. */
1346         r_step->type = RECONSTRUCT_STEP_INIT_ZERO;
1347       }
1348       break;
1349     }
1350     case STRUCT_MEMBER_CATEGORY_PRIMITIVE: {
1351       if (STREQ(new_type_name, old_type_name)) {
1352         /* Primitives with the same name cannot be different, so just do a memcpy. */
1353         r_step->type = RECONSTRUCT_STEP_MEMCPY;
1354         r_step->data.memcpy.new_offset = new_member_offset;
1355         r_step->data.memcpy.old_offset = old_member_offset;
1356         r_step->data.memcpy.size = newsdna->types_size[new_member->type] * shared_array_length;
1357       }
1358       else {
1359         /* The old and new primitive types are different, cast from the old to new type. */
1360         r_step->type = RECONSTRUCT_STEP_CAST_PRIMITIVE;
1361         r_step->data.cast_primitive.array_len = shared_array_length;
1362         r_step->data.cast_primitive.new_offset = new_member_offset;
1363         r_step->data.cast_primitive.old_offset = old_member_offset;
1364         r_step->data.cast_primitive.new_type = new_member->type;
1365         r_step->data.cast_primitive.old_type = old_member->type;
1366       }
1367       break;
1368     }
1369     case STRUCT_MEMBER_CATEGORY_POINTER: {
1370       if (newsdna->pointer_size == oldsdna->pointer_size) {
1371         /* The pointer size is the same, so just do a memcpy. */
1372         r_step->type = RECONSTRUCT_STEP_MEMCPY;
1373         r_step->data.memcpy.new_offset = new_member_offset;
1374         r_step->data.memcpy.old_offset = old_member_offset;
1375         r_step->data.memcpy.size = newsdna->pointer_size * shared_array_length;
1376       }
1377       else if (newsdna->pointer_size == 8 && oldsdna->pointer_size == 4) {
1378         /* Need to convert from 32 bit to 64 bit pointers. */
1379         r_step->type = RECONSTRUCT_STEP_CAST_POINTER_TO_64;
1380         r_step->data.cast_pointer.new_offset = new_member_offset;
1381         r_step->data.cast_pointer.old_offset = old_member_offset;
1382         r_step->data.cast_pointer.array_len = shared_array_length;
1383       }
1384       else if (newsdna->pointer_size == 4 && oldsdna->pointer_size == 8) {
1385         /* Need to convert from 64 bit to 32 bit pointers. */
1386         r_step->type = RECONSTRUCT_STEP_CAST_POINTER_TO_32;
1387         r_step->data.cast_pointer.new_offset = new_member_offset;
1388         r_step->data.cast_pointer.old_offset = old_member_offset;
1389         r_step->data.cast_pointer.array_len = shared_array_length;
1390       }
1391       else {
1392         BLI_assert(!"invalid pointer size");
1393         r_step->type = RECONSTRUCT_STEP_INIT_ZERO;
1394       }
1395       break;
1396     }
1397   }
1398 }
1399 
1400 /** Useful function when debugging the reconstruct steps. */
print_reconstruct_step(ReconstructStep * step,const SDNA * oldsdna,const SDNA * newsdna)1401 static void print_reconstruct_step(ReconstructStep *step, const SDNA *oldsdna, const SDNA *newsdna)
1402 {
1403   switch (step->type) {
1404     case RECONSTRUCT_STEP_INIT_ZERO: {
1405       printf("init zero");
1406       break;
1407     }
1408     case RECONSTRUCT_STEP_MEMCPY: {
1409       printf("memcpy, size: %d, old offset: %d, new offset: %d",
1410              step->data.memcpy.size,
1411              step->data.memcpy.old_offset,
1412              step->data.memcpy.new_offset);
1413       break;
1414     }
1415     case RECONSTRUCT_STEP_CAST_PRIMITIVE: {
1416       printf(
1417           "cast element, old type: %d ('%s'), new type: %d ('%s'), old offset: %d, new offset: "
1418           "%d, length: %d",
1419           (int)step->data.cast_primitive.old_type,
1420           oldsdna->types[step->data.cast_primitive.old_type],
1421           (int)step->data.cast_primitive.new_type,
1422           newsdna->types[step->data.cast_primitive.new_type],
1423           step->data.cast_primitive.old_offset,
1424           step->data.cast_primitive.new_offset,
1425           step->data.cast_primitive.array_len);
1426       break;
1427     }
1428     case RECONSTRUCT_STEP_CAST_POINTER_TO_32: {
1429       printf("pointer to 32, old offset: %d, new offset: %d, length: %d",
1430              step->data.cast_pointer.old_offset,
1431              step->data.cast_pointer.new_offset,
1432              step->data.cast_pointer.array_len);
1433       break;
1434     }
1435     case RECONSTRUCT_STEP_CAST_POINTER_TO_64: {
1436       printf("pointer to 64, old offset: %d, new offset: %d, length: %d",
1437              step->data.cast_pointer.old_offset,
1438              step->data.cast_pointer.new_offset,
1439              step->data.cast_pointer.array_len);
1440       break;
1441     }
1442     case RECONSTRUCT_STEP_SUBSTRUCT: {
1443       printf(
1444           "substruct, old offset: %d, new offset: %d, new struct: %d ('%s', size per struct: %d), "
1445           "length: %d",
1446           step->data.substruct.old_offset,
1447           step->data.substruct.new_offset,
1448           step->data.substruct.new_struct_nr,
1449           newsdna->types[newsdna->structs[step->data.substruct.new_struct_nr]->type],
1450           newsdna->types_size[newsdna->structs[step->data.substruct.new_struct_nr]->type],
1451           step->data.substruct.array_len);
1452       break;
1453     }
1454   }
1455 }
1456 
1457 /**
1458  * Generate an array of reconstruct steps for the given #new_struct. There will be one
1459  * reconstruct step for every member.
1460  */
create_reconstruct_steps_for_struct(const SDNA * oldsdna,const SDNA * newsdna,const char * compare_flags,const SDNA_Struct * old_struct,const SDNA_Struct * new_struct)1461 static ReconstructStep *create_reconstruct_steps_for_struct(const SDNA *oldsdna,
1462                                                             const SDNA *newsdna,
1463                                                             const char *compare_flags,
1464                                                             const SDNA_Struct *old_struct,
1465                                                             const SDNA_Struct *new_struct)
1466 {
1467   ReconstructStep *steps = MEM_calloc_arrayN(
1468       new_struct->members_len, sizeof(ReconstructStep), __func__);
1469 
1470   int new_member_offset = 0;
1471   for (int new_member_index = 0; new_member_index < new_struct->members_len; new_member_index++) {
1472     const SDNA_StructMember *new_member = &new_struct->members[new_member_index];
1473     init_reconstruct_step_for_member(oldsdna,
1474                                      newsdna,
1475                                      compare_flags,
1476                                      old_struct,
1477                                      new_member,
1478                                      new_member_offset,
1479                                      &steps[new_member_index]);
1480     new_member_offset += get_member_size_in_bytes(newsdna, new_member);
1481   }
1482 
1483   return steps;
1484 }
1485 
1486 /** Compresses an array of reconstruct steps in-place and returns the new step count. */
compress_reconstruct_steps(ReconstructStep * steps,const int old_step_count)1487 static int compress_reconstruct_steps(ReconstructStep *steps, const int old_step_count)
1488 {
1489   int new_step_count = 0;
1490   for (int a = 0; a < old_step_count; a++) {
1491     ReconstructStep *step = &steps[a];
1492     switch (step->type) {
1493       case RECONSTRUCT_STEP_INIT_ZERO:
1494         /* These steps are simply removed. */
1495         break;
1496       case RECONSTRUCT_STEP_MEMCPY:
1497         if (new_step_count > 0) {
1498           /* Try to merge this memcpy step with the previous one. */
1499           ReconstructStep *prev_step = &steps[new_step_count - 1];
1500           if (prev_step->type == RECONSTRUCT_STEP_MEMCPY) {
1501             /* Check if there are no bytes between the blocks to copy. */
1502             if (prev_step->data.memcpy.old_offset + prev_step->data.memcpy.size ==
1503                     step->data.memcpy.old_offset &&
1504                 prev_step->data.memcpy.new_offset + prev_step->data.memcpy.size ==
1505                     step->data.memcpy.new_offset) {
1506               prev_step->data.memcpy.size += step->data.memcpy.size;
1507               break;
1508             }
1509           }
1510         }
1511         steps[new_step_count] = *step;
1512         new_step_count++;
1513         break;
1514       case RECONSTRUCT_STEP_CAST_PRIMITIVE:
1515       case RECONSTRUCT_STEP_CAST_POINTER_TO_32:
1516       case RECONSTRUCT_STEP_CAST_POINTER_TO_64:
1517       case RECONSTRUCT_STEP_SUBSTRUCT:
1518         /* These steps are not changed at all for now. It should be possible to merge consecutive
1519          * steps of the same type, but it is not really worth it. */
1520         steps[new_step_count] = *step;
1521         new_step_count++;
1522         break;
1523     }
1524   }
1525   return new_step_count;
1526 }
1527 
1528 /**
1529  * Pre-process information about how structs in \a newsdna can be reconstructed from structs in
1530  * \a oldsdna. This information is then used to speedup #DNA_struct_reconstruct.
1531  */
DNA_reconstruct_info_create(const SDNA * oldsdna,const SDNA * newsdna,const char * compare_flags)1532 DNA_ReconstructInfo *DNA_reconstruct_info_create(const SDNA *oldsdna,
1533                                                  const SDNA *newsdna,
1534                                                  const char *compare_flags)
1535 {
1536   DNA_ReconstructInfo *reconstruct_info = MEM_callocN(sizeof(DNA_ReconstructInfo), __func__);
1537   reconstruct_info->oldsdna = oldsdna;
1538   reconstruct_info->newsdna = newsdna;
1539   reconstruct_info->compare_flags = compare_flags;
1540   reconstruct_info->step_counts = MEM_malloc_arrayN(sizeof(int), newsdna->structs_len, __func__);
1541   reconstruct_info->steps = MEM_malloc_arrayN(
1542       sizeof(ReconstructStep *), newsdna->structs_len, __func__);
1543 
1544   /* Generate reconstruct steps for all structs. */
1545   for (int new_struct_nr = 0; new_struct_nr < newsdna->structs_len; new_struct_nr++) {
1546     const SDNA_Struct *new_struct = newsdna->structs[new_struct_nr];
1547     const char *new_struct_name = newsdna->types[new_struct->type];
1548     const int old_struct_nr = DNA_struct_find_nr(oldsdna, new_struct_name);
1549     if (old_struct_nr < 0) {
1550       reconstruct_info->steps[new_struct_nr] = NULL;
1551       reconstruct_info->step_counts[new_struct_nr] = 0;
1552       continue;
1553     }
1554     const SDNA_Struct *old_struct = oldsdna->structs[old_struct_nr];
1555     ReconstructStep *steps = create_reconstruct_steps_for_struct(
1556         oldsdna, newsdna, compare_flags, old_struct, new_struct);
1557 
1558     int steps_len = new_struct->members_len;
1559     /* Comment the line below to skip the compression for debugging purposes. */
1560     steps_len = compress_reconstruct_steps(steps, new_struct->members_len);
1561 
1562     reconstruct_info->steps[new_struct_nr] = steps;
1563     reconstruct_info->step_counts[new_struct_nr] = steps_len;
1564 
1565 /* This is useful when debugging the reconstruct steps. */
1566 #if 0
1567     printf("%s: \n", new_struct_name);
1568     for (int a = 0; a < steps_len; a++) {
1569       printf("  ");
1570       print_reconstruct_step(&steps[a], oldsdna, newsdna);
1571       printf("\n");
1572     }
1573 #endif
1574     UNUSED_VARS(print_reconstruct_step);
1575   }
1576 
1577   return reconstruct_info;
1578 }
1579 
DNA_reconstruct_info_free(DNA_ReconstructInfo * reconstruct_info)1580 void DNA_reconstruct_info_free(DNA_ReconstructInfo *reconstruct_info)
1581 {
1582   for (int a = 0; a < reconstruct_info->newsdna->structs_len; a++) {
1583     if (reconstruct_info->steps[a] != NULL) {
1584       MEM_freeN(reconstruct_info->steps[a]);
1585     }
1586   }
1587   MEM_freeN(reconstruct_info->steps);
1588   MEM_freeN(reconstruct_info->step_counts);
1589   MEM_freeN(reconstruct_info);
1590 }
1591 
1592 /**
1593  * Returns the offset of the field with the specified name and type within the specified
1594  * struct type in #SDNA, -1 on failure.
1595  */
DNA_elem_offset(SDNA * sdna,const char * stype,const char * vartype,const char * name)1596 int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
1597 {
1598   const int SDNAnr = DNA_struct_find_nr(sdna, stype);
1599   BLI_assert(SDNAnr != -1);
1600   const SDNA_Struct *const spo = sdna->structs[SDNAnr];
1601   return elem_offset(sdna, vartype, name, spo);
1602 }
1603 
DNA_struct_find(const SDNA * sdna,const char * stype)1604 bool DNA_struct_find(const SDNA *sdna, const char *stype)
1605 {
1606   return DNA_struct_find_nr(sdna, stype) != -1;
1607 }
1608 
DNA_struct_elem_find(const SDNA * sdna,const char * stype,const char * vartype,const char * name)1609 bool DNA_struct_elem_find(const SDNA *sdna,
1610                           const char *stype,
1611                           const char *vartype,
1612                           const char *name)
1613 {
1614   const int SDNAnr = DNA_struct_find_nr(sdna, stype);
1615 
1616   if (SDNAnr != -1) {
1617     const SDNA_Struct *const spo = sdna->structs[SDNAnr];
1618     const bool found = elem_exists(sdna, vartype, name, spo);
1619 
1620     if (found) {
1621       return true;
1622     }
1623   }
1624   return false;
1625 }
1626 
1627 /** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
DNA_struct_alias_elem_find(const SDNA * sdna,const char * stype,const char * vartype,const char * name)1628 bool DNA_struct_alias_elem_find(const SDNA *sdna,
1629                                 const char *stype,
1630                                 const char *vartype,
1631                                 const char *name)
1632 {
1633   const int SDNAnr = DNA_struct_alias_find_nr(sdna, stype);
1634 
1635   if (SDNAnr != -1) {
1636     const SDNA_Struct *const spo = sdna->structs[SDNAnr];
1637     const bool found = elem_exists_alias(sdna, vartype, name, spo);
1638 
1639     if (found) {
1640       return true;
1641     }
1642   }
1643   return false;
1644 }
1645 
1646 /**
1647  * Returns the size in bytes of a primitive type.
1648  */
DNA_elem_type_size(const eSDNA_Type elem_nr)1649 int DNA_elem_type_size(const eSDNA_Type elem_nr)
1650 {
1651   /* should contain all enum types */
1652   switch (elem_nr) {
1653     case SDNA_TYPE_CHAR:
1654     case SDNA_TYPE_UCHAR:
1655       return 1;
1656     case SDNA_TYPE_SHORT:
1657     case SDNA_TYPE_USHORT:
1658       return 2;
1659     case SDNA_TYPE_INT:
1660     case SDNA_TYPE_FLOAT:
1661       return 4;
1662     case SDNA_TYPE_DOUBLE:
1663     case SDNA_TYPE_INT64:
1664     case SDNA_TYPE_UINT64:
1665       return 8;
1666   }
1667 
1668   /* weak */
1669   return 8;
1670 }
1671 
1672 /* -------------------------------------------------------------------- */
1673 /** \name Version Patch DNA
1674  * \{ */
1675 
DNA_sdna_patch_struct_nr(SDNA * sdna,const int struct_name_old_nr,const char * struct_name_new)1676 static bool DNA_sdna_patch_struct_nr(SDNA *sdna,
1677                                      const int struct_name_old_nr,
1678                                      const char *struct_name_new)
1679 {
1680   BLI_assert(DNA_struct_find_nr(DNA_sdna_current_get(), struct_name_new) != -1);
1681   const SDNA_Struct *struct_info = sdna->structs[struct_name_old_nr];
1682 #ifdef WITH_DNA_GHASH
1683   BLI_ghash_remove(sdna->structs_map, (void *)sdna->types[struct_info->type], NULL, NULL);
1684   BLI_ghash_insert(
1685       sdna->structs_map, (void *)struct_name_new, POINTER_FROM_INT(struct_name_old_nr));
1686 #endif
1687   sdna->types[struct_info->type] = struct_name_new;
1688   return true;
1689 }
1690 /**
1691  * Rename a struct
1692  */
DNA_sdna_patch_struct(SDNA * sdna,const char * struct_name_old,const char * struct_name_new)1693 bool DNA_sdna_patch_struct(SDNA *sdna, const char *struct_name_old, const char *struct_name_new)
1694 {
1695   const int struct_name_old_nr = DNA_struct_find_nr(sdna, struct_name_old);
1696   if (struct_name_old_nr != -1) {
1697     return DNA_sdna_patch_struct_nr(sdna, struct_name_old_nr, struct_name_new);
1698   }
1699   return false;
1700 }
1701 
1702 /* Make public if called often with same struct (avoid duplicate look-ups). */
DNA_sdna_patch_struct_member_nr(SDNA * sdna,const int struct_name_nr,const char * elem_old,const char * elem_new)1703 static bool DNA_sdna_patch_struct_member_nr(SDNA *sdna,
1704                                             const int struct_name_nr,
1705                                             const char *elem_old,
1706                                             const char *elem_new)
1707 {
1708   /* These names aren't handled here (it's not used).
1709    * Ensure they are never used or we get out of sync arrays. */
1710   BLI_assert(sdna->alias.names == NULL);
1711   const int elem_old_len = strlen(elem_old);
1712   const int elem_new_len = strlen(elem_new);
1713   BLI_assert(elem_new != NULL);
1714   SDNA_Struct *sp = sdna->structs[struct_name_nr];
1715   for (int elem_index = sp->members_len; elem_index > 0; elem_index--) {
1716     SDNA_StructMember *member = &sp->members[elem_index];
1717     const char *elem_old_full = sdna->names[member->name];
1718     /* Start & end offsets in 'elem_old_full'. */
1719     uint elem_old_full_offset_start;
1720     if (DNA_elem_id_match(elem_old, elem_old_len, elem_old_full, &elem_old_full_offset_start)) {
1721       if (sdna->mem_arena == NULL) {
1722         sdna->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1723       }
1724       const char *elem_new_full = DNA_elem_id_rename(sdna->mem_arena,
1725                                                      elem_old,
1726                                                      elem_old_len,
1727                                                      elem_new,
1728                                                      elem_new_len,
1729                                                      elem_old_full,
1730                                                      strlen(elem_old_full),
1731                                                      elem_old_full_offset_start);
1732 
1733       if (sdna->names_len == sdna->names_len_alloc) {
1734         sdna->names_len_alloc += 64;
1735         sdna->names = MEM_recallocN((void *)sdna->names,
1736                                     sizeof(*sdna->names) * sdna->names_len_alloc);
1737         sdna->names_array_len = MEM_recallocN(
1738             (void *)sdna->names_array_len, sizeof(*sdna->names_array_len) * sdna->names_len_alloc);
1739       }
1740       const short name_nr_prev = member->name;
1741       member->name = sdna->names_len++;
1742       sdna->names[member->name] = elem_new_full;
1743       sdna->names_array_len[member->name] = sdna->names_array_len[name_nr_prev];
1744 
1745       return true;
1746     }
1747   }
1748   return false;
1749 }
1750 /**
1751  * Replace \a elem_old with \a elem_new for struct \a struct_name
1752  * handles search & replace, maintaining surrounding non-identifier characters
1753  * such as pointer & array size.
1754  */
DNA_sdna_patch_struct_member(SDNA * sdna,const char * struct_name,const char * elem_old,const char * elem_new)1755 bool DNA_sdna_patch_struct_member(SDNA *sdna,
1756                                   const char *struct_name,
1757                                   const char *elem_old,
1758                                   const char *elem_new)
1759 {
1760   const int struct_name_nr = DNA_struct_find_nr(sdna, struct_name);
1761   if (struct_name_nr != -1) {
1762     return DNA_sdna_patch_struct_member_nr(sdna, struct_name_nr, elem_old, elem_new);
1763   }
1764   return false;
1765 }
1766 
1767 /** \} */
1768 
1769 /* -------------------------------------------------------------------- */
1770 /** \name Versioning (Forward Compatible)
1771  *
1772  * Versioning that allows new names.
1773  * \{ */
1774 
1775 /**
1776  * Names are shared between structs which causes problems renaming.
1777  * Make sure every struct member gets its own name so renaming only ever impacts a single struct.
1778  *
1779  * The resulting SDNA is never written to disk.
1780  */
sdna_expand_names(SDNA * sdna)1781 static void sdna_expand_names(SDNA *sdna)
1782 {
1783   int names_expand_len = 0;
1784   for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
1785     const SDNA_Struct *struct_old = sdna->structs[struct_nr];
1786     names_expand_len += struct_old->members_len;
1787   }
1788   const char **names_expand = MEM_mallocN(sizeof(*names_expand) * names_expand_len, __func__);
1789   short *names_array_len_expand = MEM_mallocN(sizeof(*names_array_len_expand) * names_expand_len,
1790                                               __func__);
1791 
1792   int names_expand_index = 0;
1793   for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
1794     /* We can't edit this memory 'sdna->structs' points to (readonly datatoc file). */
1795     const SDNA_Struct *struct_old = sdna->structs[struct_nr];
1796 
1797     const int array_size = sizeof(short) * 2 + sizeof(SDNA_StructMember) * struct_old->members_len;
1798     SDNA_Struct *struct_new = BLI_memarena_alloc(sdna->mem_arena, array_size);
1799     memcpy(struct_new, struct_old, array_size);
1800     sdna->structs[struct_nr] = struct_new;
1801 
1802     for (int i = 0; i < struct_old->members_len; i++) {
1803       const SDNA_StructMember *member_old = &struct_old->members[i];
1804       SDNA_StructMember *member_new = &struct_new->members[i];
1805 
1806       names_expand[names_expand_index] = sdna->names[member_old->name];
1807       names_array_len_expand[names_expand_index] = sdna->names_array_len[member_old->name];
1808 
1809       BLI_assert(names_expand_index < SHRT_MAX);
1810       member_new->name = names_expand_index;
1811       names_expand_index++;
1812     }
1813   }
1814   MEM_freeN((void *)sdna->names);
1815   sdna->names = names_expand;
1816 
1817   MEM_freeN((void *)sdna->names_array_len);
1818   sdna->names_array_len = names_array_len_expand;
1819 
1820   sdna->names_len = names_expand_len;
1821 }
1822 
dna_sdna_alias_from_static_elem_full(SDNA * sdna,GHash * elem_map_alias_from_static,const char * struct_name_static,const char * elem_static_full)1823 static const char *dna_sdna_alias_from_static_elem_full(SDNA *sdna,
1824                                                         GHash *elem_map_alias_from_static,
1825                                                         const char *struct_name_static,
1826                                                         const char *elem_static_full)
1827 {
1828   const int elem_static_full_len = strlen(elem_static_full);
1829   char *elem_static = alloca(elem_static_full_len + 1);
1830   const int elem_static_len = DNA_elem_id_strip_copy(elem_static, elem_static_full);
1831   const char *str_pair[2] = {struct_name_static, elem_static};
1832   const char *elem_alias = BLI_ghash_lookup(elem_map_alias_from_static, str_pair);
1833   if (elem_alias) {
1834     return DNA_elem_id_rename(sdna->mem_arena,
1835                               elem_static,
1836                               elem_static_len,
1837                               elem_alias,
1838                               strlen(elem_alias),
1839                               elem_static_full,
1840                               elem_static_full_len,
1841                               DNA_elem_id_offset_start(elem_static_full));
1842   }
1843   return NULL;
1844 }
1845 
DNA_sdna_alias_data_ensure(SDNA * sdna)1846 void DNA_sdna_alias_data_ensure(SDNA *sdna)
1847 {
1848   /* We may want this to be optional later. */
1849   const bool use_legacy_hack = true;
1850 
1851   if (sdna->mem_arena == NULL) {
1852     sdna->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1853   }
1854 
1855   GHash *struct_map_alias_from_static;
1856   GHash *elem_map_alias_from_static;
1857 
1858   DNA_alias_maps(
1859       DNA_RENAME_ALIAS_FROM_STATIC, &struct_map_alias_from_static, &elem_map_alias_from_static);
1860 
1861   if (sdna->alias.types == NULL) {
1862     sdna->alias.types = MEM_mallocN(sizeof(*sdna->alias.types) * sdna->types_len, __func__);
1863     for (int type_nr = 0; type_nr < sdna->types_len; type_nr++) {
1864       const char *struct_name_static = sdna->types[type_nr];
1865 
1866       if (use_legacy_hack) {
1867         struct_name_static = DNA_struct_rename_legacy_hack_alias_from_static(struct_name_static);
1868       }
1869 
1870       sdna->alias.types[type_nr] = BLI_ghash_lookup_default(
1871           struct_map_alias_from_static, struct_name_static, (void *)struct_name_static);
1872     }
1873   }
1874 
1875   if (sdna->alias.names == NULL) {
1876     sdna_expand_names(sdna);
1877     sdna->alias.names = MEM_mallocN(sizeof(*sdna->alias.names) * sdna->names_len, __func__);
1878     for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
1879       const SDNA_Struct *struct_info = sdna->structs[struct_nr];
1880       const char *struct_name_static = sdna->types[struct_info->type];
1881 
1882       if (use_legacy_hack) {
1883         struct_name_static = DNA_struct_rename_legacy_hack_alias_from_static(struct_name_static);
1884       }
1885 
1886       for (int a = 0; a < struct_info->members_len; a++) {
1887         const SDNA_StructMember *member = &struct_info->members[a];
1888         const char *elem_alias_full = dna_sdna_alias_from_static_elem_full(
1889             sdna, elem_map_alias_from_static, struct_name_static, sdna->names[member->name]);
1890         if (elem_alias_full != NULL) {
1891           sdna->alias.names[member->name] = elem_alias_full;
1892         }
1893         else {
1894           sdna->alias.names[member->name] = sdna->names[member->name];
1895         }
1896       }
1897     }
1898   }
1899   BLI_ghash_free(struct_map_alias_from_static, NULL, NULL);
1900   BLI_ghash_free(elem_map_alias_from_static, MEM_freeN, NULL);
1901 }
1902 
1903 /**
1904  * Separated from #DNA_sdna_alias_data_ensure because it's not needed
1905  * unless we want to lookup aliased struct names (#DNA_struct_alias_find_nr and friends).
1906  */
DNA_sdna_alias_data_ensure_structs_map(SDNA * sdna)1907 void DNA_sdna_alias_data_ensure_structs_map(SDNA *sdna)
1908 {
1909   DNA_sdna_alias_data_ensure(sdna);
1910 #ifdef WITH_DNA_GHASH
1911   /* create a ghash lookup to speed up */
1912   struct GHash *structs_map = BLI_ghash_str_new_ex(__func__, sdna->structs_len);
1913   for (intptr_t nr = 0; nr < sdna->structs_len; nr++) {
1914     const SDNA_Struct *struct_info = sdna->structs[nr];
1915     BLI_ghash_insert(
1916         structs_map, (void *)sdna->alias.types[struct_info->type], POINTER_FROM_INT(nr));
1917   }
1918   sdna->alias.structs_map = structs_map;
1919 #else
1920   UNUSED_VARS(sdna);
1921 #endif
1922 }
1923 
1924 /** \} */
1925