void BLI_endian_switch_int32_array(int *val, const int size) { if (size > 0) { int i = size; val = val + (size - 1); while (i--) { BLI_endian_switch_int32(val--); } } }
struct anim_index *IMB_indexer_open(const char *name) { char header[13]; struct anim_index *idx; FILE *fp = BLI_fopen(name, "rb"); int i; if (!fp) { return NULL; } if (fread(header, 12, 1, fp) != 1) { fclose(fp); return NULL; } header[12] = 0; if (memcmp(header, magic, 8) != 0) { fclose(fp); return NULL; } if (atoi(header + 9) != INDEX_FILE_VERSION) { fclose(fp); return NULL; } idx = MEM_callocN(sizeof(struct anim_index), "anim_index"); BLI_strncpy(idx->name, name, sizeof(idx->name)); fseek(fp, 0, SEEK_END); idx->num_entries = (ftell(fp) - 12) / (sizeof(int) + /* framepos */ sizeof(unsigned long long) + /* seek_pos */ sizeof(unsigned long long) + /* seek_pos_dts */ sizeof(unsigned long long) /* pts */ ); fseek(fp, 12, SEEK_SET); idx->entries = MEM_callocN(sizeof(struct anim_index_entry) * idx->num_entries, "anim_index_entries"); for (i = 0; i < idx->num_entries; i++) { fread(&idx->entries[i].frameno, sizeof(int), 1, fp); fread(&idx->entries[i].seek_pos, sizeof(unsigned long long), 1, fp); fread(&idx->entries[i].seek_pos_dts, sizeof(unsigned long long), 1, fp); fread(&idx->entries[i].pts, sizeof(unsigned long long), 1, fp); } if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) { for (i = 0; i < idx->num_entries; i++) { BLI_endian_switch_int32(&idx->entries[i].frameno); BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos); BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts); BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts); } } fclose(fp); return idx; }
/** * In sdna->data the data, now we convert that to something understandable */ static bool init_structDNA( SDNA *sdna, bool do_endian_swap, const char **r_error_message) { int *data, *verg, gravity_fix = -1; short *sp; char str[8]; verg = (int *)str; data = (int *)sdna->data; /* clear pointers incase of error */ sdna->names = NULL; sdna->types = NULL; sdna->structs = NULL; #ifdef WITH_DNA_GHASH sdna->structs_map = NULL; #endif strcpy(str, "SDNA"); if (*data != *verg) { *r_error_message = "SDNA error in SDNA file"; return false; } else { const char *cp; data++; /* load names array */ strcpy(str, "NAME"); if (*data == *verg) { data++; sdna->nr_names = *data; if (do_endian_swap) { BLI_endian_switch_int32(&sdna->nr_names); } data++; sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames"); } else { *r_error_message = "NAME error in SDNA file"; return false; } cp = (char *)data; for (int nr = 0; nr < sdna->nr_names; nr++) { sdna->names[nr] = cp; /* "float gravity [3]" was parsed wrong giving both "gravity" and * "[3]" members. we rename "[3]", and later set the type of * "gravity" to "void" so the offsets work out correct */ if (*cp == '[' && strcmp(cp, "[3]") == 0) { if (nr && strcmp(sdna->names[nr - 1], "Cvi") == 0) { sdna->names[nr] = "gravity[3]"; gravity_fix = nr; } } while (*cp) cp++; cp++; } cp = pad_up_4(cp); /* load type names array */ data = (int *)cp; strcpy(str, "TYPE"); if (*data == *verg) { data++; sdna->nr_types = *data; if (do_endian_swap) { BLI_endian_switch_int32(&sdna->nr_types); } data++; sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes"); } else { *r_error_message = "TYPE error in SDNA file"; return false; } cp = (char *)data; for (int nr = 0; nr < sdna->nr_types; nr++) { sdna->types[nr] = cp; /* this is a patch, to change struct names without a conflict with SDNA */ /* be careful to use it, in this case for a system-struct (opengl/X) */ if (*cp == 'b') { /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */ if (strcmp("bScreen", cp) == 0) sdna->types[nr] = cp + 1; } while (*cp) cp++; cp++; } cp = pad_up_4(cp); /* load typelen array */ data = (int *)cp; strcpy(str, "TLEN"); if (*data == *verg) { data++; sp = (short *)data; sdna->typelens = sp; if (do_endian_swap) { BLI_endian_switch_int16_array(sp, sdna->nr_types); } sp += sdna->nr_types; } else { *r_error_message = "TLEN error in SDNA file"; return false; } if (sdna->nr_types & 1) sp++; /* prevent BUS error */ /* load struct array */ data = (int *)sp; strcpy(str, "STRC"); if (*data == *verg) { data++; sdna->nr_structs = *data; if (do_endian_swap) { BLI_endian_switch_int32(&sdna->nr_structs); } data++; sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs"); } else { *r_error_message = "STRC error in SDNA file"; return false; } sp = (short *)data; for (int nr = 0; nr < sdna->nr_structs; nr++) { sdna->structs[nr] = sp; if (do_endian_swap) { short a; BLI_endian_switch_int16(&sp[0]); BLI_endian_switch_int16(&sp[1]); a = sp[1]; sp += 2; while (a--) { BLI_endian_switch_int16(&sp[0]); BLI_endian_switch_int16(&sp[1]); sp += 2; } } else { sp += 2 * sp[1] + 2; } } } { /* second part of gravity problem, setting "gravity" type to void */ if (gravity_fix > -1) { for (int nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) sp[10] = SDNA_TYPE_VOID; } } } #ifdef WITH_DNA_GHASH { /* create a ghash lookup to speed up */ sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs); for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], SET_INT_IN_POINTER(nr)); } } #endif /* Calculate 'sdna->pointerlen' */ { intptr_t nr = DNA_struct_find_nr(sdna, "ListBase"); /* should never happen, only with corrupt file for example */ if (UNLIKELY(nr == -1)) { *r_error_message = "ListBase struct error! Not found."; return false; } /* finally pointerlen: use struct ListBase to test it, never change the size of it! */ sp = sdna->structs[nr]; /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */ sdna->pointerlen = sdna->typelens[sp[0]] / 2; if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) { *r_error_message = "ListBase struct error! Needs it to calculate pointerize."; /* well, at least sizeof(ListBase) is error proof! (ton) */ return false; } } return true; }