Blender V4.5
dna_genfile.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
14
15#include <algorithm>
16#include <climits>
17#include <cstdio>
18#include <cstdlib>
19#include <cstring>
20#include <iostream>
21
22#include <fmt/format.h>
23
24#include "MEM_guardedalloc.h" /* for MEM_freeN MEM_mallocN MEM_callocN */
25
26#include "BLI_endian_switch.h"
27#include "BLI_ghash.h"
28#include "BLI_index_range.hh"
30#include "BLI_memarena.h"
31#include "BLI_set.hh"
32#include "BLI_utildefines.h"
33
34#include "DNA_genfile.h"
35#include "DNA_print.hh"
36#include "DNA_sdna_types.h" /* for SDNA ;-) */
37
119
120#ifdef __BIG_ENDIAN__
121/* Big Endian */
122# define MAKE_ID(a, b, c, d) (int(a) << 24 | int(b) << 16 | (c) << 8 | (d))
123#else
124/* Little Endian */
125# define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
126#endif
127
128/* ************************* DIV ********************** */
129
131{
132 if (sdna->data_alloc) {
133 MEM_freeN(sdna->data);
134 }
135
136 MEM_SAFE_FREE(sdna->members);
138 MEM_SAFE_FREE(sdna->types);
139 MEM_SAFE_FREE(sdna->structs);
141
142#ifdef WITH_DNA_GHASH
143 if (sdna->types_to_structs_map) {
144 BLI_ghash_free(sdna->types_to_structs_map, nullptr, nullptr);
145 }
146#endif
147
148 if (sdna->mem_arena) {
150 }
151
154#ifdef WITH_DNA_GHASH
155 if (sdna->alias.types_to_structs_map) {
156 BLI_ghash_free(sdna->alias.types_to_structs_map, nullptr, nullptr);
157 }
158#endif
159
160 MEM_freeN(sdna);
161}
162
163int DNA_struct_size(const SDNA *sdna, int struct_index)
164{
165 return sdna->types_size[sdna->structs[struct_index]->type_index];
166}
167
171static bool ispointer(const char *name)
172{
173 /* check if pointer or function pointer */
174 return (name[0] == '*' || (name[0] == '(' && name[1] == '*'));
175}
176
177int DNA_struct_member_size(const SDNA *sdna, short type, short member_index)
178{
179 const char *cp = sdna->members[member_index];
180 int len = 0;
181
182 /* is it a pointer or function pointer? */
183 if (ispointer(cp)) {
184 /* has the name an extra length? (array) */
185 len = sdna->pointer_size * sdna->members_array_num[member_index];
186 }
187 else if (sdna->types_size[type]) {
188 /* has the name an extra length? (array) */
189 len = int(sdna->types_size[type]) * sdna->members_array_num[member_index];
190 }
191
192 return len;
193}
194
195#if 0
196static void printstruct(SDNA *sdna, short struct_index)
197{
198 /* is for debug */
199
200 SDNA_Struct *struct_info = sdna->structs[struct_index];
201 printf("struct %s\n", sdna->types[struct_info->type]);
202
203 for (int b = 0; b < struct_info->members_len; b++) {
204 SDNA_StructMember *struct_member = &struct_info->members[b];
205 printf(" %s %s\n", sdna->types[struct_member->type], sdna->names[struct_member->name]);
206 }
207}
208#endif
209
214 /* From SDNA struct. */
215 const char **types,
216 const int /*types_num*/,
217 SDNA_Struct **const structs,
218 const int structs_num,
219#ifdef WITH_DNA_GHASH
220 GHash *structs_map,
221#endif
222 /* Regular args. */
223 const char *str,
224 uint *struct_index_last)
225{
226 if (*struct_index_last < structs_num) {
227 const SDNA_Struct *struct_info = structs[*struct_index_last];
228 if (STREQ(types[struct_info->type_index], str)) {
229 return *struct_index_last;
230 }
231 }
232
233#ifdef WITH_DNA_GHASH
234 {
235 void **struct_index_p = BLI_ghash_lookup_p(structs_map, str);
236 if (struct_index_p) {
237 const int struct_index = POINTER_AS_INT(*struct_index_p);
238 *struct_index_last = struct_index;
239 return struct_index;
240 }
241 }
242#else
243 {
244 for (int struct_index = 0; struct_index < types_num; struct_index++) {
245 const SDNA_Struct *struct_info = structs[struct_index];
246 if (STREQ(types[struct_info->type], str)) {
247 *struct_index_last = struct_index;
248 return struct_index;
249 }
250 }
251 }
252#endif
253 return -1;
254}
255
257 const char *str,
258 uint *struct_index_last)
259{
260#ifdef WITH_DNA_GHASH
261 BLI_assert(sdna->types_to_structs_map != nullptr);
262#endif
264 /* Expand SDNA. */
265 sdna->types,
266 sdna->types_num,
267 sdna->structs,
268 sdna->structs_num,
269#ifdef WITH_DNA_GHASH
271#endif
272 /* Regular args. */
273 str,
274 struct_index_last);
275}
276
277int DNA_struct_find_index_with_alias_ex(const SDNA *sdna, const char *str, uint *struct_index_last)
278{
279#ifdef WITH_DNA_GHASH
280 BLI_assert(sdna->alias.types_to_structs_map != nullptr);
281#endif
283 /* Expand SDNA. */
284 sdna->alias.types,
285 sdna->types_num,
286 sdna->structs,
287 sdna->structs_num,
288#ifdef WITH_DNA_GHASH
290#endif
291 /* Regular args. */
292 str,
293 struct_index_last);
294}
295
296int DNA_struct_find_index_without_alias(const SDNA *sdna, const char *str)
297{
298 uint index_last_dummy = UINT_MAX;
299 return DNA_struct_find_index_without_alias_ex(sdna, str, &index_last_dummy);
300}
301
302int DNA_struct_find_with_alias(const SDNA *sdna, const char *str)
303{
304 uint index_last_dummy = UINT_MAX;
305 return DNA_struct_find_index_with_alias_ex(sdna, str, &index_last_dummy);
306}
307
308bool DNA_struct_exists_with_alias(const SDNA *sdna, const char *str)
309{
310 return DNA_struct_find_with_alias(sdna, str) != -1;
311}
312
313/* ************************* END DIV ********************** */
314
315/* ************************* READ DNA ********************** */
316
317BLI_INLINE const char *pad_up_4(const char *ptr)
318{
319 return (const char *)((uintptr_t(ptr) + 3) & ~3);
320}
321
325static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error_message)
326{
327 int member_index_gravity_fix = -1;
328
329 int *data = (int *)sdna->data;
330
331 /* Clear pointers in case of error. */
332 sdna->types = nullptr;
333 sdna->types_size = nullptr;
334 sdna->types_alignment = nullptr;
335 sdna->structs = nullptr;
336#ifdef WITH_DNA_GHASH
337 sdna->types_to_structs_map = nullptr;
338#endif
339
340 sdna->members = nullptr;
341 sdna->members_array_num = nullptr;
342
343 sdna->mem_arena = nullptr;
344
345 /* Lazy initialize. */
346 memset(&sdna->alias, 0, sizeof(sdna->alias));
347
348 /* Struct DNA ('SDNA') */
349 if (*data != MAKE_ID('S', 'D', 'N', 'A')) {
350 *r_error_message = "SDNA error in SDNA file";
351 return false;
352 }
353
354 const char *cp;
355
356 data++;
357 /* Names array ('NAME') */
358 if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
359 data++;
360
361 sdna->members_num = *data;
362 if (do_endian_swap) {
364 }
365 sdna->members_num_alloc = sdna->members_num;
366
367 data++;
368 sdna->members = MEM_calloc_arrayN<const char *>(sdna->members_num, "sdnanames");
369 }
370 if (!sdna->members) {
371 *r_error_message = "NAME error in SDNA file";
372 return false;
373 }
374
375 cp = (char *)data;
376 for (int member_index = 0; member_index < sdna->members_num; member_index++) {
377 sdna->members[member_index] = cp;
378
379 /* "float gravity [3]" was parsed wrong giving both "gravity" and
380 * "[3]" members. we rename "[3]", and later set the type of
381 * "gravity" to "void" so the offsets work out correct */
382 if (*cp == '[' && STREQ(cp, "[3]")) {
383 if (member_index && STREQ(sdna->members[member_index - 1], "Cvi")) {
384 sdna->members[member_index] = "gravity[3]";
385 member_index_gravity_fix = member_index;
386 }
387 }
388 while (*cp) {
389 cp++;
390 }
391 cp++;
392 }
393
394 cp = pad_up_4(cp);
395
396 /* Type names array ('TYPE') */
397 data = (int *)cp;
398 if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
399 data++;
400
401 sdna->types_num = *data;
402 if (do_endian_swap) {
404 }
405
406 data++;
407 sdna->types = MEM_calloc_arrayN<const char *>(sdna->types_num, "sdnatypes");
408 }
409 if (!sdna->types) {
410 *r_error_message = "TYPE error in SDNA file";
411 return false;
412 }
413
414 cp = (char *)data;
415 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
416 /* WARNING! See: DNA_struct_rename_legacy_hack_static_from_alias docs. */
418 while (*cp) {
419 cp++;
420 }
421 cp++;
422 }
423
424 cp = pad_up_4(cp);
425
426 /* Type lengths array ('TLEN') */
427 data = (int *)cp;
428 short *sp;
429 if (*data == MAKE_ID('T', 'L', 'E', 'N')) {
430 data++;
431 sp = (short *)data;
432 sdna->types_size = sp;
433
434 if (do_endian_swap) {
436 }
437
438 sp += sdna->types_num;
439 }
440 if (!sdna->types_size) {
441 *r_error_message = "TLEN error in SDNA file";
442 return false;
443 }
444 /* prevent BUS error */
445 if (sdna->types_num & 1) {
446 sp++;
447 }
448
449 /* Struct array ('STRC') */
450 data = (int *)sp;
451 if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
452 data++;
453
454 sdna->structs_num = *data;
455 if (do_endian_swap) {
457 }
458
459 data++;
460 sdna->structs = MEM_calloc_arrayN<SDNA_Struct *>(sdna->structs_num, "sdnastrcs");
461 }
462 if (!sdna->structs) {
463 *r_error_message = "STRC error in SDNA file";
464 return false;
465 }
466
467 /* Safety check, to ensure that there is no multiple usages of a same struct index. */
468 blender::Set<short> struct_indices;
469 sp = (short *)data;
470 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
471 SDNA_Struct *struct_info = (SDNA_Struct *)sp;
472 sdna->structs[struct_index] = struct_info;
473
474 if (do_endian_swap) {
475 BLI_endian_switch_int16(&struct_info->type_index);
477
478 for (short a = 0; a < struct_info->members_num; a++) {
479 SDNA_StructMember *member = &struct_info->members[a];
482 }
483 }
484 if (!struct_indices.add(struct_info->type_index)) {
485 *r_error_message = "Invalid duplicate struct type index in SDNA file";
486 return false;
487 }
488
489 sp += 2 + (sizeof(SDNA_StructMember) / sizeof(short)) * struct_info->members_num;
490 }
491
492 {
493 /* second part of gravity problem, setting "gravity" type to void */
494 if (member_index_gravity_fix > -1) {
495 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
496 sp = (short *)sdna->structs[struct_index];
497 if (STREQ(sdna->types[sp[0]], "ClothSimSettings")) {
498 sp[10] = SDNA_TYPE_VOID;
499 }
500 }
501 }
502 }
503
504#ifdef WITH_DNA_GHASH
505 {
506 /* create a ghash lookup to speed up */
507 sdna->types_to_structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->structs_num);
508
509 for (intptr_t struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
510 SDNA_Struct *struct_info = sdna->structs[struct_index];
512 (void *)sdna->types[struct_info->type_index],
513 POINTER_FROM_INT(struct_index));
514 }
515 }
516#endif
517
518 /* Calculate 'sdna->pointer_size'.
519 *
520 * NOTE: Cannot just do `sizeof(void *)` here, since the current DNA may come from a blend-file
521 * saved on a different system, using a different pointer size. So instead, use half the size of
522 * the #ListBase struct (only made of two pointers).
523 */
524 {
525 const int struct_index = DNA_struct_find_index_without_alias(sdna, "ListBase");
526
527 /* Should never happen, only with corrupt file for example. */
528 if (UNLIKELY(struct_index == -1)) {
529 *r_error_message = "ListBase struct error! Not found.";
530 return false;
531 }
532
533 const SDNA_Struct *struct_info = sdna->structs[struct_index];
534 sdna->pointer_size = sdna->types_size[struct_info->type_index] / 2;
535
536 /* Should never fail, double-check that #ListBase struct is still what is should be
537 * (a couple of pointers and nothing else). */
538 if (UNLIKELY(struct_info->members_num != 2 || !ELEM(sdna->pointer_size, 4, 8))) {
539 *r_error_message = "ListBase struct error: invalid computed pointer-size.";
540 return false;
541 }
542 }
543
544 /* Cache name size. */
545 {
546 short *members_array_num = MEM_malloc_arrayN<short>(size_t(sdna->members_num), __func__);
547 for (int member_index = 0; member_index < sdna->members_num; member_index++) {
548 members_array_num[member_index] = DNA_member_array_num(sdna->members[member_index]);
549 }
550 sdna->members_array_num = members_array_num;
551 }
552
553 sdna->types_alignment = MEM_malloc_arrayN<int>(size_t(sdna->types_num), __func__);
554 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
555 sdna->types_alignment[type_index] = int(__STDCPP_DEFAULT_NEW_ALIGNMENT__);
556 }
557 {
558 /* TODO: This should be generalized at some point. We should be able to specify `overaligned`
559 * types directly in the DNA struct definitions. */
560 uint dummy_index = 0;
561 const int mat4x4f_struct_index = DNA_struct_find_index_without_alias_ex(
562 sdna, "mat4x4f", &dummy_index);
563 if (mat4x4f_struct_index > 0) {
564 const SDNA_Struct *struct_info = sdna->structs[mat4x4f_struct_index];
565 const int mat4x4f_type_index = struct_info->type_index;
566 sdna->types_alignment[mat4x4f_type_index] = alignof(blender::float4x4);
567 }
568 }
569
570 return true;
571}
572
574 const int data_len,
575 bool do_endian_swap,
576 bool data_alloc,
577 const bool do_alias,
578 const char **r_error_message)
579{
580 SDNA *sdna = MEM_mallocN<SDNA>("sdna");
581 const char *error_message = nullptr;
582
583 sdna->data_size = data_len;
584 if (data_alloc) {
585 char *data_copy = MEM_malloc_arrayN<char>(size_t(data_len), "sdna_data");
586 memcpy(data_copy, data, data_len);
587 sdna->data = data_copy;
588 }
589 else {
590 sdna->data = static_cast<const char *>(data);
591 }
592 sdna->data_alloc = data_alloc;
593
594 if (init_structDNA(sdna, do_endian_swap, &error_message)) {
595 if (do_alias) {
597 }
598 return sdna;
599 }
600
601 if (r_error_message == nullptr) {
602 fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
603 }
604 else {
605 *r_error_message = error_message;
606 }
607 DNA_sdna_free(sdna);
608 return nullptr;
609}
610
617static SDNA *g_sdna = nullptr;
618
620{
621 g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, true, nullptr);
622}
623
625{
626 BLI_assert(g_sdna != nullptr);
627 return g_sdna;
628}
629
631{
633 g_sdna = nullptr;
634}
635
636/* ******************** END READ DNA ********************** */
637
638/* ******************* HANDLE DNA ***************** */
639
644static void set_compare_flags_for_struct(const SDNA *oldsdna,
645 const SDNA *newsdna,
646 char *compare_flags,
647 const int old_struct_index)
648{
649 if (compare_flags[old_struct_index] != SDNA_CMP_UNKNOWN) {
650 /* This flag has been initialized already. */
651 return;
652 }
653
654 SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
655 const char *struct_name = oldsdna->types[old_struct->type_index];
656
657 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, struct_name);
658 if (new_struct_index == -1) {
659 /* Didn't find a matching new struct, so it has been removed. */
660 compare_flags[old_struct_index] = SDNA_CMP_REMOVED;
661 return;
662 }
663
664 SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
665 if (old_struct->members_num != new_struct->members_num) {
666 /* Structs with a different amount of members are not equal. */
667 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
668 return;
669 }
670 if (oldsdna->types_size[old_struct->type_index] != newsdna->types_size[new_struct->type_index]) {
671 /* Structs that don't have the same size are not equal. */
672 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
673 return;
674 }
675
676 /* Compare each member individually. */
677 for (int member_index = 0; member_index < old_struct->members_num; member_index++) {
678 const SDNA_StructMember *old_member = &old_struct->members[member_index];
679 const SDNA_StructMember *new_member = &new_struct->members[member_index];
680
681 const char *old_type_name = oldsdna->types[old_member->type_index];
682 const char *new_type_name = newsdna->types[new_member->type_index];
683 if (!STREQ(old_type_name, new_type_name)) {
684 /* If two members have a different type in the same place, the structs are not equal. */
685 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
686 return;
687 }
688
689 const char *old_member_name = oldsdna->members[old_member->member_index];
690 const char *new_member_name = newsdna->members[new_member->member_index];
691 if (!STREQ(old_member_name, new_member_name)) {
692 /* If two members have a different name in the same place, the structs are not equal. */
693 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
694 return;
695 }
696
697 if (ispointer(old_member_name)) {
698 if (oldsdna->pointer_size != newsdna->pointer_size) {
699 /* When the struct contains a pointer, and the pointer sizes differ, the structs are not
700 * equal. */
701 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
702 return;
703 }
704 }
705 else {
706 const int old_member_struct_index = DNA_struct_find_index_without_alias(oldsdna,
707 old_type_name);
708 if (old_member_struct_index >= 0) {
709 set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, old_member_struct_index);
710 if (compare_flags[old_member_struct_index] != SDNA_CMP_EQUAL) {
711 /* If an embedded struct is not equal, the parent struct cannot be equal either. */
712 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
713 return;
714 }
715 }
716 }
717 }
718
719 compare_flags[old_struct_index] = SDNA_CMP_EQUAL;
720}
721
722const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
723{
724 if (oldsdna->structs_num == 0) {
725 printf("error: file without SDNA\n");
726 return nullptr;
727 }
728
729 char *compare_flags = MEM_malloc_arrayN<char>(size_t(oldsdna->structs_num), "compare flags");
730 memset(compare_flags, SDNA_CMP_UNKNOWN, oldsdna->structs_num);
731
732 /* Set correct flag for every struct. */
733 for (int old_struct_index = 0; old_struct_index < oldsdna->structs_num; old_struct_index++) {
734 set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, old_struct_index);
735 BLI_assert(compare_flags[old_struct_index] != SDNA_CMP_UNKNOWN);
736 }
737
738 /* First struct is the fake 'raw data' one (see the #SDNA_TYPE_RAW_DATA 'basic type' definition
739 * and its usages). By definition, it is always 'equal'.
740 *
741 * NOTE: Bugs History (pre-4.3).
742 *
743 * It used to be `struct Link`, it was skipped in compare_flags (at index `0`). This was a bug,
744 * and was dirty-patched by setting `compare_flags[0]` to `SDNA_CMP_EQUAL` unconditionally.
745 *
746 * Then the `0` struct became `struct DrawDataList`, which was never actually written in
747 * blend-files.
748 *
749 * Write and read blend-file code also has had implicit assumptions that a `0` value in the
750 * #BHead.SDNAnr (aka DNA struct index) meant 'raw data', and therefore was not representing any
751 * real DNA struct. This assumption has been false for years. By luck, this bug seems to have
752 * been fully harmless, for at least the following reasons:
753 * - Read code always ignored DNA struct info in BHead blocks with a `0` value.
754 * - `DrawDataList` data was never actually written in blend-files.
755 * - `struct Link` never needed DNA-versioning.
756 *
757 * NOTE: This may have been broken in BE/LE conversion cases, however this endianness handling
758 * code have likely been dead/never used in practice for many years now.
759 */
760 BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
762
763/* This code can be enabled to see which structs have changed. */
764#if 0
765 for (int a = 0; a < oldsdna->structs_len; a++) {
766 if (compare_flags[a] == SDNA_CMP_NOT_EQUAL) {
767 SDNA_Struct *struct_info = oldsdna->structs[a];
768 printf("changed: %s\n", oldsdna->types[struct_info->type]);
769 }
770 }
771#endif
772
773 return compare_flags;
774}
775
788static void cast_primitive_type(const eSDNA_Type old_type,
789 const eSDNA_Type new_type,
790 const int array_len,
791 const char *old_data,
792 char *new_data)
793{
794 /* define lengths */
795 const int oldlen = DNA_elem_type_size(old_type);
796 const int curlen = DNA_elem_type_size(new_type);
797
798 double old_value_f = 0.0;
799 /* Intentionally overflow signed values into an unsigned type.
800 * Casting back to a signed value preserves the sign (when the new value is signed). */
801 uint64_t old_value_i = 0;
802
803 for (int a = 0; a < array_len; a++) {
804 switch (old_type) {
805 case SDNA_TYPE_CHAR: {
806 const char value = *old_data;
807 old_value_i = value;
808 old_value_f = double(value);
809 break;
810 }
811 case SDNA_TYPE_UCHAR: {
812 const uchar value = *reinterpret_cast<const uchar *>(old_data);
813 old_value_i = value;
814 old_value_f = double(value);
815 break;
816 }
817 case SDNA_TYPE_SHORT: {
818 const short value = *reinterpret_cast<const short *>(old_data);
819 old_value_i = value;
820 old_value_f = double(value);
821 break;
822 }
823 case SDNA_TYPE_USHORT: {
824 const ushort value = *reinterpret_cast<const ushort *>(old_data);
825 old_value_i = value;
826 old_value_f = double(value);
827 break;
828 }
829 case SDNA_TYPE_INT: {
830 const int value = *reinterpret_cast<const int *>(old_data);
831 old_value_i = value;
832 old_value_f = double(value);
833 break;
834 }
835 case SDNA_TYPE_FLOAT: {
836 const float value = *reinterpret_cast<const float *>(old_data);
837 /* `int64_t` range stored in a `uint64_t`. */
838 old_value_i = uint64_t(int64_t(value));
839 old_value_f = value;
840 break;
841 }
842 case SDNA_TYPE_DOUBLE: {
843 const double value = *reinterpret_cast<const double *>(old_data);
844 /* `int64_t` range stored in a `uint64_t`. */
845 old_value_i = uint64_t(int64_t(value));
846 old_value_f = value;
847 break;
848 }
849 case SDNA_TYPE_INT64: {
850 const int64_t value = *reinterpret_cast<const int64_t *>(old_data);
851 old_value_i = uint64_t(value);
852 old_value_f = double(value);
853 break;
854 }
855 case SDNA_TYPE_UINT64: {
856 const uint64_t value = *reinterpret_cast<const uint64_t *>(old_data);
857 old_value_i = value;
858 old_value_f = double(value);
859 break;
860 }
861 case SDNA_TYPE_INT8: {
862 const int8_t value = *reinterpret_cast<const int8_t *>(old_data);
863 old_value_i = uint64_t(value);
864 old_value_f = double(value);
865 break;
866 }
868 BLI_assert_msg(false, "Conversion from SDNA_TYPE_RAW_DATA is not supported");
869 break;
870 }
871
872 switch (new_type) {
873 case SDNA_TYPE_CHAR:
874 *new_data = char(old_value_i);
875 break;
876 case SDNA_TYPE_UCHAR:
877 *reinterpret_cast<uchar *>(new_data) = uchar(old_value_i);
878 break;
879 case SDNA_TYPE_SHORT:
880 *reinterpret_cast<short *>(new_data) = short(old_value_i);
881 break;
882 case SDNA_TYPE_USHORT:
883 *reinterpret_cast<ushort *>(new_data) = ushort(old_value_i);
884 break;
885 case SDNA_TYPE_INT:
886 *reinterpret_cast<int *>(new_data) = int(old_value_i);
887 break;
888 case SDNA_TYPE_FLOAT:
889 if (old_type < 2) {
890 old_value_f /= 255.0;
891 }
892 *reinterpret_cast<float *>(new_data) = old_value_f;
893 break;
894 case SDNA_TYPE_DOUBLE:
895 if (old_type < 2) {
896 old_value_f /= 255.0;
897 }
898 *reinterpret_cast<double *>(new_data) = old_value_f;
899 break;
900 case SDNA_TYPE_INT64:
901 *reinterpret_cast<int64_t *>(new_data) = int64_t(old_value_i);
902 break;
903 case SDNA_TYPE_UINT64:
904 *reinterpret_cast<uint64_t *>(new_data) = old_value_i;
905 break;
906 case SDNA_TYPE_INT8:
907 *reinterpret_cast<int8_t *>(new_data) = int8_t(old_value_i);
908 break;
910 BLI_assert_msg(false, "Conversion to SDNA_TYPE_RAW_DATA is not supported");
911 break;
912 }
913
914 old_data += oldlen;
915 new_data += curlen;
916 }
917}
918
919static void cast_pointer_32_to_64(const int array_len,
920 const uint32_t *old_data,
921 uint64_t *new_data)
922{
923 for (int a = 0; a < array_len; a++) {
924 new_data[a] = old_data[a];
925 }
926}
927
928static void cast_pointer_64_to_32(const int array_len,
929 const uint64_t *old_data,
930 uint32_t *new_data)
931{
932 /* WARNING: 32-bit Blender trying to load file saved by 64-bit Blender,
933 * pointers may lose uniqueness on truncation! (Hopefully this won't
934 * happen unless/until we ever get to multi-gigabyte .blend files...) */
935 for (int a = 0; a < array_len; a++) {
936 new_data[a] = old_data[a] >> 3;
937 }
938}
939
943static bool elem_streq(const char *name, const char *oname)
944{
945 int a = 0;
946
947 while (true) {
948 if (name[a] != oname[a]) {
949 return false;
950 }
951 if (name[a] == '[' || oname[a] == '[') {
952 break;
953 }
954 if (name[a] == 0 || oname[a] == 0) {
955 break;
956 }
957 a++;
958 }
959 return true;
960}
961
972 /* Expand SDNA. */
973 const char **types,
974 const char **names,
975 /* Regular args. */
976 const char *type,
977 const char *name,
978 const SDNA_Struct *old)
979{
980 /* in old is the old struct */
981 for (int a = 0; a < old->members_num; a++) {
982 const SDNA_StructMember *member = &old->members[a];
983 const char *otype = types[member->type_index];
984 const char *oname = names[member->member_index];
985
986 if (elem_streq(name, oname)) { /* name equal */
987 return STREQ(type, otype); /* type equal */
988 }
989 }
990 return false;
991}
992
996static bool elem_exists_without_alias(const SDNA *sdna,
997 const char *type,
998 const char *name,
999 const SDNA_Struct *old)
1000{
1001 return elem_exists_impl(
1002 /* Expand SDNA. */
1003 sdna->types,
1004 sdna->members,
1005 /* Regular args. */
1006 type,
1007 name,
1008 old);
1009}
1010
1011static bool elem_exists_with_alias(const SDNA *sdna,
1012 const char *type,
1013 const char *name,
1014 const SDNA_Struct *old)
1015{
1016 return elem_exists_impl(
1017 /* Expand SDNA. */
1018 sdna->alias.types,
1019 sdna->alias.members,
1020 /* Regular args. */
1021 type,
1022 name,
1023 old);
1024}
1025
1026static int elem_offset_impl(const SDNA *sdna,
1027 const char **types,
1028 const char **names,
1029 const char *type,
1030 const char *name,
1031 const SDNA_Struct *old)
1032{
1033 /* Without array-part, so names can differ: return old `namenr` and type. */
1034
1035 /* in old is the old struct */
1036 int offset = 0;
1037 for (int a = 0; a < old->members_num; a++) {
1038 const SDNA_StructMember *member = &old->members[a];
1039 const char *otype = types[member->type_index];
1040 const char *oname = names[member->member_index];
1041 if (elem_streq(name, oname)) { /* name equal */
1042 if (STREQ(type, otype)) { /* type equal */
1043 return offset;
1044 }
1045 break; /* Fail below. */
1046 }
1047 offset += DNA_struct_member_size(sdna, member->type_index, member->member_index);
1048 }
1049 return -1;
1050}
1051
1067static int elem_offset_without_alias(const SDNA *sdna,
1068 const char *type,
1069 const char *name,
1070 const SDNA_Struct *old)
1071{
1072 return elem_offset_impl(sdna, sdna->types, sdna->members, type, name, old);
1073}
1074
1078static int elem_offset_with_alias(const SDNA *sdna,
1079 const char *type,
1080 const char *name,
1081 const SDNA_Struct *old)
1082{
1083 return elem_offset_impl(sdna, sdna->alias.types, sdna->alias.members, type, name, old);
1084}
1085
1086/* Each struct member belongs to one of the categories below. */
1092
1094 const SDNA_StructMember *member)
1095{
1096 const char *member_name = sdna->members[member->member_index];
1097 if (ispointer(member_name)) {
1099 }
1100 const char *member_type_name = sdna->types[member->type_index];
1101 if (DNA_struct_exists_without_alias(sdna, member_type_name)) {
1103 }
1105}
1106
1107static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member)
1108{
1109 const char *name = sdna->members[member->member_index];
1110 const int array_length = sdna->members_array_num[member->member_index];
1111 if (ispointer(name)) {
1112 return sdna->pointer_size * array_length;
1113 }
1114 const int type_size = sdna->types_size[member->type_index];
1115 return type_size * array_length;
1116}
1117
1118void DNA_struct_switch_endian(const SDNA *sdna, int struct_index, char *data)
1119{
1120 if (struct_index == -1) {
1121 return;
1122 }
1123
1124 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1125
1126 int offset_in_bytes = 0;
1127 for (int member_index = 0; member_index < struct_info->members_num; member_index++) {
1128 const SDNA_StructMember *member = &struct_info->members[member_index];
1129 const eStructMemberCategory member_category = get_struct_member_category(sdna, member);
1130 char *member_data = data + offset_in_bytes;
1131 const char *member_type_name = sdna->types[member->type_index];
1132 const int member_array_length = sdna->members_array_num[member->member_index];
1133
1134 switch (member_category) {
1136 const int substruct_size = sdna->types_size[member->type_index];
1137 const int substruct_index = DNA_struct_find_index_without_alias(sdna, member_type_name);
1138 BLI_assert(substruct_index != -1);
1139 for (int a = 0; a < member_array_length; a++) {
1140 DNA_struct_switch_endian(sdna, substruct_index, member_data + a * substruct_size);
1141 }
1142 break;
1143 }
1145 switch (member->type_index) {
1146 case SDNA_TYPE_SHORT:
1147 case SDNA_TYPE_USHORT: {
1148 BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length);
1149 break;
1150 }
1151 case SDNA_TYPE_INT:
1152 case SDNA_TYPE_FLOAT: {
1153 /* NOTE: intentionally ignore `long/ulong`, because these could be 4 or 8 bytes.
1154 * Fortunately, we only use these types for runtime variables and only once for a
1155 * struct type that is no longer used. */
1156 BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length);
1157 break;
1158 }
1159 case SDNA_TYPE_INT64:
1160 case SDNA_TYPE_UINT64:
1161 case SDNA_TYPE_DOUBLE: {
1162 BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length);
1163 break;
1164 }
1165 default: {
1166 break;
1167 }
1168 }
1169 break;
1170 }
1172 /* See `readfile.cc` (#uint32_from_uint64_ptr swap endian argument),
1173 * this is only done when reducing the size of a pointer from 4 to 8. */
1174 if (sizeof(void *) < 8) {
1175 if (sdna->pointer_size == 8) {
1176 BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length);
1177 }
1178 }
1179 break;
1180 }
1181 }
1182 offset_in_bytes += get_member_size_in_bytes(sdna, member);
1183 }
1184}
1185
1194
1197 union {
1198 struct {
1201 int size;
1203 struct {
1204 int old_offset;
1205 int new_offset;
1210 struct {
1211 int old_offset;
1212 int new_offset;
1213 int array_len;
1215 struct {
1216 int old_offset;
1217 int new_offset;
1218 int array_len;
1223};
1224
1233
1234static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1235 const int blocks,
1236 const int old_struct_index,
1237 const int new_struct_index,
1238 const char *old_blocks,
1239 char *new_blocks);
1240
1250static void reconstruct_struct(const DNA_ReconstructInfo *reconstruct_info,
1251 const int new_struct_index,
1252 const char *old_block,
1253 char *new_block)
1254{
1255 const ReconstructStep *steps = reconstruct_info->steps[new_struct_index];
1256 const int step_count = reconstruct_info->step_counts[new_struct_index];
1257
1258 /* Execute all preprocessed steps. */
1259 for (int a = 0; a < step_count; a++) {
1260 const ReconstructStep *step = &steps[a];
1261 switch (step->type) {
1263 memcpy(new_block + step->data.memcpy.new_offset,
1264 old_block + step->data.memcpy.old_offset,
1265 step->data.memcpy.size);
1266 break;
1268 cast_primitive_type(step->data.cast_primitive.old_type,
1269 step->data.cast_primitive.new_type,
1270 step->data.cast_primitive.array_len,
1271 old_block + step->data.cast_primitive.old_offset,
1272 new_block + step->data.cast_primitive.new_offset);
1273 break;
1275 cast_pointer_64_to_32(step->data.cast_pointer.array_len,
1276 (const uint64_t *)(old_block + step->data.cast_pointer.old_offset),
1277 (uint32_t *)(new_block + step->data.cast_pointer.new_offset));
1278 break;
1280 cast_pointer_32_to_64(step->data.cast_pointer.array_len,
1281 (const uint32_t *)(old_block + step->data.cast_pointer.old_offset),
1282 (uint64_t *)(new_block + step->data.cast_pointer.new_offset));
1283 break;
1285 reconstruct_structs(reconstruct_info,
1286 step->data.substruct.array_len,
1287 step->data.substruct.old_struct_index,
1288 step->data.substruct.new_struct_index,
1289 old_block + step->data.substruct.old_offset,
1290 new_block + step->data.substruct.new_offset);
1291 break;
1293 /* Do nothing, because the memory block are zeroed (from #MEM_callocN).
1294 *
1295 * Note that the struct could be initialized with the default struct,
1296 * however this complicates versioning, especially with flags, see: D4500. */
1297 break;
1298 }
1299 }
1300}
1301
1303static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1304 const int blocks,
1305 const int old_struct_index,
1306 const int new_struct_index,
1307 const char *old_blocks,
1308 char *new_blocks)
1309{
1310 const SDNA_Struct *old_struct = reconstruct_info->oldsdna->structs[old_struct_index];
1311 const SDNA_Struct *new_struct = reconstruct_info->newsdna->structs[new_struct_index];
1312
1313 const int old_block_size = reconstruct_info->oldsdna->types_size[old_struct->type_index];
1314 const int new_block_size = reconstruct_info->newsdna->types_size[new_struct->type_index];
1315
1316 for (int a = 0; a < blocks; a++) {
1317 const char *old_block = old_blocks + a * old_block_size;
1318 char *new_block = new_blocks + a * new_block_size;
1319 reconstruct_struct(reconstruct_info, new_struct_index, old_block, new_block);
1320 }
1321}
1322
1323void *DNA_struct_reconstruct(const DNA_ReconstructInfo *reconstruct_info,
1324 int old_struct_index,
1325 int blocks,
1326 const void *old_blocks,
1327 const char *alloc_name)
1328{
1329 const SDNA *oldsdna = reconstruct_info->oldsdna;
1330 const SDNA *newsdna = reconstruct_info->newsdna;
1331
1332 const SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
1333 const char *type_name = oldsdna->types[old_struct->type_index];
1334 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, type_name);
1335
1336 if (new_struct_index == -1) {
1337 return nullptr;
1338 }
1339
1340 const SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
1341 const int new_block_size = newsdna->types_size[new_struct->type_index];
1342
1343 const int alignment = DNA_struct_alignment(newsdna, new_struct_index);
1344 char *new_blocks = static_cast<char *>(
1345 MEM_calloc_arrayN_aligned(new_block_size, blocks, alignment, alloc_name));
1346 reconstruct_structs(reconstruct_info,
1347 blocks,
1348 old_struct_index,
1349 new_struct_index,
1350 static_cast<const char *>(old_blocks),
1351 new_blocks);
1352 return new_blocks;
1353}
1354
1357 const SDNA_Struct *struct_info,
1358 const char *name,
1359 int *r_offset)
1360{
1361 int offset = 0;
1362 for (int a = 0; a < struct_info->members_num; a++) {
1363 const SDNA_StructMember *member = &struct_info->members[a];
1364 const char *member_name = sdna->members[member->member_index];
1365 if (elem_streq(name, member_name)) {
1366 *r_offset = offset;
1367 return member;
1368 }
1369 offset += get_member_size_in_bytes(sdna, member);
1370 }
1371 return nullptr;
1372}
1373
1375static void init_reconstruct_step_for_member(const SDNA *oldsdna,
1376 const SDNA *newsdna,
1377 const char *compare_flags,
1378 const SDNA_Struct *old_struct,
1379 const SDNA_StructMember *new_member,
1380 const int new_member_offset,
1381 ReconstructStep *r_step)
1382{
1383
1384 /* Find the matching old member. */
1385 int old_member_offset;
1386 const char *new_name = newsdna->members[new_member->member_index];
1388 oldsdna, old_struct, new_name, &old_member_offset);
1389
1390 if (old_member == nullptr) {
1391 /* No matching member has been found in the old struct. */
1393 return;
1394 }
1395
1396 /* Determine the member category of the old an new members. */
1397 const eStructMemberCategory new_category = get_struct_member_category(newsdna, new_member);
1398 const eStructMemberCategory old_category = get_struct_member_category(oldsdna, old_member);
1399
1400 if (new_category != old_category) {
1401 /* Can only reconstruct the new member based on the old member, when the belong to the same
1402 * category. */
1404 return;
1405 }
1406
1407 const int new_array_length = newsdna->members_array_num[new_member->member_index];
1408 const int old_array_length = oldsdna->members_array_num[old_member->member_index];
1409 const int shared_array_length = std::min(new_array_length, old_array_length);
1410
1411 const char *new_type_name = newsdna->types[new_member->type_index];
1412 const char *old_type_name = oldsdna->types[old_member->type_index];
1413
1414 switch (new_category) {
1416 if (STREQ(new_type_name, old_type_name)) {
1417 const int old_struct_index = DNA_struct_find_index_without_alias(oldsdna, old_type_name);
1418 BLI_assert(old_struct_index != -1);
1419 enum eSDNA_StructCompare compare_flag = eSDNA_StructCompare(
1420 compare_flags[old_struct_index]);
1421 BLI_assert(compare_flag != SDNA_CMP_REMOVED);
1422 if (compare_flag == SDNA_CMP_EQUAL) {
1423 /* The old and new members are identical, just do a #memcpy. */
1424 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1425 r_step->data.memcpy.new_offset = new_member_offset;
1426 r_step->data.memcpy.old_offset = old_member_offset;
1427 r_step->data.memcpy.size = newsdna->types_size[new_member->type_index] *
1428 shared_array_length;
1429 }
1430 else {
1431 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, new_type_name);
1432 BLI_assert(new_struct_index != -1);
1433
1434 /* The old and new members are different, use recursion to reconstruct the
1435 * nested struct. */
1436 BLI_assert(compare_flag == SDNA_CMP_NOT_EQUAL);
1438 r_step->data.substruct.new_offset = new_member_offset;
1439 r_step->data.substruct.old_offset = old_member_offset;
1440 r_step->data.substruct.array_len = shared_array_length;
1441 r_step->data.substruct.new_struct_index = new_struct_index;
1442 r_step->data.substruct.old_struct_index = old_struct_index;
1443 }
1444 }
1445 else {
1446 /* Cannot match structs that have different names. */
1448 }
1449 break;
1450 }
1452 if (STREQ(new_type_name, old_type_name)) {
1453 /* Primitives with the same name cannot be different, so just do a #memcpy. */
1454 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1455 r_step->data.memcpy.new_offset = new_member_offset;
1456 r_step->data.memcpy.old_offset = old_member_offset;
1457 r_step->data.memcpy.size = newsdna->types_size[new_member->type_index] *
1458 shared_array_length;
1459 }
1460 else {
1461 /* The old and new primitive types are different, cast from the old to new type. */
1463 r_step->data.cast_primitive.array_len = shared_array_length;
1464 r_step->data.cast_primitive.new_offset = new_member_offset;
1465 r_step->data.cast_primitive.old_offset = old_member_offset;
1466 r_step->data.cast_primitive.new_type = eSDNA_Type(new_member->type_index);
1467 r_step->data.cast_primitive.old_type = eSDNA_Type(old_member->type_index);
1468 }
1469 break;
1470 }
1472 if (newsdna->pointer_size == oldsdna->pointer_size) {
1473 /* The pointer size is the same, so just do a #memcpy. */
1474 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1475 r_step->data.memcpy.new_offset = new_member_offset;
1476 r_step->data.memcpy.old_offset = old_member_offset;
1477 r_step->data.memcpy.size = newsdna->pointer_size * shared_array_length;
1478 }
1479 else if (newsdna->pointer_size == 8 && oldsdna->pointer_size == 4) {
1480 /* Need to convert from 32 bit to 64 bit pointers. */
1482 r_step->data.cast_pointer.new_offset = new_member_offset;
1483 r_step->data.cast_pointer.old_offset = old_member_offset;
1484 r_step->data.cast_pointer.array_len = shared_array_length;
1485 }
1486 else if (newsdna->pointer_size == 4 && oldsdna->pointer_size == 8) {
1487 /* Need to convert from 64 bit to 32 bit pointers. */
1489 r_step->data.cast_pointer.new_offset = new_member_offset;
1490 r_step->data.cast_pointer.old_offset = old_member_offset;
1491 r_step->data.cast_pointer.array_len = shared_array_length;
1492 }
1493 else {
1494 BLI_assert_msg(0, "invalid pointer size");
1496 }
1497 break;
1498 }
1499 }
1500}
1501
1503[[maybe_unused]] static void print_reconstruct_step(const ReconstructStep *step,
1504 const SDNA *oldsdna,
1505 const SDNA *newsdna)
1506{
1507 switch (step->type) {
1509 printf("initialize zero");
1510 break;
1511 }
1513 printf("memcpy, size: %d, old offset: %d, new offset: %d",
1514 step->data.memcpy.size,
1515 step->data.memcpy.old_offset,
1516 step->data.memcpy.new_offset);
1517 break;
1518 }
1520 printf(
1521 "cast element, old type: %d ('%s'), new type: %d ('%s'), old offset: %d, new offset: "
1522 "%d, length: %d",
1523 int(step->data.cast_primitive.old_type),
1524 oldsdna->types[step->data.cast_primitive.old_type],
1525 int(step->data.cast_primitive.new_type),
1526 newsdna->types[step->data.cast_primitive.new_type],
1527 step->data.cast_primitive.old_offset,
1528 step->data.cast_primitive.new_offset,
1529 step->data.cast_primitive.array_len);
1530 break;
1531 }
1533 printf("pointer to 32, old offset: %d, new offset: %d, length: %d",
1534 step->data.cast_pointer.old_offset,
1535 step->data.cast_pointer.new_offset,
1536 step->data.cast_pointer.array_len);
1537 break;
1538 }
1540 printf("pointer to 64, old offset: %d, new offset: %d, length: %d",
1541 step->data.cast_pointer.old_offset,
1542 step->data.cast_pointer.new_offset,
1543 step->data.cast_pointer.array_len);
1544 break;
1545 }
1547 printf(
1548 "substruct, old offset: %d, new offset: %d, new struct: %d ('%s', size per struct: %d), "
1549 "length: %d",
1550 step->data.substruct.old_offset,
1551 step->data.substruct.new_offset,
1552 step->data.substruct.new_struct_index,
1553 newsdna->types[newsdna->structs[step->data.substruct.new_struct_index]->type_index],
1554 newsdna->types_size[newsdna->structs[step->data.substruct.new_struct_index]->type_index],
1555 step->data.substruct.array_len);
1556 break;
1557 }
1558 }
1559}
1560
1566 const SDNA *newsdna,
1567 const char *compare_flags,
1568 const SDNA_Struct *old_struct,
1569 const SDNA_Struct *new_struct)
1570{
1572
1573 int new_member_offset = 0;
1574 for (int new_member_index = 0; new_member_index < new_struct->members_num; new_member_index++) {
1575 const SDNA_StructMember *new_member = &new_struct->members[new_member_index];
1577 newsdna,
1578 compare_flags,
1579 old_struct,
1580 new_member,
1581 new_member_offset,
1582 &steps[new_member_index]);
1583 new_member_offset += get_member_size_in_bytes(newsdna, new_member);
1584 }
1585
1586 return steps;
1587}
1588
1590static int compress_reconstruct_steps(ReconstructStep *steps, const int old_step_count)
1591{
1592 int new_step_count = 0;
1593 for (int a = 0; a < old_step_count; a++) {
1594 ReconstructStep *step = &steps[a];
1595 switch (step->type) {
1597 /* These steps are simply removed. */
1598 break;
1600 if (new_step_count > 0) {
1601 /* Try to merge this memcpy step with the previous one. */
1602 ReconstructStep *prev_step = &steps[new_step_count - 1];
1603 if (prev_step->type == RECONSTRUCT_STEP_MEMCPY) {
1604 /* Check if there are no bytes between the blocks to copy. */
1605 if (prev_step->data.memcpy.old_offset + prev_step->data.memcpy.size ==
1606 step->data.memcpy.old_offset &&
1607 prev_step->data.memcpy.new_offset + prev_step->data.memcpy.size ==
1608 step->data.memcpy.new_offset)
1609 {
1610 prev_step->data.memcpy.size += step->data.memcpy.size;
1611 break;
1612 }
1613 }
1614 }
1615 steps[new_step_count] = *step;
1616 new_step_count++;
1617 break;
1622 /* These steps are not changed at all for now. It should be possible to merge consecutive
1623 * steps of the same type, but it is not really worth it. */
1624 steps[new_step_count] = *step;
1625 new_step_count++;
1626 break;
1627 }
1628 }
1629 return new_step_count;
1630}
1631
1633 const SDNA *newsdna,
1634 const char *compare_flags)
1635{
1636 DNA_ReconstructInfo *reconstruct_info = MEM_callocN<DNA_ReconstructInfo>(__func__);
1637 reconstruct_info->oldsdna = oldsdna;
1638 reconstruct_info->newsdna = newsdna;
1639 reconstruct_info->compare_flags = compare_flags;
1640 reconstruct_info->step_counts = MEM_malloc_arrayN<int>(size_t(newsdna->structs_num), __func__);
1641 reconstruct_info->steps = MEM_malloc_arrayN<ReconstructStep *>(size_t(newsdna->structs_num),
1642 __func__);
1643
1644 /* Generate reconstruct steps for all structs. */
1645 for (int new_struct_index = 0; new_struct_index < newsdna->structs_num; new_struct_index++) {
1646 const SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
1647 const char *new_struct_name = newsdna->types[new_struct->type_index];
1648 const int old_struct_index = DNA_struct_find_index_without_alias(oldsdna, new_struct_name);
1649 if (old_struct_index < 0) {
1650 reconstruct_info->steps[new_struct_index] = nullptr;
1651 reconstruct_info->step_counts[new_struct_index] = 0;
1652 continue;
1653 }
1654 const SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
1656 oldsdna, newsdna, compare_flags, old_struct, new_struct);
1657
1658 /* Comment the line below to skip the compression for debugging purposes. */
1659 const int steps_len = compress_reconstruct_steps(steps, new_struct->members_num);
1660
1661 reconstruct_info->steps[new_struct_index] = steps;
1662 reconstruct_info->step_counts[new_struct_index] = steps_len;
1663
1664/* This is useful when debugging the reconstruct steps. */
1665#if 0
1666 printf("%s: \n", new_struct_name);
1667 for (int a = 0; a < steps_len; a++) {
1668 printf(" ");
1669 print_reconstruct_step(&steps[a], oldsdna, newsdna);
1670 printf("\n");
1671 }
1672#endif
1673 }
1674
1675 return reconstruct_info;
1676}
1677
1679{
1680 for (int new_struct_index = 0; new_struct_index < reconstruct_info->newsdna->structs_num;
1681 new_struct_index++)
1682 {
1683 if (reconstruct_info->steps[new_struct_index] != nullptr) {
1684 MEM_freeN(reconstruct_info->steps[new_struct_index]);
1685 }
1686 }
1687 MEM_freeN(reconstruct_info->steps);
1688 MEM_freeN(reconstruct_info->step_counts);
1689 MEM_freeN(reconstruct_info);
1690}
1691
1693 const char *stype,
1694 const char *vartype,
1695 const char *name)
1696{
1697 const int struct_index = DNA_struct_find_index_without_alias(sdna, stype);
1698 BLI_assert(struct_index != -1);
1699 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1700 return elem_offset_without_alias(sdna, vartype, name, struct_info);
1701}
1702
1704 const char *stype,
1705 const char *vartype,
1706 const char *name)
1707{
1708 const int struct_index = DNA_struct_find_with_alias(sdna, stype);
1709 BLI_assert(struct_index != -1);
1710 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1711 return elem_offset_with_alias(sdna, vartype, name, struct_info);
1712}
1713
1714bool DNA_struct_exists_without_alias(const SDNA *sdna, const char *stype)
1715{
1716 return DNA_struct_find_index_without_alias(sdna, stype) != -1;
1717}
1718
1720 const char *stype,
1721 const char *vartype,
1722 const char *name)
1723{
1724 const int struct_index = DNA_struct_find_index_without_alias(sdna, stype);
1725
1726 if (struct_index != -1) {
1727 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1728 const bool found = elem_exists_without_alias(sdna, vartype, name, struct_info);
1729
1730 if (found) {
1731 return true;
1732 }
1733 }
1734 return false;
1735}
1736
1738 const char *stype,
1739 const char *vartype,
1740 const char *name)
1741{
1742 const int SDNAnr = DNA_struct_find_with_alias(sdna, stype);
1743
1744 if (SDNAnr != -1) {
1745 const SDNA_Struct *const spo = sdna->structs[SDNAnr];
1746 const bool found = elem_exists_with_alias(sdna, vartype, name, spo);
1747
1748 if (found) {
1749 return true;
1750 }
1751 }
1752 return false;
1753}
1754
1756{
1757 /* should contain all enum types */
1758 switch (elem_nr) {
1759 case SDNA_TYPE_CHAR:
1760 case SDNA_TYPE_UCHAR:
1761 case SDNA_TYPE_INT8:
1762 return 1;
1763 case SDNA_TYPE_SHORT:
1764 case SDNA_TYPE_USHORT:
1765 return 2;
1766 case SDNA_TYPE_INT:
1767 case SDNA_TYPE_FLOAT:
1768 return 4;
1769 case SDNA_TYPE_DOUBLE:
1770 case SDNA_TYPE_INT64:
1771 case SDNA_TYPE_UINT64:
1772 return 8;
1773 case SDNA_TYPE_RAW_DATA:
1774 BLI_assert_msg(false, "Operations on the size of SDNA_TYPE_RAW_DATA is not supported");
1775 return 0;
1776 }
1777
1778 /* weak */
1779 return 8;
1780}
1781
1782int DNA_struct_alignment(const SDNA *sdna, const int struct_index)
1783{
1784 return sdna->types_alignment[struct_index];
1785}
1786
1787const char *DNA_struct_identifier(SDNA *sdna, const int struct_index)
1788{
1790 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1791 return sdna->alias.types[struct_info->type_index];
1792}
1793
1794/* -------------------------------------------------------------------- */
1797
1798static bool DNA_sdna_patch_struct(SDNA *sdna, const int struct_index, const char *new_type_name)
1799{
1801 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1802#ifdef WITH_DNA_GHASH
1804 sdna->types_to_structs_map, (void *)sdna->types[struct_info->type_index], nullptr, nullptr);
1806 sdna->types_to_structs_map, (void *)new_type_name, POINTER_FROM_INT(struct_index));
1807#endif
1808 sdna->types[struct_info->type_index] = new_type_name;
1809 return true;
1810}
1812 const char *old_type_name,
1813 const char *new_type_name)
1814{
1815 const int struct_index = DNA_struct_find_index_without_alias(sdna, old_type_name);
1816 if (struct_index != -1) {
1817 return DNA_sdna_patch_struct(sdna, struct_index, new_type_name);
1818 }
1819 return false;
1820}
1821
1822/* Make public if called often with same struct (avoid duplicate lookups). */
1824 const int struct_index,
1825 const char *old_member_name,
1826 const char *new_member_name)
1827{
1828 /* These names aren't handled here (it's not used).
1829 * Ensure they are never used or we get out of sync arrays. */
1830 BLI_assert(sdna->alias.members == nullptr);
1831 const int old_member_name_len = strlen(old_member_name);
1832 const int new_member_name_len = strlen(new_member_name);
1833 BLI_assert(new_member_name != nullptr);
1834 SDNA_Struct *struct_info = sdna->structs[struct_index];
1835 for (int struct_member_index = struct_info->members_num; struct_member_index > 0;
1836 struct_member_index--)
1837 {
1838 SDNA_StructMember *member_info = &struct_info->members[struct_member_index];
1839 const char *old_member_name_full = sdna->members[member_info->member_index];
1840 /* Start & end offsets in #old_member_full. */
1841 uint old_member_name_full_offset_start;
1842 if (DNA_member_id_match(old_member_name,
1843 old_member_name_len,
1844 old_member_name_full,
1845 &old_member_name_full_offset_start))
1846 {
1847 if (sdna->mem_arena == nullptr) {
1849 }
1850 const char *new_member_name_full = DNA_member_id_rename(sdna->mem_arena,
1851 old_member_name,
1852 old_member_name_len,
1853 new_member_name,
1854 new_member_name_len,
1855 old_member_name_full,
1856 strlen(old_member_name_full),
1857 old_member_name_full_offset_start);
1858
1859 if (sdna->members_num == sdna->members_num_alloc) {
1860 sdna->members_num_alloc += 64;
1861 sdna->members = static_cast<const char **>(MEM_recallocN(
1862 (void *)sdna->members, sizeof(*sdna->members) * sdna->members_num_alloc));
1863 sdna->members_array_num = static_cast<short int *>(
1864 MEM_recallocN((void *)sdna->members_array_num,
1865 sizeof(*sdna->members_array_num) * sdna->members_num_alloc));
1866 }
1867 const short old_member_index = member_info->member_index;
1868 member_info->member_index = sdna->members_num++;
1869 sdna->members[member_info->member_index] = new_member_name_full;
1870 sdna->members_array_num[member_info->member_index] =
1871 sdna->members_array_num[old_member_index];
1872
1873 return true;
1874 }
1875 }
1876 return false;
1877}
1879 const char *type_name,
1880 const char *old_member_name,
1881 const char *new_member_name)
1882{
1883 const int struct_index = DNA_struct_find_index_without_alias(sdna, type_name);
1884 if (struct_index != -1) {
1885 return DNA_sdna_patch_struct_member(sdna, struct_index, old_member_name, new_member_name);
1886 }
1887 return false;
1888}
1889
1891
1892/* -------------------------------------------------------------------- */
1897
1904static void sdna_expand_names(SDNA *sdna)
1905{
1906 int names_expand_len = 0;
1907 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1908 const SDNA_Struct *struct_old = sdna->structs[struct_index];
1909 names_expand_len += struct_old->members_num;
1910 }
1911 const char **names_expand = MEM_malloc_arrayN<const char *>(size_t(names_expand_len), __func__);
1912 short *names_array_len_expand = MEM_malloc_arrayN<short>(size_t(names_expand_len), __func__);
1913
1914 int names_expand_index = 0;
1915 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1916 /* We can't edit this memory 'sdna->structs' points to (read-only `datatoc` file). */
1917 const SDNA_Struct *struct_old = sdna->structs[struct_index];
1918
1919 const int array_size = sizeof(short) * 2 + sizeof(SDNA_StructMember) * struct_old->members_num;
1920 SDNA_Struct *struct_new = static_cast<SDNA_Struct *>(
1921 BLI_memarena_alloc(sdna->mem_arena, array_size));
1922 memcpy(struct_new, struct_old, array_size);
1923 sdna->structs[struct_index] = struct_new;
1924
1925 for (int i = 0; i < struct_old->members_num; i++) {
1926 const SDNA_StructMember *member_old = &struct_old->members[i];
1927 SDNA_StructMember *member_new = &struct_new->members[i];
1928
1929 names_expand[names_expand_index] = sdna->members[member_old->member_index];
1930 names_array_len_expand[names_expand_index] =
1931 sdna->members_array_num[member_old->member_index];
1932
1933 BLI_assert(names_expand_index < SHRT_MAX);
1934 member_new->member_index = names_expand_index;
1935 names_expand_index++;
1936 }
1937 }
1938 MEM_freeN(sdna->members);
1939 sdna->members = names_expand;
1940
1942 sdna->members_array_num = names_array_len_expand;
1943
1944 sdna->members_num = names_expand_len;
1945}
1946
1948 GHash *elem_map_alias_from_static,
1949 const char *struct_name_static,
1950 const char *elem_static_full)
1951{
1952 const int elem_static_full_len = strlen(elem_static_full);
1953 char *elem_static = static_cast<char *>(alloca(elem_static_full_len + 1));
1954 const int elem_static_len = DNA_member_id_strip_copy(elem_static, elem_static_full);
1955 const char *str_pair[2] = {struct_name_static, elem_static};
1956 const char *elem_alias = static_cast<const char *>(
1957 BLI_ghash_lookup(elem_map_alias_from_static, str_pair));
1958 if (elem_alias) {
1959 return DNA_member_id_rename(sdna->mem_arena,
1960 elem_static,
1961 elem_static_len,
1962 elem_alias,
1963 strlen(elem_alias),
1964 elem_static_full,
1965 elem_static_full_len,
1966 DNA_member_id_offset_start(elem_static_full));
1967 }
1968 return nullptr;
1969}
1970
1972{
1973 if (sdna->alias.members && sdna->alias.types) {
1974 return;
1975 }
1976
1977 /* We may want this to be optional later. */
1978 const bool use_legacy_hack = true;
1979
1980 if (sdna->mem_arena == nullptr) {
1982 }
1983
1986
1989
1990 if (sdna->alias.types == nullptr) {
1991 sdna->alias.types = MEM_malloc_arrayN<const char *>(size_t(sdna->types_num), __func__);
1992 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
1993 const char *type_name_static = sdna->types[type_index];
1994
1995 if (use_legacy_hack) {
1996 type_name_static = DNA_struct_rename_legacy_hack_alias_from_static(type_name_static);
1997 }
1998
1999 sdna->alias.types[type_index] = static_cast<const char *>(BLI_ghash_lookup_default(
2000 type_map_alias_from_static, type_name_static, (void *)type_name_static));
2001 }
2002 }
2003
2004 if (sdna->alias.members == nullptr) {
2005 sdna_expand_names(sdna);
2006 sdna->alias.members = MEM_malloc_arrayN<const char *>(size_t(sdna->members_num), __func__);
2007 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
2008 const SDNA_Struct *struct_info = sdna->structs[struct_index];
2009 const char *struct_name_static = sdna->types[struct_info->type_index];
2010
2011 if (use_legacy_hack) {
2012 struct_name_static = DNA_struct_rename_legacy_hack_alias_from_static(struct_name_static);
2013 }
2014
2015 for (int a = 0; a < struct_info->members_num; a++) {
2016 const SDNA_StructMember *member = &struct_info->members[a];
2017 const char *member_alias_full = dna_sdna_alias_from_static_elem_full(
2018 sdna,
2020 struct_name_static,
2021 sdna->members[member->member_index]);
2022 if (member_alias_full != nullptr) {
2023 sdna->alias.members[member->member_index] = member_alias_full;
2024 }
2025 else {
2026 sdna->alias.members[member->member_index] = sdna->members[member->member_index];
2027 }
2028 }
2029 }
2030 }
2031 BLI_ghash_free(type_map_alias_from_static, nullptr, nullptr);
2033}
2034
2036{
2037 if (sdna->alias.types_to_structs_map) {
2038 return;
2039 }
2040
2042#ifdef WITH_DNA_GHASH
2043 /* create a ghash lookup to speed up */
2044 GHash *type_to_struct_index_map = BLI_ghash_str_new_ex(__func__, sdna->structs_num);
2045 for (intptr_t struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
2046 const SDNA_Struct *struct_info = sdna->structs[struct_index];
2047 BLI_ghash_insert(type_to_struct_index_map,
2048 (void *)sdna->alias.types[struct_info->type_index],
2049 POINTER_FROM_INT(struct_index));
2050 }
2051 sdna->alias.types_to_structs_map = type_to_struct_index_map;
2052#else
2053 UNUSED_VARS(sdna);
2054#endif
2055}
2056
2058
2059/* -------------------------------------------------------------------- */
2063
2064namespace blender::dna {
2065
2066static void print_struct_array_recursive(const SDNA &sdna,
2067 const SDNA_Struct &sdna_struct,
2068 const void *initial_data,
2069 const int64_t element_num,
2070 const int indent,
2071 fmt::appender &dst);
2072static void print_single_struct_recursive(const SDNA &sdna,
2073 const SDNA_Struct &sdna_struct,
2074 const void *initial_data,
2075 const int indent,
2076 fmt::appender &dst);
2077
2081static bool char_array_startswith_simple_name(const char *data, const int array_len)
2082{
2083 const int string_length = strnlen(data, array_len);
2084 if (string_length == array_len) {
2085 return false;
2086 }
2087 for (const int i : IndexRange(string_length)) {
2088 const uchar c = data[i];
2089 /* This is only a very simple check and does not cover more complex cases with multi-byte UTF8
2090 * characters. It's only a heuristic anyway, making a wrong decision here just means that the
2091 * data will be printed differently. */
2092 if (!std::isprint(c)) {
2093 return false;
2094 }
2095 }
2096 return true;
2097}
2098
2099static void print_struct_array_recursive(const SDNA &sdna,
2100 const SDNA_Struct &sdna_struct,
2101 const void *data,
2102 const int64_t element_num,
2103 const int indent,
2104 fmt::appender &dst)
2105{
2106 if (element_num == 1) {
2107 print_single_struct_recursive(sdna, sdna_struct, data, indent, dst);
2108 return;
2109 }
2110
2111 const char *struct_name = sdna.types[sdna_struct.type_index];
2112 const int64_t struct_size = sdna.types_size[sdna_struct.type_index];
2113 for (const int64_t i : IndexRange(element_num)) {
2114 const void *element_data = POINTER_OFFSET(data, i * struct_size);
2115 fmt::format_to(dst, "{:{}}{}: <{}>\n", "", indent, i, struct_name);
2116 print_single_struct_recursive(sdna, sdna_struct, element_data, indent + 2, dst);
2117 }
2118}
2119
2120static void print_single_struct_recursive(const SDNA &sdna,
2121 const SDNA_Struct &sdna_struct,
2122 const void *initial_data,
2123 const int indent,
2124 fmt::appender &dst)
2125{
2126 using namespace blender;
2127 const void *data = initial_data;
2128
2129 for (const int member_i : IndexRange(sdna_struct.members_num)) {
2130 const SDNA_StructMember &member = sdna_struct.members[member_i];
2131 const char *member_type_name = sdna.types[member.type_index];
2132 const char *member_name = sdna.members[member.member_index];
2133 const eStructMemberCategory member_category = get_struct_member_category(&sdna, &member);
2134 const int member_array_len = sdna.members_array_num[member.member_index];
2135
2136 fmt::format_to(dst, "{:{}}{} {}:", "", indent, member_type_name, member_name);
2137
2138 if (member_category == STRUCT_MEMBER_CATEGORY_PRIMITIVE &&
2139 member.type_index == SDNA_TYPE_CHAR && member_array_len > 1)
2140 {
2141 const char *str_data = static_cast<const char *>(data);
2142 fmt::format_to(dst, " ");
2143 if (char_array_startswith_simple_name(str_data, member_array_len)) {
2144 fmt::format_to(dst, "'{}'", str_data);
2145 }
2146 else {
2147 for (const int i : IndexRange(member_array_len)) {
2148 fmt::format_to(dst, "{} ", int(str_data[i]));
2149 }
2150 }
2151 fmt::format_to(dst, "\n");
2152 }
2153 else {
2154 switch (member_category) {
2156 fmt::format_to(dst, "\n");
2157 const int substruct_i = DNA_struct_find_index_without_alias(&sdna, member_type_name);
2158 const SDNA_Struct &sub_sdna_struct = *sdna.structs[substruct_i];
2160 sdna, sub_sdna_struct, data, member_array_len, indent + 2, dst);
2161 break;
2162 }
2164 fmt::format_to(dst, " ");
2165 const int type_size = sdna.types_size[member.type_index];
2166 const eSDNA_Type type = eSDNA_Type(member.type_index);
2167 for ([[maybe_unused]] const int elem_i : IndexRange(member_array_len)) {
2168 const void *current_data = POINTER_OFFSET(data, elem_i * type_size);
2169 switch (type) {
2170 case SDNA_TYPE_CHAR: {
2171 const char value = *reinterpret_cast<const char *>(current_data);
2172 fmt::format_to(dst, "{}", int(value));
2173 break;
2174 }
2175 case SDNA_TYPE_UCHAR: {
2176 const uchar value = *reinterpret_cast<const uchar *>(current_data);
2177 fmt::format_to(dst, "{}", int(value));
2178 break;
2179 }
2180 case SDNA_TYPE_INT8: {
2181 fmt::format_to(dst, "{}", *reinterpret_cast<const int8_t *>(current_data));
2182 break;
2183 }
2184 case SDNA_TYPE_SHORT: {
2185 fmt::format_to(dst, "{}", *reinterpret_cast<const short *>(current_data));
2186 break;
2187 }
2188 case SDNA_TYPE_USHORT: {
2189 fmt::format_to(dst, "{}", *reinterpret_cast<const ushort *>(current_data));
2190 break;
2191 }
2192 case SDNA_TYPE_INT: {
2193 fmt::format_to(dst, "{}", *reinterpret_cast<const int *>(current_data));
2194 break;
2195 }
2196 case SDNA_TYPE_FLOAT: {
2197 fmt::format_to(dst, "{}", *reinterpret_cast<const float *>(current_data));
2198 break;
2199 }
2200 case SDNA_TYPE_DOUBLE: {
2201 fmt::format_to(dst, "{}", *reinterpret_cast<const double *>(current_data));
2202 break;
2203 }
2204 case SDNA_TYPE_INT64: {
2205 fmt::format_to(dst, "{}", *reinterpret_cast<const int64_t *>(current_data));
2206 break;
2207 }
2208 case SDNA_TYPE_UINT64: {
2209 fmt::format_to(dst, "{}", *reinterpret_cast<const uint64_t *>(current_data));
2210 break;
2211 }
2212 case SDNA_TYPE_RAW_DATA: {
2214 break;
2215 }
2216 }
2217 fmt::format_to(dst, " ");
2218 }
2219 fmt::format_to(dst, "\n");
2220 break;
2221 }
2223 for ([[maybe_unused]] const int elem_i : IndexRange(member_array_len)) {
2224 const void *current_data = POINTER_OFFSET(data, sdna.pointer_size * elem_i);
2225 fmt::format_to(dst, " {}", *reinterpret_cast<const void *const *>(current_data));
2226 }
2227 fmt::format_to(dst, "\n");
2228 break;
2229 }
2230 }
2231 }
2232 const int member_size = get_member_size_in_bytes(&sdna, &member);
2233 data = POINTER_OFFSET(data, member_size);
2234 }
2235}
2236
2238 const int struct_id,
2239 const void *initial_data,
2240 const void *address,
2241 const int64_t element_num,
2242 std::ostream &stream)
2243{
2244 const SDNA_Struct &sdna_struct = *sdna.structs[struct_id];
2245
2246 fmt::memory_buffer buf;
2247 fmt::appender dst{buf};
2248
2249 const char *struct_name = sdna.types[sdna_struct.type_index];
2250 fmt::format_to(dst, "<{}> {}x at {}\n", struct_name, element_num, address);
2251
2252 print_struct_array_recursive(sdna, sdna_struct, initial_data, element_num, 2, dst);
2253 stream << fmt::to_string(buf);
2254}
2255
2256void print_struct_by_id(const int struct_id, const void *data)
2257{
2258 const SDNA &sdna = *DNA_sdna_current_get();
2259 print_structs_at_address(sdna, struct_id, data, data, 1, std::cout);
2260}
2261
2262} // namespace blender::dna
2263
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define BLI_INLINE
BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_NONNULL(1)
void BLI_endian_switch_int32_array(int *val, int size) ATTR_NONNULL(1)
void BLI_endian_switch_uint64_array(uint64_t *val, int size) ATTR_NONNULL(1)
void BLI_endian_switch_int64_array(int64_t *val, int size) ATTR_NONNULL(1)
void BLI_endian_switch_int16_array(short *val, int size) ATTR_NONNULL(1)
BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_NONNULL(1)
void * BLI_ghash_lookup_default(const GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:738
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:745
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:787
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
unsigned char uchar
unsigned int uint
unsigned short ushort
#define UNUSED_VARS(...)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
blenloader genfile private function prototypes
#define SDNA_TYPE_VOID
Definition DNA_genfile.h:44
eSDNA_Type
Definition DNA_genfile.h:32
@ SDNA_TYPE_CHAR
Definition DNA_genfile.h:33
@ SDNA_TYPE_RAW_DATA
Definition DNA_genfile.h:54
@ SDNA_TYPE_INT
Definition DNA_genfile.h:37
@ SDNA_TYPE_UINT64
Definition DNA_genfile.h:46
@ SDNA_TYPE_DOUBLE
Definition DNA_genfile.h:41
@ SDNA_TYPE_SHORT
Definition DNA_genfile.h:35
@ SDNA_TYPE_UCHAR
Definition DNA_genfile.h:34
@ SDNA_TYPE_INT8
Definition DNA_genfile.h:47
@ SDNA_TYPE_INT64
Definition DNA_genfile.h:45
@ SDNA_TYPE_FLOAT
Definition DNA_genfile.h:40
@ SDNA_TYPE_USHORT
Definition DNA_genfile.h:36
const struct SDNA * DNA_sdna_current_get(void)
const unsigned char DNAstr[]
const int DNAlen
int DNA_struct_find_index_without_alias(const struct SDNA *sdna, const char *str)
eSDNA_StructCompare
Definition DNA_genfile.h:60
@ SDNA_CMP_EQUAL
Definition DNA_genfile.h:66
@ SDNA_CMP_REMOVED
Definition DNA_genfile.h:63
@ SDNA_CMP_UNKNOWN
Definition DNA_genfile.h:71
@ SDNA_CMP_NOT_EQUAL
Definition DNA_genfile.h:69
struct SDNA SDNA
#define SDNA_RAW_DATA_STRUCT_INDEX
struct SDNA_Struct SDNA_Struct
Read Guarded memory(de)allocation.
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
bool add(const Key &key)
Definition BLI_set.hh:248
bool DNA_struct_member_exists_with_alias(const SDNA *sdna, const char *stype, const char *vartype, const char *name)
static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error_message)
static void print_reconstruct_step(const ReconstructStep *step, const SDNA *oldsdna, const SDNA *newsdna)
static void reconstruct_struct(const DNA_ReconstructInfo *reconstruct_info, const int new_struct_index, const char *old_block, char *new_block)
static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info, const int blocks, const int old_struct_index, const int new_struct_index, const char *old_blocks, char *new_blocks)
int DNA_struct_find_index_without_alias_ex(const SDNA *sdna, const char *str, uint *struct_index_last)
const char * DNA_struct_identifier(SDNA *sdna, const int struct_index)
void DNA_sdna_current_free()
int DNA_struct_find_with_alias(const SDNA *sdna, const char *str)
SDNA * DNA_sdna_from_data(const void *data, const int data_len, bool do_endian_swap, bool data_alloc, const bool do_alias, const char **r_error_message)
DNA_ReconstructInfo * DNA_reconstruct_info_create(const SDNA *oldsdna, const SDNA *newsdna, const char *compare_flags)
eReconstructStepType
@ RECONSTRUCT_STEP_CAST_POINTER_TO_32
@ RECONSTRUCT_STEP_CAST_POINTER_TO_64
@ RECONSTRUCT_STEP_INIT_ZERO
@ RECONSTRUCT_STEP_SUBSTRUCT
@ RECONSTRUCT_STEP_CAST_PRIMITIVE
@ RECONSTRUCT_STEP_MEMCPY
int DNA_elem_type_size(const eSDNA_Type elem_nr)
static bool ispointer(const char *name)
static bool DNA_sdna_patch_struct_member(SDNA *sdna, const int struct_index, const char *old_member_name, const char *new_member_name)
int DNA_struct_member_size(const SDNA *sdna, short type, short member_index)
static bool elem_exists_impl(const char **types, const char **names, const char *type, const char *name, const SDNA_Struct *old)
static bool DNA_sdna_patch_struct(SDNA *sdna, const int struct_index, const char *new_type_name)
static int elem_offset_with_alias(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
static void cast_primitive_type(const eSDNA_Type old_type, const eSDNA_Type new_type, const int array_len, const char *old_data, char *new_data)
BLI_INLINE const char * pad_up_4(const char *ptr)
bool DNA_struct_exists_without_alias(const SDNA *sdna, const char *stype)
static void 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)
static void cast_pointer_64_to_32(const int array_len, const uint64_t *old_data, uint32_t *new_data)
void DNA_struct_switch_endian(const SDNA *sdna, int struct_index, char *data)
static void sdna_expand_names(SDNA *sdna)
static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member)
static int dna_struct_find_index_ex_impl(const char **types, const int, SDNA_Struct **const structs, const int structs_num, const char *str, uint *struct_index_last)
int DNA_struct_alignment(const SDNA *sdna, const int struct_index)
const SDNA * DNA_sdna_current_get()
static const char * 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)
static bool elem_exists_without_alias(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
#define MAKE_ID(a, b, c, d)
int DNA_struct_size(const SDNA *sdna, int struct_index)
static eStructMemberCategory get_struct_member_category(const SDNA *sdna, const SDNA_StructMember *member)
static bool elem_exists_with_alias(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
static void set_compare_flags_for_struct(const SDNA *oldsdna, const SDNA *newsdna, char *compare_flags, const int old_struct_index)
void DNA_reconstruct_info_free(DNA_ReconstructInfo *reconstruct_info)
int DNA_struct_member_offset_by_name_with_alias(const SDNA *sdna, const char *stype, const char *vartype, const char *name)
static const SDNA_StructMember * find_member_with_matching_name(const SDNA *sdna, const SDNA_Struct *struct_info, const char *name, int *r_offset)
static ReconstructStep * 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)
const char * DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
static int elem_offset_without_alias(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
void DNA_sdna_alias_data_ensure(SDNA *sdna)
static int elem_offset_impl(const SDNA *sdna, const char **types, const char **names, const char *type, const char *name, const SDNA_Struct *old)
eStructMemberCategory
@ STRUCT_MEMBER_CATEGORY_STRUCT
@ STRUCT_MEMBER_CATEGORY_POINTER
@ STRUCT_MEMBER_CATEGORY_PRIMITIVE
static void cast_pointer_32_to_64(const int array_len, const uint32_t *old_data, uint64_t *new_data)
bool DNA_sdna_patch_struct_member_by_name(SDNA *sdna, const char *type_name, const char *old_member_name, const char *new_member_name)
void DNA_sdna_free(SDNA *sdna)
static bool elem_streq(const char *name, const char *oname)
void * DNA_struct_reconstruct(const DNA_ReconstructInfo *reconstruct_info, int old_struct_index, int blocks, const void *old_blocks, const char *alloc_name)
bool DNA_struct_exists_with_alias(const SDNA *sdna, const char *str)
void DNA_sdna_current_init()
void DNA_sdna_alias_data_ensure_structs_map(SDNA *sdna)
static SDNA * g_sdna
int DNA_struct_find_index_with_alias_ex(const SDNA *sdna, const char *str, uint *struct_index_last)
int DNA_struct_member_offset_by_name_without_alias(const SDNA *sdna, const char *stype, const char *vartype, const char *name)
bool DNA_struct_member_exists_without_alias(const SDNA *sdna, const char *stype, const char *vartype, const char *name)
static int compress_reconstruct_steps(ReconstructStep *steps, const int old_step_count)
int DNA_struct_find_index_without_alias(const SDNA *sdna, const char *str)
bool DNA_sdna_patch_struct_by_name(SDNA *sdna, const char *old_type_name, const char *new_type_name)
const char * DNA_struct_rename_legacy_hack_static_from_alias(const char *name)
Definition dna_utils.cc:292
const char * DNA_struct_rename_legacy_hack_alias_from_static(const char *name)
Definition dna_utils.cc:308
int DNA_member_array_num(const char *str)
Definition dna_utils.cc:29
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
uint DNA_member_id_strip_copy(char *member_id_dst, const char *member_full_src)
Definition dna_utils.cc:96
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
@ DNA_RENAME_ALIAS_FROM_STATIC
Definition dna_utils.h:91
void DNA_alias_maps(enum eDNA_RenameDir version_dir, struct GHash **r_type_map, struct GHash **r_member_map)
#define str(s)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define printf(...)
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
#define UINT_MAX
Definition hash_md5.cc:44
static int types_num
Definition makesdna.cc:66
GHash * type_map_alias_from_static
Definition makesdna.cc:92
GHash * member_map_alias_from_static
Definition makesdna.cc:94
static char ** types
Definition makesdna.cc:71
static short ** structs
Definition makesdna.cc:88
static int structs_num
Definition makesdna.cc:67
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void *(* MEM_calloc_arrayN_aligned)(size_t len, size_t size, size_t alignment, const char *str)
Definition mallocn.cc:59
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void print_struct_array_recursive(const SDNA &sdna, const SDNA_Struct &sdna_struct, const void *initial_data, const int64_t element_num, const int indent, fmt::appender &dst)
static bool char_array_startswith_simple_name(const char *data, const int array_len)
static void print_single_struct_recursive(const SDNA &sdna, const SDNA_Struct &sdna_struct, const void *initial_data, const int indent, fmt::appender &dst)
void print_struct_by_id(int struct_id, const void *data)
void print_structs_at_address(const SDNA &sdna, int struct_id, const void *data, const void *address, int64_t element_num, std::ostream &stream)
MatBase< float, 4, 4 > float4x4
static const int steps
ReconstructStep ** steps
const char * compare_flags
eSDNA_Type old_type
eReconstructStepType type
eSDNA_Type new_type
struct ReconstructStep::@360237214336100004034032212103057025256052121062::@012052277273060354130114334214130373275075175334 cast_primitive
struct ReconstructStep::@360237214336100004034032212103057025256052121062::@205043300057004054232034152026016343025207167360 memcpy
union ReconstructStep::@360237214336100004034032212103057025256052121062 data
struct ReconstructStep::@360237214336100004034032212103057025256052121062::@234133277165134170167230172065207225160372374031 substruct
struct ReconstructStep::@360237214336100004034032212103057025256052121062::@000363114227370211030126075012301156331273261257 cast_pointer
SDNA_StructMember members[]
struct GHash * types_to_structs_map
const char ** members
int types_num
int structs_num
struct SDNA::@004326156331245255142220052114124163207305010377 alias
short * types_size
SDNA_Struct ** structs
int * types_alignment
struct MemArena * mem_arena
int members_num
int members_num_alloc
const char ** types
int pointer_size
const char * data
bool data_alloc
short * members_array_num
int data_size
i
Definition text_draw.cc:230
uint len
PointerRNA * ptr
Definition wm_files.cc:4227