Blender V5.0
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_ghash.h"
27#include "BLI_index_range.hh"
29#include "BLI_memarena.h"
30#include "BLI_set.hh"
31#include "BLI_utildefines.h"
32
33#include "DNA_genfile.h"
34#include "DNA_print.hh"
35#include "DNA_sdna_pointers.hh"
36#include "DNA_sdna_types.h" /* for SDNA ;-) */
37
118
119/* NOTE: this is endianness-sensitive. */
120/* Little Endian */
121#define MAKE_ID(a, b, c, d) (int(d) << 24 | int(c) << 16 | (b) << 8 | (a))
122
123/* ************************* DIV ********************** */
124
126{
127 if (sdna->data_alloc) {
128 MEM_freeN(sdna->data);
129 }
130
131 MEM_SAFE_FREE(sdna->members);
133 MEM_SAFE_FREE(sdna->types);
134 MEM_SAFE_FREE(sdna->structs);
136
137#ifdef WITH_DNA_GHASH
138 if (sdna->types_to_structs_map) {
139 BLI_ghash_free(sdna->types_to_structs_map, nullptr, nullptr);
140 }
141#endif
142
143 if (sdna->mem_arena) {
145 }
146
149#ifdef WITH_DNA_GHASH
150 if (sdna->alias.types_to_structs_map) {
151 BLI_ghash_free(sdna->alias.types_to_structs_map, nullptr, nullptr);
152 }
153#endif
154
155 MEM_freeN(sdna);
156}
157
158int DNA_struct_size(const SDNA *sdna, int struct_index)
159{
160 return sdna->types_size[sdna->structs[struct_index]->type_index];
161}
162
166static bool ispointer(const char *name)
167{
168 /* check if pointer or function pointer */
169 return (name[0] == '*' || (name[0] == '(' && name[1] == '*'));
170}
171
172int DNA_struct_member_size(const SDNA *sdna, short type, short member_index)
173{
174 const char *cp = sdna->members[member_index];
175 int len = 0;
176
177 /* is it a pointer or function pointer? */
178 if (ispointer(cp)) {
179 /* has the name an extra length? (array) */
180 len = sdna->pointer_size * sdna->members_array_num[member_index];
181 }
182 else if (sdna->types_size[type]) {
183 /* has the name an extra length? (array) */
184 len = int(sdna->types_size[type]) * sdna->members_array_num[member_index];
185 }
186
187 return len;
188}
189
190#if 0
191static void printstruct(SDNA *sdna, short struct_index)
192{
193 /* is for debug */
194
195 SDNA_Struct *struct_info = sdna->structs[struct_index];
196 printf("struct %s\n", sdna->types[struct_info->type]);
197
198 for (int b = 0; b < struct_info->members_len; b++) {
199 SDNA_StructMember *struct_member = &struct_info->members[b];
200 printf(" %s %s\n", sdna->types[struct_member->type], sdna->names[struct_member->name]);
201 }
202}
203#endif
204
209 /* From SDNA struct. */
210 const char **types,
211 const int /*types_num*/,
212 SDNA_Struct **const structs,
213 const int structs_num,
214#ifdef WITH_DNA_GHASH
215 GHash *structs_map,
216#endif
217 /* Regular args. */
218 const char *str,
219 uint *struct_index_last)
220{
221 if (*struct_index_last < structs_num) {
222 const SDNA_Struct *struct_info = structs[*struct_index_last];
223 if (STREQ(types[struct_info->type_index], str)) {
224 return *struct_index_last;
225 }
226 }
227
228#ifdef WITH_DNA_GHASH
229 {
230 void **struct_index_p = BLI_ghash_lookup_p(structs_map, str);
231 if (struct_index_p) {
232 const int struct_index = POINTER_AS_INT(*struct_index_p);
233 *struct_index_last = struct_index;
234 return struct_index;
235 }
236 }
237#else
238 {
239 for (int struct_index = 0; struct_index < types_num; struct_index++) {
240 const SDNA_Struct *struct_info = structs[struct_index];
241 if (STREQ(types[struct_info->type], str)) {
242 *struct_index_last = struct_index;
243 return struct_index;
244 }
245 }
246 }
247#endif
248 return -1;
249}
250
252 const char *str,
253 uint *struct_index_last)
254{
255#ifdef WITH_DNA_GHASH
256 BLI_assert(sdna->types_to_structs_map != nullptr);
257#endif
259 /* Expand SDNA. */
260 sdna->types,
261 sdna->types_num,
262 sdna->structs,
263 sdna->structs_num,
264#ifdef WITH_DNA_GHASH
266#endif
267 /* Regular args. */
268 str,
269 struct_index_last);
270}
271
272int DNA_struct_find_index_with_alias_ex(const SDNA *sdna, const char *str, uint *struct_index_last)
273{
274#ifdef WITH_DNA_GHASH
275 BLI_assert(sdna->alias.types_to_structs_map != nullptr);
276#endif
278 /* Expand SDNA. */
279 sdna->alias.types,
280 sdna->types_num,
281 sdna->structs,
282 sdna->structs_num,
283#ifdef WITH_DNA_GHASH
285#endif
286 /* Regular args. */
287 str,
288 struct_index_last);
289}
290
291int DNA_struct_find_index_without_alias(const SDNA *sdna, const char *str)
292{
293 uint index_last_dummy = UINT_MAX;
294 return DNA_struct_find_index_without_alias_ex(sdna, str, &index_last_dummy);
295}
296
297int DNA_struct_find_with_alias(const SDNA *sdna, const char *str)
298{
299 uint index_last_dummy = UINT_MAX;
300 return DNA_struct_find_index_with_alias_ex(sdna, str, &index_last_dummy);
301}
302
303bool DNA_struct_exists_with_alias(const SDNA *sdna, const char *str)
304{
305 return DNA_struct_find_with_alias(sdna, str) != -1;
306}
307
308/* ************************* END DIV ********************** */
309
310/* ************************* READ DNA ********************** */
311
312BLI_INLINE const char *pad_up_4(const char *ptr)
313{
314 return (const char *)((uintptr_t(ptr) + 3) & ~3);
315}
316
320static bool init_structDNA(SDNA *sdna, const char **r_error_message)
321{
322 int member_index_gravity_fix = -1;
323
324 int *data = (int *)sdna->data;
325
326 /* Clear pointers in case of error. */
327 sdna->types = nullptr;
328 sdna->types_size = nullptr;
329 sdna->types_alignment = nullptr;
330 sdna->structs = nullptr;
331#ifdef WITH_DNA_GHASH
332 sdna->types_to_structs_map = nullptr;
333#endif
334
335 sdna->members = nullptr;
336 sdna->members_array_num = nullptr;
337
338 sdna->mem_arena = nullptr;
339
340 /* Lazy initialize. */
341 memset(&sdna->alias, 0, sizeof(sdna->alias));
342
343 /* Struct DNA ('SDNA') */
344 if (*data != MAKE_ID('S', 'D', 'N', 'A')) {
345 *r_error_message = "SDNA error in SDNA file";
346 return false;
347 }
348
349 const char *cp;
350
351 data++;
352 /* Names array ('NAME') */
353 if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
354 data++;
355
356 /* NOTE: this is endianness-sensitive. */
357 sdna->members_num = *data;
358 sdna->members_num_alloc = sdna->members_num;
359
360 data++;
361 sdna->members = MEM_calloc_arrayN<const char *>(sdna->members_num, "sdnanames");
362 }
363 if (!sdna->members) {
364 *r_error_message = "NAME error in SDNA file";
365 return false;
366 }
367
368 cp = (char *)data;
369 for (int member_index = 0; member_index < sdna->members_num; member_index++) {
370 sdna->members[member_index] = cp;
371
372 /* "float gravity [3]" was parsed wrong giving both "gravity" and
373 * "[3]" members. we rename "[3]", and later set the type of
374 * "gravity" to "void" so the offsets work out correct */
375 if (*cp == '[' && STREQ(cp, "[3]")) {
376 if (member_index && STREQ(sdna->members[member_index - 1], "Cvi")) {
377 sdna->members[member_index] = "gravity[3]";
378 member_index_gravity_fix = member_index;
379 }
380 }
381 while (*cp) {
382 cp++;
383 }
384 cp++;
385 }
386
387 cp = pad_up_4(cp);
388
389 /* Type names array ('TYPE') */
390 data = (int *)cp;
391 if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
392 data++;
393
394 /* NOTE: this is endianness-sensitive. */
395 sdna->types_num = *data;
396
397 data++;
398 sdna->types = MEM_calloc_arrayN<const char *>(sdna->types_num, "sdnatypes");
399 }
400 if (!sdna->types) {
401 *r_error_message = "TYPE error in SDNA file";
402 return false;
403 }
404
405 cp = (char *)data;
406 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
407 /* WARNING! See: DNA_struct_rename_legacy_hack_static_from_alias docs. */
409 while (*cp) {
410 cp++;
411 }
412 cp++;
413 }
414
415 cp = pad_up_4(cp);
416
417 /* Type lengths array ('TLEN') */
418 data = (int *)cp;
419 short *sp;
420 if (*data == MAKE_ID('T', 'L', 'E', 'N')) {
421 data++;
422 /* NOTE: this is endianness-sensitive. */
423 sp = (short *)data;
424 sdna->types_size = sp;
425
426 sp += sdna->types_num;
427 }
428 if (!sdna->types_size) {
429 *r_error_message = "TLEN error in SDNA file";
430 return false;
431 }
432 /* prevent BUS error */
433 if (sdna->types_num & 1) {
434 sp++;
435 }
436
437 /* Struct array ('STRC') */
438 data = (int *)sp;
439 if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
440 data++;
441
442 /* NOTE: this is endianness-sensitive. */
443 sdna->structs_num = *data;
444
445 data++;
446 sdna->structs = MEM_calloc_arrayN<SDNA_Struct *>(sdna->structs_num, "sdnastrcs");
447 }
448 if (!sdna->structs) {
449 *r_error_message = "STRC error in SDNA file";
450 return false;
451 }
452
453 /* Safety check, to ensure that there is no multiple usages of a same struct index. */
454 blender::Set<short> struct_indices;
455 sp = (short *)data;
456 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
457 /* NOTE: this is endianness-sensitive. */
458 SDNA_Struct *struct_info = (SDNA_Struct *)sp;
459 sdna->structs[struct_index] = struct_info;
460
461 if (!struct_indices.add(struct_info->type_index)) {
462 *r_error_message = "Invalid duplicate struct type index in SDNA file";
463 return false;
464 }
465
466 sp += 2 + (sizeof(SDNA_StructMember) / sizeof(short)) * struct_info->members_num;
467 }
468
469 {
470 /* second part of gravity problem, setting "gravity" type to void */
471 if (member_index_gravity_fix > -1) {
472 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
473 sp = (short *)sdna->structs[struct_index];
474 if (STREQ(sdna->types[sp[0]], "ClothSimSettings")) {
475 sp[10] = SDNA_TYPE_VOID;
476 }
477 }
478 }
479 }
480
481#ifdef WITH_DNA_GHASH
482 {
483 /* create a ghash lookup to speed up */
484 sdna->types_to_structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->structs_num);
485
486 for (intptr_t struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
487 SDNA_Struct *struct_info = sdna->structs[struct_index];
489 (void *)sdna->types[struct_info->type_index],
490 POINTER_FROM_INT(struct_index));
491 }
492 }
493#endif
494
495 /* Calculate 'sdna->pointer_size'.
496 *
497 * NOTE: Cannot just do `sizeof(void *)` here, since the current DNA may come from a blend-file
498 * saved on a different system, using a different pointer size. So instead, use half the size of
499 * the #ListBase struct (only made of two pointers).
500 */
501 {
502 const int struct_index = DNA_struct_find_index_without_alias(sdna, "ListBase");
503
504 /* Should never happen, only with corrupt file for example. */
505 if (UNLIKELY(struct_index == -1)) {
506 *r_error_message = "ListBase struct error! Not found.";
507 return false;
508 }
509
510 const SDNA_Struct *struct_info = sdna->structs[struct_index];
511 sdna->pointer_size = sdna->types_size[struct_info->type_index] / 2;
512
513 /* Should never fail, double-check that #ListBase struct is still what is should be
514 * (a couple of pointers and nothing else). */
515 if (UNLIKELY(struct_info->members_num != 2 || !ELEM(sdna->pointer_size, 4, 8))) {
516 *r_error_message = "ListBase struct error: invalid computed pointer-size.";
517 return false;
518 }
519 }
520
521 /* Cache name size. */
522 {
523 short *members_array_num = MEM_malloc_arrayN<short>(size_t(sdna->members_num), __func__);
524 for (int member_index = 0; member_index < sdna->members_num; member_index++) {
525 members_array_num[member_index] = DNA_member_array_num(sdna->members[member_index]);
526 }
527 sdna->members_array_num = members_array_num;
528 }
529
530 sdna->types_alignment = MEM_malloc_arrayN<int>(size_t(sdna->types_num), __func__);
531 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
532 sdna->types_alignment[type_index] = int(__STDCPP_DEFAULT_NEW_ALIGNMENT__);
533 }
534 {
535 /* TODO: This should be generalized at some point. We should be able to specify `overaligned`
536 * types directly in the DNA struct definitions. */
537 uint dummy_index = 0;
538 const int mat4x4f_struct_index = DNA_struct_find_index_without_alias_ex(
539 sdna, "mat4x4f", &dummy_index);
540 if (mat4x4f_struct_index > 0) {
541 const SDNA_Struct *struct_info = sdna->structs[mat4x4f_struct_index];
542 const int mat4x4f_type_index = struct_info->type_index;
543 sdna->types_alignment[mat4x4f_type_index] = alignof(blender::float4x4);
544 }
545 }
546
547 return true;
548}
549
551 const int data_len,
552 bool data_alloc,
553 const bool do_alias,
554 const char **r_error_message)
555{
556 SDNA *sdna = MEM_mallocN<SDNA>("sdna");
557 const char *error_message = nullptr;
558
559 sdna->data_size = data_len;
560 if (data_alloc) {
561 char *data_copy = MEM_malloc_arrayN<char>(size_t(data_len), "sdna_data");
562 memcpy(data_copy, data, data_len);
563 sdna->data = data_copy;
564 }
565 else {
566 sdna->data = static_cast<const char *>(data);
567 }
568 sdna->data_alloc = data_alloc;
569
570 if (init_structDNA(sdna, &error_message)) {
571 if (do_alias) {
573 }
574 return sdna;
575 }
576
577 if (r_error_message == nullptr) {
578 fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
579 }
580 else {
581 *r_error_message = error_message;
582 }
583 DNA_sdna_free(sdna);
584 return nullptr;
585}
586
593static SDNA *g_sdna = nullptr;
594
596{
597 g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, true, nullptr);
598}
599
601{
602 BLI_assert(g_sdna != nullptr);
603 return g_sdna;
604}
605
607{
609 g_sdna = nullptr;
610}
611
612/* ******************** END READ DNA ********************** */
613
614/* ******************* HANDLE DNA ***************** */
615
620static void set_compare_flags_for_struct(const SDNA *oldsdna,
621 const SDNA *newsdna,
622 char *compare_flags,
623 const int old_struct_index)
624{
625 if (compare_flags[old_struct_index] != SDNA_CMP_UNKNOWN) {
626 /* This flag has been initialized already. */
627 return;
628 }
629
630 SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
631 const char *struct_name = oldsdna->types[old_struct->type_index];
632
633 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, struct_name);
634 if (new_struct_index == -1) {
635 /* Didn't find a matching new struct, so it has been removed. */
636 compare_flags[old_struct_index] = SDNA_CMP_REMOVED;
637 return;
638 }
639
640 SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
641 if (old_struct->members_num != new_struct->members_num) {
642 /* Structs with a different amount of members are not equal. */
643 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
644 return;
645 }
646 if (oldsdna->types_size[old_struct->type_index] != newsdna->types_size[new_struct->type_index]) {
647 /* Structs that don't have the same size are not equal. */
648 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
649 return;
650 }
651
652 /* Compare each member individually. */
653 for (int member_index = 0; member_index < old_struct->members_num; member_index++) {
654 const SDNA_StructMember *old_member = &old_struct->members[member_index];
655 const SDNA_StructMember *new_member = &new_struct->members[member_index];
656
657 const char *old_type_name = oldsdna->types[old_member->type_index];
658 const char *new_type_name = newsdna->types[new_member->type_index];
659 if (!STREQ(old_type_name, new_type_name)) {
660 /* If two members have a different type in the same place, the structs are not equal. */
661 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
662 return;
663 }
664
665 const char *old_member_name = oldsdna->members[old_member->member_index];
666 const char *new_member_name = newsdna->members[new_member->member_index];
667 if (!STREQ(old_member_name, new_member_name)) {
668 /* If two members have a different name in the same place, the structs are not equal. */
669 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
670 return;
671 }
672
673 if (ispointer(old_member_name)) {
674 if (oldsdna->pointer_size != newsdna->pointer_size) {
675 /* When the struct contains a pointer, and the pointer sizes differ, the structs are not
676 * equal. */
677 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
678 return;
679 }
680 }
681 else {
682 const int old_member_struct_index = DNA_struct_find_index_without_alias(oldsdna,
683 old_type_name);
684 if (old_member_struct_index >= 0) {
685 set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, old_member_struct_index);
686 if (compare_flags[old_member_struct_index] != SDNA_CMP_EQUAL) {
687 /* If an embedded struct is not equal, the parent struct cannot be equal either. */
688 compare_flags[old_struct_index] = SDNA_CMP_NOT_EQUAL;
689 return;
690 }
691 }
692 }
693 }
694
695 compare_flags[old_struct_index] = SDNA_CMP_EQUAL;
696}
697
698const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
699{
700 if (oldsdna->structs_num == 0) {
701 printf("error: file without SDNA\n");
702 return nullptr;
703 }
704
705 char *compare_flags = MEM_malloc_arrayN<char>(size_t(oldsdna->structs_num), "compare flags");
706 memset(compare_flags, SDNA_CMP_UNKNOWN, oldsdna->structs_num);
707
708 /* Set correct flag for every struct. */
709 for (int old_struct_index = 0; old_struct_index < oldsdna->structs_num; old_struct_index++) {
710 set_compare_flags_for_struct(oldsdna, newsdna, compare_flags, old_struct_index);
711 BLI_assert(compare_flags[old_struct_index] != SDNA_CMP_UNKNOWN);
712 }
713
714 /* First struct is the fake 'raw data' one (see the #SDNA_TYPE_RAW_DATA 'basic type' definition
715 * and its usages). By definition, it is always 'equal'.
716 *
717 * NOTE: Bugs History (pre-4.3).
718 *
719 * It used to be `struct Link`, it was skipped in compare_flags (at index `0`). This was a bug,
720 * and was dirty-patched by setting `compare_flags[0]` to `SDNA_CMP_EQUAL` unconditionally.
721 *
722 * Then the `0` struct became `struct DrawDataList`, which was never actually written in
723 * blend-files.
724 *
725 * Write and read blend-file code also has had implicit assumptions that a `0` value in the
726 * #BHead.SDNAnr (aka DNA struct index) meant 'raw data', and therefore was not representing any
727 * real DNA struct. This assumption has been false for years. By luck, this bug seems to have
728 * been fully harmless, for at least the following reasons:
729 * - Read code always ignored DNA struct info in BHead blocks with a `0` value.
730 * - `DrawDataList` data was never actually written in blend-files.
731 * - `struct Link` never needed DNA-versioning.
732 *
733 * NOTE: This may have been broken in BE/LE conversion cases, however this endianness handling
734 * code have likely been dead/never used in practice for many years, and has been removed in
735 * Blender 5.0.
736 */
737 BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
739
740/* This code can be enabled to see which structs have changed. */
741#if 0
742 for (int a = 0; a < oldsdna->structs_len; a++) {
743 if (compare_flags[a] == SDNA_CMP_NOT_EQUAL) {
744 SDNA_Struct *struct_info = oldsdna->structs[a];
745 printf("changed: %s\n", oldsdna->types[struct_info->type]);
746 }
747 }
748#endif
749
750 return compare_flags;
751}
752
765static void cast_primitive_type(const eSDNA_Type old_type,
766 const eSDNA_Type new_type,
767 const int array_len,
768 const char *old_data,
769 char *new_data)
770{
771 /* define lengths */
772 const int oldlen = DNA_elem_type_size(old_type);
773 const int curlen = DNA_elem_type_size(new_type);
774
775 double old_value_f = 0.0;
776 /* Intentionally overflow signed values into an unsigned type.
777 * Casting back to a signed value preserves the sign (when the new value is signed). */
778 uint64_t old_value_i = 0;
779
780 for (int a = 0; a < array_len; a++) {
781 switch (old_type) {
782 case SDNA_TYPE_CHAR: {
783 const char value = *old_data;
784 old_value_i = value;
785 old_value_f = double(value);
786 break;
787 }
788 case SDNA_TYPE_UCHAR: {
789 const uchar value = *reinterpret_cast<const uchar *>(old_data);
790 old_value_i = value;
791 old_value_f = double(value);
792 break;
793 }
794 case SDNA_TYPE_SHORT: {
795 const short value = *reinterpret_cast<const short *>(old_data);
796 old_value_i = value;
797 old_value_f = double(value);
798 break;
799 }
800 case SDNA_TYPE_USHORT: {
801 const ushort value = *reinterpret_cast<const ushort *>(old_data);
802 old_value_i = value;
803 old_value_f = double(value);
804 break;
805 }
806 case SDNA_TYPE_INT: {
807 const int value = *reinterpret_cast<const int *>(old_data);
808 old_value_i = value;
809 old_value_f = double(value);
810 break;
811 }
812 case SDNA_TYPE_FLOAT: {
813 const float value = *reinterpret_cast<const float *>(old_data);
814 /* `int64_t` range stored in a `uint64_t`. */
815 old_value_i = uint64_t(int64_t(value));
816 old_value_f = value;
817 break;
818 }
819 case SDNA_TYPE_DOUBLE: {
820 const double value = *reinterpret_cast<const double *>(old_data);
821 /* `int64_t` range stored in a `uint64_t`. */
822 old_value_i = uint64_t(int64_t(value));
823 old_value_f = value;
824 break;
825 }
826 case SDNA_TYPE_INT64: {
827 const int64_t value = *reinterpret_cast<const int64_t *>(old_data);
828 old_value_i = uint64_t(value);
829 old_value_f = double(value);
830 break;
831 }
832 case SDNA_TYPE_UINT64: {
833 const uint64_t value = *reinterpret_cast<const uint64_t *>(old_data);
834 old_value_i = value;
835 old_value_f = double(value);
836 break;
837 }
838 case SDNA_TYPE_INT8: {
839 const int8_t value = *reinterpret_cast<const int8_t *>(old_data);
840 old_value_i = uint64_t(value);
841 old_value_f = double(value);
842 break;
843 }
845 BLI_assert_msg(false, "Conversion from SDNA_TYPE_RAW_DATA is not supported");
846 break;
847 }
848
849 switch (new_type) {
850 case SDNA_TYPE_CHAR:
851 *new_data = char(old_value_i);
852 break;
853 case SDNA_TYPE_UCHAR:
854 *reinterpret_cast<uchar *>(new_data) = uchar(old_value_i);
855 break;
856 case SDNA_TYPE_SHORT:
857 *reinterpret_cast<short *>(new_data) = short(old_value_i);
858 break;
859 case SDNA_TYPE_USHORT:
860 *reinterpret_cast<ushort *>(new_data) = ushort(old_value_i);
861 break;
862 case SDNA_TYPE_INT:
863 *reinterpret_cast<int *>(new_data) = int(old_value_i);
864 break;
865 case SDNA_TYPE_FLOAT:
866 if (old_type < 2) {
867 old_value_f /= 255.0;
868 }
869 *reinterpret_cast<float *>(new_data) = old_value_f;
870 break;
871 case SDNA_TYPE_DOUBLE:
872 if (old_type < 2) {
873 old_value_f /= 255.0;
874 }
875 *reinterpret_cast<double *>(new_data) = old_value_f;
876 break;
877 case SDNA_TYPE_INT64:
878 *reinterpret_cast<int64_t *>(new_data) = int64_t(old_value_i);
879 break;
880 case SDNA_TYPE_UINT64:
881 *reinterpret_cast<uint64_t *>(new_data) = old_value_i;
882 break;
883 case SDNA_TYPE_INT8:
884 *reinterpret_cast<int8_t *>(new_data) = int8_t(old_value_i);
885 break;
887 BLI_assert_msg(false, "Conversion to SDNA_TYPE_RAW_DATA is not supported");
888 break;
889 }
890
891 old_data += oldlen;
892 new_data += curlen;
893 }
894}
895
896static void cast_pointer_32_to_64(const int array_len,
897 const uint32_t *old_data,
898 uint64_t *new_data)
899{
900 for (int a = 0; a < array_len; a++) {
901 new_data[a] = old_data[a];
902 }
903}
904
905static void cast_pointer_64_to_32(const int array_len,
906 const uint64_t *old_data,
907 uint32_t *new_data)
908{
909 /* WARNING: 32-bit Blender trying to load file saved by 64-bit Blender,
910 * pointers may lose uniqueness on truncation! (Hopefully this won't
911 * happen unless/until we ever get to multi-gigabyte .blend files...) */
912 for (int a = 0; a < array_len; a++) {
913 new_data[a] = old_data[a] >> 3;
914 }
915}
916
920static bool elem_streq(const char *name, const char *oname)
921{
922 int a = 0;
923
924 while (true) {
925 if (name[a] != oname[a]) {
926 return false;
927 }
928 if (name[a] == '[' || oname[a] == '[') {
929 break;
930 }
931 if (name[a] == 0 || oname[a] == 0) {
932 break;
933 }
934 a++;
935 }
936 return true;
937}
938
949 /* Expand SDNA. */
950 const char **types,
951 const char **names,
952 /* Regular args. */
953 const char *type,
954 const char *name,
955 const SDNA_Struct *old)
956{
957 /* in old is the old struct */
958 for (int a = 0; a < old->members_num; a++) {
959 const SDNA_StructMember *member = &old->members[a];
960 const char *otype = types[member->type_index];
961 const char *oname = names[member->member_index];
962
963 if (elem_streq(name, oname)) { /* name equal */
964 return STREQ(type, otype); /* type equal */
965 }
966 }
967 return false;
968}
969
973static bool elem_exists_without_alias(const SDNA *sdna,
974 const char *type,
975 const char *name,
976 const SDNA_Struct *old)
977{
978 return elem_exists_impl(
979 /* Expand SDNA. */
980 sdna->types,
981 sdna->members,
982 /* Regular args. */
983 type,
984 name,
985 old);
986}
987
988static bool elem_exists_with_alias(const SDNA *sdna,
989 const char *type,
990 const char *name,
991 const SDNA_Struct *old)
992{
993 return elem_exists_impl(
994 /* Expand SDNA. */
995 sdna->alias.types,
996 sdna->alias.members,
997 /* Regular args. */
998 type,
999 name,
1000 old);
1001}
1002
1003static int elem_offset_impl(const SDNA *sdna,
1004 const char **types,
1005 const char **names,
1006 const char *type,
1007 const char *name,
1008 const SDNA_Struct *old)
1009{
1010 /* Without array-part, so names can differ: return old `namenr` and type. */
1011
1012 /* in old is the old struct */
1013 int offset = 0;
1014 for (int a = 0; a < old->members_num; a++) {
1015 const SDNA_StructMember *member = &old->members[a];
1016 const char *otype = types[member->type_index];
1017 const char *oname = names[member->member_index];
1018 if (elem_streq(name, oname)) { /* name equal */
1019 if (STREQ(type, otype)) { /* type equal */
1020 return offset;
1021 }
1022 break; /* Fail below. */
1023 }
1024 offset += DNA_struct_member_size(sdna, member->type_index, member->member_index);
1025 }
1026 return -1;
1027}
1028
1044static int elem_offset_without_alias(const SDNA *sdna,
1045 const char *type,
1046 const char *name,
1047 const SDNA_Struct *old)
1048{
1049 return elem_offset_impl(sdna, sdna->types, sdna->members, type, name, old);
1050}
1051
1055static int elem_offset_with_alias(const SDNA *sdna,
1056 const char *type,
1057 const char *name,
1058 const SDNA_Struct *old)
1059{
1060 return elem_offset_impl(sdna, sdna->alias.types, sdna->alias.members, type, name, old);
1061}
1062
1063/* Each struct member belongs to one of the categories below. */
1069
1071 const SDNA_StructMember *member)
1072{
1073 const char *member_name = sdna->members[member->member_index];
1074 if (ispointer(member_name)) {
1076 }
1077 const char *member_type_name = sdna->types[member->type_index];
1078 if (DNA_struct_exists_without_alias(sdna, member_type_name)) {
1080 }
1082}
1083
1084static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member)
1085{
1086 const char *name = sdna->members[member->member_index];
1087 const int array_length = sdna->members_array_num[member->member_index];
1088 if (ispointer(name)) {
1089 return sdna->pointer_size * array_length;
1090 }
1091 const int type_size = sdna->types_size[member->type_index];
1092 return type_size * array_length;
1093}
1094
1103
1106 union {
1107 struct {
1110 int size;
1112 struct {
1113 int old_offset;
1114 int new_offset;
1119 struct {
1120 int old_offset;
1121 int new_offset;
1122 int array_len;
1124 struct {
1125 int old_offset;
1126 int new_offset;
1127 int array_len;
1132};
1133
1142
1143static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1144 const int blocks,
1145 const int old_struct_index,
1146 const int new_struct_index,
1147 const char *old_blocks,
1148 char *new_blocks);
1149
1159static void reconstruct_struct(const DNA_ReconstructInfo *reconstruct_info,
1160 const int new_struct_index,
1161 const char *old_block,
1162 char *new_block)
1163{
1164 const ReconstructStep *steps = reconstruct_info->steps[new_struct_index];
1165 const int step_count = reconstruct_info->step_counts[new_struct_index];
1166
1167 /* Execute all preprocessed steps. */
1168 for (int a = 0; a < step_count; a++) {
1169 const ReconstructStep *step = &steps[a];
1170 switch (step->type) {
1172 memcpy(new_block + step->data.memcpy.new_offset,
1173 old_block + step->data.memcpy.old_offset,
1174 step->data.memcpy.size);
1175 break;
1177 cast_primitive_type(step->data.cast_primitive.old_type,
1178 step->data.cast_primitive.new_type,
1179 step->data.cast_primitive.array_len,
1180 old_block + step->data.cast_primitive.old_offset,
1181 new_block + step->data.cast_primitive.new_offset);
1182 break;
1184 cast_pointer_64_to_32(step->data.cast_pointer.array_len,
1185 (const uint64_t *)(old_block + step->data.cast_pointer.old_offset),
1186 (uint32_t *)(new_block + step->data.cast_pointer.new_offset));
1187 break;
1189 cast_pointer_32_to_64(step->data.cast_pointer.array_len,
1190 (const uint32_t *)(old_block + step->data.cast_pointer.old_offset),
1191 (uint64_t *)(new_block + step->data.cast_pointer.new_offset));
1192 break;
1194 reconstruct_structs(reconstruct_info,
1195 step->data.substruct.array_len,
1196 step->data.substruct.old_struct_index,
1197 step->data.substruct.new_struct_index,
1198 old_block + step->data.substruct.old_offset,
1199 new_block + step->data.substruct.new_offset);
1200 break;
1202 /* Do nothing, because the memory block are zeroed (from #MEM_callocN).
1203 *
1204 * Note that the struct could be initialized with the default struct,
1205 * however this complicates versioning, especially with flags, see: D4500. */
1206 break;
1207 }
1208 }
1209}
1210
1212static void reconstruct_structs(const DNA_ReconstructInfo *reconstruct_info,
1213 const int blocks,
1214 const int old_struct_index,
1215 const int new_struct_index,
1216 const char *old_blocks,
1217 char *new_blocks)
1218{
1219 const SDNA_Struct *old_struct = reconstruct_info->oldsdna->structs[old_struct_index];
1220 const SDNA_Struct *new_struct = reconstruct_info->newsdna->structs[new_struct_index];
1221
1222 const int old_block_size = reconstruct_info->oldsdna->types_size[old_struct->type_index];
1223 const int new_block_size = reconstruct_info->newsdna->types_size[new_struct->type_index];
1224
1225 for (int a = 0; a < blocks; a++) {
1226 const char *old_block = old_blocks + a * old_block_size;
1227 char *new_block = new_blocks + a * new_block_size;
1228 reconstruct_struct(reconstruct_info, new_struct_index, old_block, new_block);
1229 }
1230}
1231
1232void *DNA_struct_reconstruct(const DNA_ReconstructInfo *reconstruct_info,
1233 int old_struct_index,
1234 int blocks,
1235 const void *old_blocks,
1236 const char *alloc_name)
1237{
1238 const SDNA *oldsdna = reconstruct_info->oldsdna;
1239 const SDNA *newsdna = reconstruct_info->newsdna;
1240
1241 const SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
1242 const char *type_name = oldsdna->types[old_struct->type_index];
1243 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, type_name);
1244
1245 if (new_struct_index == -1) {
1246 return nullptr;
1247 }
1248
1249 const SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
1250 const int new_block_size = newsdna->types_size[new_struct->type_index];
1251
1252 const int alignment = DNA_struct_alignment(newsdna, new_struct_index);
1253 char *new_blocks = static_cast<char *>(
1254 MEM_calloc_arrayN_aligned(new_block_size, blocks, alignment, alloc_name));
1255 reconstruct_structs(reconstruct_info,
1256 blocks,
1257 old_struct_index,
1258 new_struct_index,
1259 static_cast<const char *>(old_blocks),
1260 new_blocks);
1261 return new_blocks;
1262}
1263
1266 const SDNA_Struct *struct_info,
1267 const char *name,
1268 int *r_offset)
1269{
1270 int offset = 0;
1271 for (int a = 0; a < struct_info->members_num; a++) {
1272 const SDNA_StructMember *member = &struct_info->members[a];
1273 const char *member_name = sdna->members[member->member_index];
1274 if (elem_streq(name, member_name)) {
1275 *r_offset = offset;
1276 return member;
1277 }
1278 offset += get_member_size_in_bytes(sdna, member);
1279 }
1280 return nullptr;
1281}
1282
1284static void init_reconstruct_step_for_member(const SDNA *oldsdna,
1285 const SDNA *newsdna,
1286 const char *compare_flags,
1287 const SDNA_Struct *old_struct,
1288 const SDNA_StructMember *new_member,
1289 const int new_member_offset,
1290 ReconstructStep *r_step)
1291{
1292
1293 /* Find the matching old member. */
1294 int old_member_offset;
1295 const char *new_name = newsdna->members[new_member->member_index];
1297 oldsdna, old_struct, new_name, &old_member_offset);
1298
1299 if (old_member == nullptr) {
1300 /* No matching member has been found in the old struct. */
1302 return;
1303 }
1304
1305 /* Determine the member category of the old an new members. */
1306 const eStructMemberCategory new_category = get_struct_member_category(newsdna, new_member);
1307 const eStructMemberCategory old_category = get_struct_member_category(oldsdna, old_member);
1308
1309 if (new_category != old_category) {
1310 /* Can only reconstruct the new member based on the old member, when the belong to the same
1311 * category. */
1313 return;
1314 }
1315
1316 const int new_array_length = newsdna->members_array_num[new_member->member_index];
1317 const int old_array_length = oldsdna->members_array_num[old_member->member_index];
1318 const int shared_array_length = std::min(new_array_length, old_array_length);
1319
1320 const char *new_type_name = newsdna->types[new_member->type_index];
1321 const char *old_type_name = oldsdna->types[old_member->type_index];
1322
1323 switch (new_category) {
1325 if (STREQ(new_type_name, old_type_name)) {
1326 const int old_struct_index = DNA_struct_find_index_without_alias(oldsdna, old_type_name);
1327 BLI_assert(old_struct_index != -1);
1328 enum eSDNA_StructCompare compare_flag = eSDNA_StructCompare(
1329 compare_flags[old_struct_index]);
1330 BLI_assert(compare_flag != SDNA_CMP_REMOVED);
1331 if (compare_flag == SDNA_CMP_EQUAL) {
1332 /* The old and new members are identical, just do a #memcpy. */
1333 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1334 r_step->data.memcpy.new_offset = new_member_offset;
1335 r_step->data.memcpy.old_offset = old_member_offset;
1336 r_step->data.memcpy.size = newsdna->types_size[new_member->type_index] *
1337 shared_array_length;
1338 }
1339 else {
1340 const int new_struct_index = DNA_struct_find_index_without_alias(newsdna, new_type_name);
1341 BLI_assert(new_struct_index != -1);
1342
1343 /* The old and new members are different, use recursion to reconstruct the
1344 * nested struct. */
1345 BLI_assert(compare_flag == SDNA_CMP_NOT_EQUAL);
1347 r_step->data.substruct.new_offset = new_member_offset;
1348 r_step->data.substruct.old_offset = old_member_offset;
1349 r_step->data.substruct.array_len = shared_array_length;
1350 r_step->data.substruct.new_struct_index = new_struct_index;
1351 r_step->data.substruct.old_struct_index = old_struct_index;
1352 }
1353 }
1354 else {
1355 /* Cannot match structs that have different names. */
1357 }
1358 break;
1359 }
1361 if (STREQ(new_type_name, old_type_name)) {
1362 /* Primitives with the same name cannot be different, so just do a #memcpy. */
1363 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1364 r_step->data.memcpy.new_offset = new_member_offset;
1365 r_step->data.memcpy.old_offset = old_member_offset;
1366 r_step->data.memcpy.size = newsdna->types_size[new_member->type_index] *
1367 shared_array_length;
1368 }
1369 else {
1370 /* The old and new primitive types are different, cast from the old to new type. */
1372 r_step->data.cast_primitive.array_len = shared_array_length;
1373 r_step->data.cast_primitive.new_offset = new_member_offset;
1374 r_step->data.cast_primitive.old_offset = old_member_offset;
1375 r_step->data.cast_primitive.new_type = eSDNA_Type(new_member->type_index);
1376 r_step->data.cast_primitive.old_type = eSDNA_Type(old_member->type_index);
1377 }
1378 break;
1379 }
1381 if (newsdna->pointer_size == oldsdna->pointer_size) {
1382 /* The pointer size is the same, so just do a #memcpy. */
1383 r_step->type = RECONSTRUCT_STEP_MEMCPY;
1384 r_step->data.memcpy.new_offset = new_member_offset;
1385 r_step->data.memcpy.old_offset = old_member_offset;
1386 r_step->data.memcpy.size = newsdna->pointer_size * shared_array_length;
1387 }
1388 else if (newsdna->pointer_size == 8 && oldsdna->pointer_size == 4) {
1389 /* Need to convert from 32 bit to 64 bit pointers. */
1391 r_step->data.cast_pointer.new_offset = new_member_offset;
1392 r_step->data.cast_pointer.old_offset = old_member_offset;
1393 r_step->data.cast_pointer.array_len = shared_array_length;
1394 }
1395 else if (newsdna->pointer_size == 4 && oldsdna->pointer_size == 8) {
1396 /* Need to convert from 64 bit to 32 bit pointers. */
1398 r_step->data.cast_pointer.new_offset = new_member_offset;
1399 r_step->data.cast_pointer.old_offset = old_member_offset;
1400 r_step->data.cast_pointer.array_len = shared_array_length;
1401 }
1402 else {
1403 BLI_assert_msg(0, "invalid pointer size");
1405 }
1406 break;
1407 }
1408 }
1409}
1410
1412[[maybe_unused]] static void print_reconstruct_step(const ReconstructStep *step,
1413 const SDNA *oldsdna,
1414 const SDNA *newsdna)
1415{
1416 switch (step->type) {
1418 printf("initialize zero");
1419 break;
1420 }
1422 printf("memcpy, size: %d, old offset: %d, new offset: %d",
1423 step->data.memcpy.size,
1424 step->data.memcpy.old_offset,
1425 step->data.memcpy.new_offset);
1426 break;
1427 }
1429 printf(
1430 "cast element, old type: %d ('%s'), new type: %d ('%s'), old offset: %d, new offset: "
1431 "%d, length: %d",
1432 int(step->data.cast_primitive.old_type),
1433 oldsdna->types[step->data.cast_primitive.old_type],
1434 int(step->data.cast_primitive.new_type),
1435 newsdna->types[step->data.cast_primitive.new_type],
1436 step->data.cast_primitive.old_offset,
1437 step->data.cast_primitive.new_offset,
1438 step->data.cast_primitive.array_len);
1439 break;
1440 }
1442 printf("pointer to 32, old offset: %d, new offset: %d, length: %d",
1443 step->data.cast_pointer.old_offset,
1444 step->data.cast_pointer.new_offset,
1445 step->data.cast_pointer.array_len);
1446 break;
1447 }
1449 printf("pointer to 64, old offset: %d, new offset: %d, length: %d",
1450 step->data.cast_pointer.old_offset,
1451 step->data.cast_pointer.new_offset,
1452 step->data.cast_pointer.array_len);
1453 break;
1454 }
1456 printf(
1457 "substruct, old offset: %d, new offset: %d, new struct: %d ('%s', size per struct: %d), "
1458 "length: %d",
1459 step->data.substruct.old_offset,
1460 step->data.substruct.new_offset,
1461 step->data.substruct.new_struct_index,
1462 newsdna->types[newsdna->structs[step->data.substruct.new_struct_index]->type_index],
1463 newsdna->types_size[newsdna->structs[step->data.substruct.new_struct_index]->type_index],
1464 step->data.substruct.array_len);
1465 break;
1466 }
1467 }
1468}
1469
1475 const SDNA *newsdna,
1476 const char *compare_flags,
1477 const SDNA_Struct *old_struct,
1478 const SDNA_Struct *new_struct)
1479{
1480 ReconstructStep *steps = MEM_calloc_arrayN<ReconstructStep>(new_struct->members_num, __func__);
1481
1482 int new_member_offset = 0;
1483 for (int new_member_index = 0; new_member_index < new_struct->members_num; new_member_index++) {
1484 const SDNA_StructMember *new_member = &new_struct->members[new_member_index];
1486 newsdna,
1487 compare_flags,
1488 old_struct,
1489 new_member,
1490 new_member_offset,
1491 &steps[new_member_index]);
1492 new_member_offset += get_member_size_in_bytes(newsdna, new_member);
1493 }
1494
1495 return steps;
1496}
1497
1499static int compress_reconstruct_steps(ReconstructStep *steps, const int old_step_count)
1500{
1501 int new_step_count = 0;
1502 for (int a = 0; a < old_step_count; a++) {
1503 ReconstructStep *step = &steps[a];
1504 switch (step->type) {
1506 /* These steps are simply removed. */
1507 break;
1509 if (new_step_count > 0) {
1510 /* Try to merge this memcpy step with the previous one. */
1511 ReconstructStep *prev_step = &steps[new_step_count - 1];
1512 if (prev_step->type == RECONSTRUCT_STEP_MEMCPY) {
1513 /* Check if there are no bytes between the blocks to copy. */
1514 if (prev_step->data.memcpy.old_offset + prev_step->data.memcpy.size ==
1515 step->data.memcpy.old_offset &&
1516 prev_step->data.memcpy.new_offset + prev_step->data.memcpy.size ==
1517 step->data.memcpy.new_offset)
1518 {
1519 prev_step->data.memcpy.size += step->data.memcpy.size;
1520 break;
1521 }
1522 }
1523 }
1524 steps[new_step_count] = *step;
1525 new_step_count++;
1526 break;
1531 /* These steps are not changed at all for now. It should be possible to merge consecutive
1532 * steps of the same type, but it is not really worth it. */
1533 steps[new_step_count] = *step;
1534 new_step_count++;
1535 break;
1536 }
1537 }
1538 return new_step_count;
1539}
1540
1542 const SDNA *newsdna,
1543 const char *compare_flags)
1544{
1545 DNA_ReconstructInfo *reconstruct_info = MEM_callocN<DNA_ReconstructInfo>(__func__);
1546 reconstruct_info->oldsdna = oldsdna;
1547 reconstruct_info->newsdna = newsdna;
1548 reconstruct_info->compare_flags = compare_flags;
1549 reconstruct_info->step_counts = MEM_malloc_arrayN<int>(size_t(newsdna->structs_num), __func__);
1550 reconstruct_info->steps = MEM_malloc_arrayN<ReconstructStep *>(size_t(newsdna->structs_num),
1551 __func__);
1552
1553 /* Generate reconstruct steps for all structs. */
1554 for (int new_struct_index = 0; new_struct_index < newsdna->structs_num; new_struct_index++) {
1555 const SDNA_Struct *new_struct = newsdna->structs[new_struct_index];
1556 const char *new_struct_name = newsdna->types[new_struct->type_index];
1557 const int old_struct_index = DNA_struct_find_index_without_alias(oldsdna, new_struct_name);
1558 if (old_struct_index < 0) {
1559 reconstruct_info->steps[new_struct_index] = nullptr;
1560 reconstruct_info->step_counts[new_struct_index] = 0;
1561 continue;
1562 }
1563 const SDNA_Struct *old_struct = oldsdna->structs[old_struct_index];
1565 oldsdna, newsdna, compare_flags, old_struct, new_struct);
1566
1567 /* Comment the line below to skip the compression for debugging purposes. */
1568 const int steps_len = compress_reconstruct_steps(steps, new_struct->members_num);
1569
1570 reconstruct_info->steps[new_struct_index] = steps;
1571 reconstruct_info->step_counts[new_struct_index] = steps_len;
1572
1573/* This is useful when debugging the reconstruct steps. */
1574#if 0
1575 printf("%s: \n", new_struct_name);
1576 for (int a = 0; a < steps_len; a++) {
1577 printf(" ");
1578 print_reconstruct_step(&steps[a], oldsdna, newsdna);
1579 printf("\n");
1580 }
1581#endif
1582 }
1583
1584 return reconstruct_info;
1585}
1586
1588{
1589 for (int new_struct_index = 0; new_struct_index < reconstruct_info->newsdna->structs_num;
1590 new_struct_index++)
1591 {
1592 if (reconstruct_info->steps[new_struct_index] != nullptr) {
1593 MEM_freeN(reconstruct_info->steps[new_struct_index]);
1594 }
1595 }
1596 MEM_freeN(reconstruct_info->steps);
1597 MEM_freeN(reconstruct_info->step_counts);
1598 MEM_freeN(reconstruct_info);
1599}
1600
1602 const char *stype,
1603 const char *vartype,
1604 const char *name)
1605{
1606 const int struct_index = DNA_struct_find_index_without_alias(sdna, stype);
1607 BLI_assert(struct_index != -1);
1608 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1609 return elem_offset_without_alias(sdna, vartype, name, struct_info);
1610}
1611
1613 const char *stype,
1614 const char *vartype,
1615 const char *name)
1616{
1617 const int struct_index = DNA_struct_find_with_alias(sdna, stype);
1618 BLI_assert(struct_index != -1);
1619 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1620 return elem_offset_with_alias(sdna, vartype, name, struct_info);
1621}
1622
1623bool DNA_struct_exists_without_alias(const SDNA *sdna, const char *stype)
1624{
1625 return DNA_struct_find_index_without_alias(sdna, stype) != -1;
1626}
1627
1629 const char *stype,
1630 const char *vartype,
1631 const char *name)
1632{
1633 const int struct_index = DNA_struct_find_index_without_alias(sdna, stype);
1634
1635 if (struct_index != -1) {
1636 const SDNA_Struct *const struct_info = sdna->structs[struct_index];
1637 const bool found = elem_exists_without_alias(sdna, vartype, name, struct_info);
1638
1639 if (found) {
1640 return true;
1641 }
1642 }
1643 return false;
1644}
1645
1647 const char *stype,
1648 const char *vartype,
1649 const char *name)
1650{
1651 const int SDNAnr = DNA_struct_find_with_alias(sdna, stype);
1652
1653 if (SDNAnr != -1) {
1654 const SDNA_Struct *const spo = sdna->structs[SDNAnr];
1655 const bool found = elem_exists_with_alias(sdna, vartype, name, spo);
1656
1657 if (found) {
1658 return true;
1659 }
1660 }
1661 return false;
1662}
1663
1665{
1666 /* should contain all enum types */
1667 switch (elem_nr) {
1668 case SDNA_TYPE_CHAR:
1669 case SDNA_TYPE_UCHAR:
1670 case SDNA_TYPE_INT8:
1671 return 1;
1672 case SDNA_TYPE_SHORT:
1673 case SDNA_TYPE_USHORT:
1674 return 2;
1675 case SDNA_TYPE_INT:
1676 case SDNA_TYPE_FLOAT:
1677 return 4;
1678 case SDNA_TYPE_DOUBLE:
1679 case SDNA_TYPE_INT64:
1680 case SDNA_TYPE_UINT64:
1681 return 8;
1682 case SDNA_TYPE_RAW_DATA:
1683 BLI_assert_msg(false, "Operations on the size of SDNA_TYPE_RAW_DATA is not supported");
1684 return 0;
1685 }
1686
1687 /* weak */
1688 return 8;
1689}
1690
1691int DNA_struct_alignment(const SDNA *sdna, const int struct_index)
1692{
1693 return sdna->types_alignment[struct_index];
1694}
1695
1696const char *DNA_struct_identifier(SDNA *sdna, const int struct_index)
1697{
1699 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1700 return sdna->alias.types[struct_info->type_index];
1701}
1702
1703/* -------------------------------------------------------------------- */
1706
1707static bool DNA_sdna_patch_struct(SDNA *sdna, const int struct_index, const char *new_type_name)
1708{
1710 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1711#ifdef WITH_DNA_GHASH
1713 sdna->types_to_structs_map, (void *)sdna->types[struct_info->type_index], nullptr, nullptr);
1715 sdna->types_to_structs_map, (void *)new_type_name, POINTER_FROM_INT(struct_index));
1716#endif
1717 sdna->types[struct_info->type_index] = new_type_name;
1718 return true;
1719}
1721 const char *old_type_name,
1722 const char *new_type_name)
1723{
1724 const int struct_index = DNA_struct_find_index_without_alias(sdna, old_type_name);
1725 if (struct_index != -1) {
1726 return DNA_sdna_patch_struct(sdna, struct_index, new_type_name);
1727 }
1728 return false;
1729}
1730
1731/* Make public if called often with same struct (avoid duplicate lookups). */
1733 const int struct_index,
1734 const char *old_member_name,
1735 const char *new_member_name)
1736{
1737 /* These names aren't handled here (it's not used).
1738 * Ensure they are never used or we get out of sync arrays. */
1739 BLI_assert(sdna->alias.members == nullptr);
1740 const int old_member_name_len = strlen(old_member_name);
1741 const int new_member_name_len = strlen(new_member_name);
1742 BLI_assert(new_member_name != nullptr);
1743 SDNA_Struct *struct_info = sdna->structs[struct_index];
1744 for (int struct_member_index = struct_info->members_num; struct_member_index > 0;
1745 struct_member_index--)
1746 {
1747 SDNA_StructMember *member_info = &struct_info->members[struct_member_index];
1748 const char *old_member_name_full = sdna->members[member_info->member_index];
1749 /* Start & end offsets in #old_member_full. */
1750 uint old_member_name_full_offset_start;
1751 if (DNA_member_id_match(old_member_name,
1752 old_member_name_len,
1753 old_member_name_full,
1754 &old_member_name_full_offset_start))
1755 {
1756 if (sdna->mem_arena == nullptr) {
1758 }
1759 const char *new_member_name_full = DNA_member_id_rename(sdna->mem_arena,
1760 old_member_name,
1761 old_member_name_len,
1762 new_member_name,
1763 new_member_name_len,
1764 old_member_name_full,
1765 strlen(old_member_name_full),
1766 old_member_name_full_offset_start);
1767
1768 if (sdna->members_num == sdna->members_num_alloc) {
1769 sdna->members_num_alloc += 64;
1770 sdna->members = static_cast<const char **>(MEM_recallocN(
1771 (void *)sdna->members, sizeof(*sdna->members) * sdna->members_num_alloc));
1772 sdna->members_array_num = static_cast<short int *>(
1773 MEM_recallocN((void *)sdna->members_array_num,
1774 sizeof(*sdna->members_array_num) * sdna->members_num_alloc));
1775 }
1776 const short old_member_index = member_info->member_index;
1777 member_info->member_index = sdna->members_num++;
1778 sdna->members[member_info->member_index] = new_member_name_full;
1779 sdna->members_array_num[member_info->member_index] =
1780 sdna->members_array_num[old_member_index];
1781
1782 return true;
1783 }
1784 }
1785 return false;
1786}
1788 const char *type_name,
1789 const char *old_member_name,
1790 const char *new_member_name)
1791{
1792 const int struct_index = DNA_struct_find_index_without_alias(sdna, type_name);
1793 if (struct_index != -1) {
1794 return DNA_sdna_patch_struct_member(sdna, struct_index, old_member_name, new_member_name);
1795 }
1796 return false;
1797}
1798
1800
1801/* -------------------------------------------------------------------- */
1806
1813static void sdna_expand_names(SDNA *sdna)
1814{
1815 int names_expand_len = 0;
1816 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1817 const SDNA_Struct *struct_old = sdna->structs[struct_index];
1818 names_expand_len += struct_old->members_num;
1819 }
1820 const char **names_expand = MEM_malloc_arrayN<const char *>(size_t(names_expand_len), __func__);
1821 short *names_array_len_expand = MEM_malloc_arrayN<short>(size_t(names_expand_len), __func__);
1822
1823 int names_expand_index = 0;
1824 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1825 /* We can't edit this memory 'sdna->structs' points to (read-only `datatoc` file). */
1826 const SDNA_Struct *struct_old = sdna->structs[struct_index];
1827
1828 const int array_size = sizeof(short) * 2 + sizeof(SDNA_StructMember) * struct_old->members_num;
1829 SDNA_Struct *struct_new = static_cast<SDNA_Struct *>(
1830 BLI_memarena_alloc(sdna->mem_arena, array_size));
1831 memcpy(struct_new, struct_old, array_size);
1832 sdna->structs[struct_index] = struct_new;
1833
1834 for (int i = 0; i < struct_old->members_num; i++) {
1835 const SDNA_StructMember *member_old = &struct_old->members[i];
1836 SDNA_StructMember *member_new = &struct_new->members[i];
1837
1838 names_expand[names_expand_index] = sdna->members[member_old->member_index];
1839 names_array_len_expand[names_expand_index] =
1840 sdna->members_array_num[member_old->member_index];
1841
1842 BLI_assert(names_expand_index < SHRT_MAX);
1843 member_new->member_index = names_expand_index;
1844 names_expand_index++;
1845 }
1846 }
1847 MEM_freeN(sdna->members);
1848 sdna->members = names_expand;
1849
1851 sdna->members_array_num = names_array_len_expand;
1852
1853 sdna->members_num = names_expand_len;
1854}
1855
1857 GHash *elem_map_alias_from_static,
1858 const char *struct_name_static,
1859 const char *elem_static_full)
1860{
1861 const int elem_static_full_len = strlen(elem_static_full);
1862 char *elem_static = static_cast<char *>(alloca(elem_static_full_len + 1));
1863 const int elem_static_len = DNA_member_id_strip_copy(elem_static, elem_static_full);
1864 const char *str_pair[2] = {struct_name_static, elem_static};
1865 const char *elem_alias = static_cast<const char *>(
1866 BLI_ghash_lookup(elem_map_alias_from_static, str_pair));
1867 if (elem_alias) {
1868 return DNA_member_id_rename(sdna->mem_arena,
1869 elem_static,
1870 elem_static_len,
1871 elem_alias,
1872 strlen(elem_alias),
1873 elem_static_full,
1874 elem_static_full_len,
1875 DNA_member_id_offset_start(elem_static_full));
1876 }
1877 return nullptr;
1878}
1879
1881{
1882 if (sdna->alias.members && sdna->alias.types) {
1883 return;
1884 }
1885
1886 /* We may want this to be optional later. */
1887 const bool use_legacy_hack = true;
1888
1889 if (sdna->mem_arena == nullptr) {
1891 }
1892
1895
1898
1899 if (sdna->alias.types == nullptr) {
1900 sdna->alias.types = MEM_malloc_arrayN<const char *>(size_t(sdna->types_num), __func__);
1901 for (int type_index = 0; type_index < sdna->types_num; type_index++) {
1902 const char *type_name_static = sdna->types[type_index];
1903
1904 if (use_legacy_hack) {
1905 type_name_static = DNA_struct_rename_legacy_hack_alias_from_static(type_name_static);
1906 }
1907
1908 sdna->alias.types[type_index] = static_cast<const char *>(BLI_ghash_lookup_default(
1909 type_map_alias_from_static, type_name_static, (void *)type_name_static));
1910 }
1911 }
1912
1913 if (sdna->alias.members == nullptr) {
1914 sdna_expand_names(sdna);
1915 sdna->alias.members = MEM_malloc_arrayN<const char *>(size_t(sdna->members_num), __func__);
1916 for (int struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1917 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1918 const char *struct_name_static = sdna->types[struct_info->type_index];
1919
1920 if (use_legacy_hack) {
1921 struct_name_static = DNA_struct_rename_legacy_hack_alias_from_static(struct_name_static);
1922 }
1923
1924 for (int a = 0; a < struct_info->members_num; a++) {
1925 const SDNA_StructMember *member = &struct_info->members[a];
1926 const char *member_alias_full = dna_sdna_alias_from_static_elem_full(
1927 sdna,
1929 struct_name_static,
1930 sdna->members[member->member_index]);
1931 if (member_alias_full != nullptr) {
1932 sdna->alias.members[member->member_index] = member_alias_full;
1933 }
1934 else {
1935 sdna->alias.members[member->member_index] = sdna->members[member->member_index];
1936 }
1937 }
1938 }
1939 }
1940 BLI_ghash_free(type_map_alias_from_static, nullptr, nullptr);
1942}
1943
1945{
1946 if (sdna->alias.types_to_structs_map) {
1947 return;
1948 }
1949
1951#ifdef WITH_DNA_GHASH
1952 /* create a ghash lookup to speed up */
1953 GHash *type_to_struct_index_map = BLI_ghash_str_new_ex(__func__, sdna->structs_num);
1954 for (intptr_t struct_index = 0; struct_index < sdna->structs_num; struct_index++) {
1955 const SDNA_Struct *struct_info = sdna->structs[struct_index];
1956 BLI_ghash_insert(type_to_struct_index_map,
1957 (void *)sdna->alias.types[struct_info->type_index],
1958 POINTER_FROM_INT(struct_index));
1959 }
1960 sdna->alias.types_to_structs_map = type_to_struct_index_map;
1961#else
1962 UNUSED_VARS(sdna);
1963#endif
1964}
1965
1966namespace blender::dna::pointers {
1967
1968PointersInDNA::PointersInDNA(const SDNA &sdna) : sdna_(sdna)
1969{
1970 structs_.resize(sdna.structs_num);
1971 for (const int struct_i : IndexRange(sdna.structs_num)) {
1972 const SDNA_Struct &sdna_struct = *sdna.structs[struct_i];
1973 StructInfo &struct_info = structs_[struct_i];
1974
1975 struct_info.size_in_bytes = 0;
1976 for (const int member_i : IndexRange(sdna_struct.members_num)) {
1977 struct_info.size_in_bytes += get_member_size_in_bytes(&sdna_,
1978 &sdna_struct.members[member_i]);
1979 }
1980
1981 this->gather_pointer_members_recursive(sdna_struct, 0, structs_[struct_i]);
1982 }
1983}
1984
1985void PointersInDNA::gather_pointer_members_recursive(const SDNA_Struct &sdna_struct,
1986 int initial_offset,
1987 StructInfo &r_struct_info) const
1988{
1989 int offset = initial_offset;
1990 for (const int member_i : IndexRange(sdna_struct.members_num)) {
1991 const SDNA_StructMember &member = sdna_struct.members[member_i];
1992 const char *member_type_name = sdna_.types[member.type_index];
1993 const eStructMemberCategory member_category = get_struct_member_category(&sdna_, &member);
1994 const int array_elem_num = sdna_.members_array_num[member.member_index];
1995
1996 if (member_category == STRUCT_MEMBER_CATEGORY_POINTER) {
1997 for (int elem_i = 0; elem_i < array_elem_num; elem_i++) {
1998 const char *member_name = sdna_.members[member.member_index];
1999 r_struct_info.pointers.append(
2000 {offset + elem_i * sdna_.pointer_size, member_type_name, member_name});
2001 }
2002 }
2003 else if (member_category == STRUCT_MEMBER_CATEGORY_STRUCT) {
2004 const int substruct_i = DNA_struct_find_index_without_alias(&sdna_, member_type_name);
2005 const SDNA_Struct &sub_sdna_struct = *sdna_.structs[substruct_i];
2006 int substruct_size = sdna_.types_size[member.type_index];
2007 for (int elem_i = 0; elem_i < array_elem_num; elem_i++) {
2008 this->gather_pointer_members_recursive(
2009 sub_sdna_struct, offset + elem_i * substruct_size, r_struct_info);
2010 }
2011 }
2012 offset += get_member_size_in_bytes(&sdna_, &member);
2013 }
2014}
2015
2016} // namespace blender::dna::pointers
2017
2019
2020/* -------------------------------------------------------------------- */
2024
2025namespace blender::dna {
2026
2027static void print_struct_array_recursive(const SDNA &sdna,
2028 const SDNA_Struct &sdna_struct,
2029 const void *initial_data,
2030 const int64_t element_num,
2031 const int indent,
2032 fmt::appender &dst);
2033static void print_single_struct_recursive(const SDNA &sdna,
2034 const SDNA_Struct &sdna_struct,
2035 const void *initial_data,
2036 const int indent,
2037 fmt::appender &dst);
2038
2042static bool char_array_startswith_simple_name(const char *data, const int array_len)
2043{
2044 const int string_length = strnlen(data, array_len);
2045 if (string_length == array_len) {
2046 return false;
2047 }
2048 for (const int i : IndexRange(string_length)) {
2049 const uchar c = data[i];
2050 /* This is only a very simple check and does not cover more complex cases with multi-byte UTF8
2051 * characters. It's only a heuristic anyway, making a wrong decision here just means that the
2052 * data will be printed differently. */
2053 if (!std::isprint(c)) {
2054 return false;
2055 }
2056 }
2057 return true;
2058}
2059
2060static void print_struct_array_recursive(const SDNA &sdna,
2061 const SDNA_Struct &sdna_struct,
2062 const void *data,
2063 const int64_t element_num,
2064 const int indent,
2065 fmt::appender &dst)
2066{
2067 if (element_num == 1) {
2068 print_single_struct_recursive(sdna, sdna_struct, data, indent, dst);
2069 return;
2070 }
2071
2072 const char *struct_name = sdna.types[sdna_struct.type_index];
2073 const int64_t struct_size = sdna.types_size[sdna_struct.type_index];
2074 for (const int64_t i : IndexRange(element_num)) {
2075 const void *element_data = POINTER_OFFSET(data, i * struct_size);
2076 fmt::format_to(dst, "{:{}}{}: <{}>\n", "", indent, i, struct_name);
2077 print_single_struct_recursive(sdna, sdna_struct, element_data, indent + 2, dst);
2078 }
2079}
2080
2081static void print_single_struct_recursive(const SDNA &sdna,
2082 const SDNA_Struct &sdna_struct,
2083 const void *initial_data,
2084 const int indent,
2085 fmt::appender &dst)
2086{
2087 using namespace blender;
2088 const void *data = initial_data;
2089
2090 for (const int member_i : IndexRange(sdna_struct.members_num)) {
2091 const SDNA_StructMember &member = sdna_struct.members[member_i];
2092 const char *member_type_name = sdna.types[member.type_index];
2093 const char *member_name = sdna.members[member.member_index];
2094 const eStructMemberCategory member_category = get_struct_member_category(&sdna, &member);
2095 const int member_array_len = sdna.members_array_num[member.member_index];
2096
2097 fmt::format_to(dst, "{:{}}{} {}:", "", indent, member_type_name, member_name);
2098
2099 if (member_category == STRUCT_MEMBER_CATEGORY_PRIMITIVE &&
2100 member.type_index == SDNA_TYPE_CHAR && member_array_len > 1)
2101 {
2102 const char *str_data = static_cast<const char *>(data);
2103 fmt::format_to(dst, " ");
2104 if (char_array_startswith_simple_name(str_data, member_array_len)) {
2105 fmt::format_to(dst, "'{}'", str_data);
2106 }
2107 else {
2108 for (const int i : IndexRange(member_array_len)) {
2109 fmt::format_to(dst, "{} ", int(str_data[i]));
2110 }
2111 }
2112 fmt::format_to(dst, "\n");
2113 }
2114 else {
2115 switch (member_category) {
2117 fmt::format_to(dst, "\n");
2118 const int substruct_i = DNA_struct_find_index_without_alias(&sdna, member_type_name);
2119 const SDNA_Struct &sub_sdna_struct = *sdna.structs[substruct_i];
2121 sdna, sub_sdna_struct, data, member_array_len, indent + 2, dst);
2122 break;
2123 }
2125 fmt::format_to(dst, " ");
2126 const int type_size = sdna.types_size[member.type_index];
2127 const eSDNA_Type type = eSDNA_Type(member.type_index);
2128 for ([[maybe_unused]] const int elem_i : IndexRange(member_array_len)) {
2129 const void *current_data = POINTER_OFFSET(data, elem_i * type_size);
2130 switch (type) {
2131 case SDNA_TYPE_CHAR: {
2132 const char value = *reinterpret_cast<const char *>(current_data);
2133 fmt::format_to(dst, "{}", int(value));
2134 break;
2135 }
2136 case SDNA_TYPE_UCHAR: {
2137 const uchar value = *reinterpret_cast<const uchar *>(current_data);
2138 fmt::format_to(dst, "{}", int(value));
2139 break;
2140 }
2141 case SDNA_TYPE_INT8: {
2142 fmt::format_to(dst, "{}", *reinterpret_cast<const int8_t *>(current_data));
2143 break;
2144 }
2145 case SDNA_TYPE_SHORT: {
2146 fmt::format_to(dst, "{}", *reinterpret_cast<const short *>(current_data));
2147 break;
2148 }
2149 case SDNA_TYPE_USHORT: {
2150 fmt::format_to(dst, "{}", *reinterpret_cast<const ushort *>(current_data));
2151 break;
2152 }
2153 case SDNA_TYPE_INT: {
2154 fmt::format_to(dst, "{}", *reinterpret_cast<const int *>(current_data));
2155 break;
2156 }
2157 case SDNA_TYPE_FLOAT: {
2158 fmt::format_to(dst, "{}", *reinterpret_cast<const float *>(current_data));
2159 break;
2160 }
2161 case SDNA_TYPE_DOUBLE: {
2162 fmt::format_to(dst, "{}", *reinterpret_cast<const double *>(current_data));
2163 break;
2164 }
2165 case SDNA_TYPE_INT64: {
2166 fmt::format_to(dst, "{}", *reinterpret_cast<const int64_t *>(current_data));
2167 break;
2168 }
2169 case SDNA_TYPE_UINT64: {
2170 fmt::format_to(dst, "{}", *reinterpret_cast<const uint64_t *>(current_data));
2171 break;
2172 }
2173 case SDNA_TYPE_RAW_DATA: {
2175 break;
2176 }
2177 }
2178 fmt::format_to(dst, " ");
2179 }
2180 fmt::format_to(dst, "\n");
2181 break;
2182 }
2184 for ([[maybe_unused]] const int elem_i : IndexRange(member_array_len)) {
2185 const void *current_data = POINTER_OFFSET(data, sdna.pointer_size * elem_i);
2186 fmt::format_to(dst, " {}", *reinterpret_cast<const void *const *>(current_data));
2187 }
2188 fmt::format_to(dst, "\n");
2189 break;
2190 }
2191 }
2192 }
2193 const int member_size = get_member_size_in_bytes(&sdna, &member);
2194 data = POINTER_OFFSET(data, member_size);
2195 }
2196}
2197
2199 const int struct_id,
2200 const void *initial_data,
2201 const void *address,
2202 const int64_t element_num,
2203 std::ostream &stream)
2204{
2205 const SDNA_Struct &sdna_struct = *sdna.structs[struct_id];
2206
2207 fmt::memory_buffer buf;
2208 fmt::appender dst{buf};
2209
2210 const char *struct_name = sdna.types[sdna_struct.type_index];
2211 fmt::format_to(dst, "<{}> {}x at {}\n", struct_name, element_num, address);
2212
2213 print_struct_array_recursive(sdna, sdna_struct, initial_data, element_num, 2, dst);
2214 stream << fmt::to_string(buf);
2215}
2216
2217void print_struct_by_id(const int struct_id, const void *data)
2218{
2219 const SDNA &sdna = *DNA_sdna_current_get();
2220 print_structs_at_address(sdna, struct_id, data, data, 1, std::cout);
2221}
2222
2223} // namespace blender::dna
2224
#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
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:45
eSDNA_Type
Definition DNA_genfile.h:33
@ SDNA_TYPE_CHAR
Definition DNA_genfile.h:34
@ SDNA_TYPE_RAW_DATA
Definition DNA_genfile.h:55
@ SDNA_TYPE_INT
Definition DNA_genfile.h:38
@ SDNA_TYPE_UINT64
Definition DNA_genfile.h:47
@ SDNA_TYPE_DOUBLE
Definition DNA_genfile.h:42
@ SDNA_TYPE_SHORT
Definition DNA_genfile.h:36
@ SDNA_TYPE_UCHAR
Definition DNA_genfile.h:35
@ SDNA_TYPE_INT8
Definition DNA_genfile.h:48
@ SDNA_TYPE_INT64
Definition DNA_genfile.h:46
@ SDNA_TYPE_FLOAT
Definition DNA_genfile.h:41
@ SDNA_TYPE_USHORT
Definition DNA_genfile.h:37
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:61
@ SDNA_CMP_EQUAL
Definition DNA_genfile.h:66
@ SDNA_CMP_REMOVED
Definition DNA_genfile.h:64
@ 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.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
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
SDNA * DNA_sdna_from_data(const void *data, const int data_len, bool data_alloc, const bool do_alias, const char **r_error_message)
bool DNA_struct_member_exists_with_alias(const SDNA *sdna, const char *stype, const char *vartype, const char *name)
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)
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)
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)
static bool init_structDNA(SDNA *sdna, const char **r_error_message)
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)
#define printf(...)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#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
const char * name
ReconstructStep ** steps
const char * compare_flags
struct ReconstructStep::@070214117165123021005026120246266015116247230365::@351271042175133212223171142267006177214106006367 substruct
eSDNA_Type old_type
union ReconstructStep::@070214117165123021005026120246266015116247230365 data
eReconstructStepType type
struct ReconstructStep::@070214117165123021005026120246266015116247230365::@221247067137127234270352111361234055247370066242 cast_primitive
struct ReconstructStep::@070214117165123021005026120246266015116247230365::@174261126310021233011270100126316371343304103071 cast_pointer
eSDNA_Type new_type
struct ReconstructStep::@070214117165123021005026120246266015116247230365::@344246050342044300060073214144026246245055225201 memcpy
SDNA_StructMember members[]
struct GHash * types_to_structs_map
const char ** members
int types_num
int structs_num
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
struct SDNA::@324261063051035105003300060127223210155361202367 alias
bool data_alloc
short * members_array_num
int data_size
i
Definition text_draw.cc:230
uint len
PointerRNA * ptr
Definition wm_files.cc:4238