[Bf-blender-cvs] [51e43f27fa2] master: DNA: cleanup endian switching when loading file

Jacques Lucke noreply at git.blender.org
Thu Oct 8 18:18:38 CEST 2020


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. @@



More information about the Bf-blender-cvs mailing list