Commit: 51e43f27fa2ecb5529d14cdfd1c73447dd420046 Author: Jacques Lucke Date: Thu Oct 8 18:17:12 2020 +0200 Branches: master https://developer.blender.org/rB51e43f27fa2ecb5529d14cdfd1c73447dd420046
DNA: cleanup endian switching when loading file This patch "modernizes" `DNA_struct_switch_endian` similar to how I updated `DNA_struct_reconstruct` recently. Furthermore, some special case handling have been moved to another place. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D9089 =================================================================== M source/blender/blenloader/intern/readfile.c M source/blender/makesdna/DNA_genfile.h M source/blender/makesdna/intern/dna_genfile.c =================================================================== diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cf2181c8a27..9465819a2d8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -766,7 +766,7 @@ static void switch_endian_bh8(BHead8 *bhead) } } -static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap) +static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, bool do_endian_swap) { BHead4 *bhead4 = (BHead4 *)bhead; int64_t old; @@ -859,7 +859,7 @@ static BHeadN *get_bhead(FileData *fd) } if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) { - bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN)); + bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0); } else { /* MIN2 is only to quiet '-Warray-bounds' compiler warning. */ @@ -2509,6 +2509,32 @@ static void direct_link_ipo(BlendDataReader *reader, Ipo *ipo) BLO_read_data_address(reader, &icu->bezt); BLO_read_data_address(reader, &icu->bp); BLO_read_data_address(reader, &icu->driver); + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&icu->blocktype); + if (icu->driver != NULL) { + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&icu->blocktype); + if (icu->driver != NULL) { + BLI_endian_switch_int16(&icu->driver->blocktype); + } + } + } + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&ipo->blocktype); + BLI_endian_switch_int16(&icu->driver->blocktype); + } + } + } + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&ipo->blocktype); } } diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index 96766bf16b8..6fcbc53d47b 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -103,7 +103,7 @@ void DNA_reconstruct_info_free(struct DNA_ReconstructInfo *reconstruct_info); int DNA_struct_find_nr_ex(const struct SDNA *sdna, const char *str, unsigned int *index_last); int DNA_struct_find_nr(const struct SDNA *sdna, const char *str); -void DNA_struct_switch_endian(const struct SDNA *oldsdna, int oldSDNAnr, char *data); +void DNA_struct_switch_endian(const struct SDNA *sdna, int struct_nr, char *data); const char *DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA *newsdna); void *DNA_struct_reconstruct(const struct DNA_ReconstructInfo *reconstruct_info, int old_struct_nr, diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index d7360c67210..1a107547450 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -980,92 +980,110 @@ static int elem_offset(const SDNA *sdna, return -1; } +/* Each struct member belongs to one of the categories below. */ +typedef enum eStructMemberCategory { + STRUCT_MEMBER_CATEGORY_STRUCT, + STRUCT_MEMBER_CATEGORY_PRIMITIVE, + STRUCT_MEMBER_CATEGORY_POINTER, +} eStructMemberCategory; + +static eStructMemberCategory get_struct_member_category(const SDNA *sdna, + const SDNA_StructMember *member) +{ + const char *member_name = sdna->names[member->name]; + if (ispointer(member_name)) { + return STRUCT_MEMBER_CATEGORY_POINTER; + } + const char *member_type_name = sdna->types[member->type]; + if (DNA_struct_find(sdna, member_type_name)) { + return STRUCT_MEMBER_CATEGORY_STRUCT; + } + return STRUCT_MEMBER_CATEGORY_PRIMITIVE; +} + +static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member) +{ + const char *name = sdna->names[member->name]; + const int array_length = sdna->names_array_len[member->name]; + if (ispointer(name)) { + return sdna->pointer_size * array_length; + } + const int type_size = sdna->types_size[member->type]; + return type_size * array_length; +} + /** * Does endian swapping on the fields of a struct value. * - * \param oldsdna: SDNA of Blender that saved file - * \param oldSDNAnr: Index of struct info within oldsdna - * \param data: Struct data + * \param sdna: SDNA of the struct_nr belongs to + * \param struct_nr: Index of struct info within sdna + * \param data: Struct data that is to be converted */ -void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data) +void DNA_struct_switch_endian(const SDNA *sdna, int struct_nr, char *data) { - /* Recursive! - * If element is a struct, call recursive. - */ - if (oldSDNAnr == -1) { + if (struct_nr == -1) { return; } - const int firststructtypenr = oldsdna->structs[0]->type; - const SDNA_Struct *struct_info = oldsdna->structs[oldSDNAnr]; - char *cur = data; - for (int a = 0; a < struct_info->members_len; a++) { - const SDNA_StructMember *member = &struct_info->members[a]; - const char *type = oldsdna->types[member->type]; - const char *name = oldsdna->names[member->name]; - const int old_name_array_len = oldsdna->names_array_len[member->name]; - - /* DNA_elem_size_nr = including arraysize */ - const int elen = DNA_elem_size_nr(oldsdna, member->type, member->name); - - /* test: is type a struct? */ - if (member->type >= firststructtypenr && !ispointer(name)) { - /* struct field type */ - /* where does the old data start (is there one?) */ - - const int data_offset = elem_offset(oldsdna, type, name, struct_info); - if (data_offset != -1) { - char *cpo = data + data_offset; - unsigned int oldsdna_index_last = UINT_MAX; - oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); - - int mul = old_name_array_len; - const int elena = elen / mul; - - while (mul--) { - DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo); - cpo += elena; + + const SDNA_Struct *struct_info = sdna->structs[struct_nr]; + + int offset_in_bytes = 0; + for (int member_index = 0; member_index < struct_info->members_len; member_index++) { + const SDNA_StructMember *member = &struct_info->members[member_index]; + const eStructMemberCategory member_category = get_struct_member_category(sdna, member); + char *member_data = data + offset_in_bytes; + const char *member_type_name = sdna->types[member->type]; + const int member_array_length = sdna->names_array_len[member->name]; + + switch (member_category) { + case STRUCT_MEMBER_CATEGORY_STRUCT: { + const int substruct_size = sdna->types_size[member->type]; + const int substruct_nr = DNA_struct_find_nr(sdna, member_type_name); + BLI_assert(substruct_nr != -1); + for (int a = 0; a < member_array_length; a++) { + DNA_struct_switch_endian(sdna, substruct_nr, member_data + a * substruct_size); } + break; } - } - else { - /* non-struct field type */ - if (ispointer(name)) { - /* See readfile.c (#bh4_from_bh8 swap endian argument), - * this is only done when reducing the size of a pointer from 4 to 8. */ - if (sizeof(void *) < 8) { - if (oldsdna->pointer_size == 8) { - BLI_endian_switch_int64_array((int64_t *)cur, old_name_array_len); + case STRUCT_MEMBER_CATEGORY_PRIMITIVE: { + switch (member->type) { + case SDNA_TYPE_SHORT: + case SDNA_TYPE_USHORT: { + BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length); + break; } - } - } - else { - if (ELEM(member->type, SDNA_TYPE_SHORT, SDNA_TYPE_USHORT)) { - - /* exception: variable called blocktype: derived from ID_ */ - bool skip = false; - if (name[0] == 'b' && name[1] == 'l') { - if (STREQ(name, "blocktype")) { - skip = true; - } + case SDNA_TYPE_INT: + case SDNA_TYPE_FLOAT: { + /* Note, intentionally ignore long/ulong, because these could be 4 or 8 bytes. + * Fortunately, we only use these types for runtime variables and only once for a + * struct type that is no longer used. */ + BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length); + break; } - - if (skip == false) { - BLI_endian_switch_int16_array((int16_t *)cur, old_name_array_len); + case SDNA_TYPE_INT64: + case SDNA_TYPE_UINT64: + case SDNA_TYPE_DOUBLE: { + BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length); + break; + } + default: { + break; } } - else if (ELEM(member->type, SDNA_TYPE_INT, SDNA_TYPE_FLOAT)) { - /* note, intentionally ignore long/ulong here these could be 4 or 8 bits, - * but turns out we only used for runtime vars and - * only once for a struct type that's no longer used. */ - - BLI_endian_switch_int32_array((int32_t *)cur, old_name_array_len); - } - else if (ELEM(member->type, SDNA_TYPE_INT64, SDNA_TYPE_UINT64, SDNA_TYPE_DOUBLE)) { - BLI_endian_switch_int64_array((int64_t *)cur, old_name_array_len); + break; + } + case STRUCT_MEMBER_CATEGORY_POINTER: { + /* See readfile.c (#bh4_from_bh8 swap endian argument), + * this is only done when reducing the size of a pointer from 4 to 8. */ + if (sizeof(void *) < 8) { + if (sdna->pointer_size == 8) { + BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length); + } } + break; } } - cur += elen; + offset_in_bytes += get_member_size_in_bytes(sdna, member); } } @@ -1235,38 +1253,6 @@ void *DNA_struct_reconstruct(c @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs