Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
commit9186b9ae4806f4bbc1a14417c408e844f8e8cc1a (patch)
tree117bbd4ace75825e3a65f0ba2a447509bde0df85 /source/blender/makesdna/intern
parentcfbd605567f48229a923df382baf6db98fbafc61 (diff)
parent9946cca14676bf07b3c7c103e99033fe1e4e423e (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/makesdna/intern')
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c307
2 files changed, 168 insertions, 141 deletions
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 0bb6e866bf4..8c758c33dc5 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -52,6 +52,8 @@ endif()
# SRC_DNA_INC is defined in the parent dir
+add_cc_flags_custom_test(makesdna)
+
add_executable(makesdna ${SRC} ${SRC_DNA_INC})
# Output dna.c
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 9135d7bab7d..4db98bda7dd 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
@@ -133,39 +134,6 @@
*
*/
-/* ************************* ENDIAN STUFF ********************** */
-
-/**
- * converts a short between big/little endian.
- */
-static short le_short(short temp)
-{
- short new;
- char *rt = (char *)&temp, *rtn = (char *)&new;
-
- rtn[0] = rt[1];
- rtn[1] = rt[0];
-
- return new;
-}
-
-/**
- * converts an int between big/little endian.
- */
-static int le_int(int temp)
-{
- int new;
- char *rt = (char *)&temp, *rtn = (char *)&new;
-
- rtn[0] = rt[3];
- rtn[1] = rt[2];
- rtn[2] = rt[1];
- rtn[3] = rt[0];
-
- return new;
-}
-
-
/* ************************* MAKE DNA ********************** */
/* allowed duplicate code from makesdna.c */
@@ -280,37 +248,16 @@ static void printstruct(SDNA *sdna, short strnr)
#endif
/**
- * Returns a pointer to the start of the struct info for the struct with the specified name.
- */
-static short *findstruct_name(SDNA *sdna, const char *str)
-{
- int a;
- short *sp = NULL;
-
-
- for (a = 0; a < sdna->nr_structs; a++) {
-
- sp = sdna->structs[a];
-
- if (strcmp(sdna->types[sp[0]], str) == 0) {
- return sp;
- }
- }
-
- return NULL;
-}
-
-/**
* Returns the index of the struct info for the struct with the specified name.
*/
-int DNA_struct_find_nr(SDNA *sdna, const char *str)
+int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
{
const short *sp = NULL;
- if (sdna->lastfind < sdna->nr_structs) {
- sp = sdna->structs[sdna->lastfind];
+ if (*index_last < sdna->nr_structs) {
+ sp = sdna->structs[*index_last];
if (strcmp(sdna->types[sp[0]], str) == 0) {
- return sdna->lastfind;
+ return *index_last;
}
}
@@ -323,7 +270,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
if (index_p) {
a = GET_INT_FROM_POINTER(*index_p);
- sdna->lastfind = a;
+ *index_last = a;
}
else {
a = -1;
@@ -339,7 +286,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
sp = sdna->structs[a];
if (strcmp(sdna->types[sp[0]], str) == 0) {
- sdna->lastfind = a;
+ *index_last = a;
return a;
}
}
@@ -348,26 +295,51 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
#endif
}
+int DNA_struct_find_nr(const SDNA *sdna, const char *str)
+{
+ unsigned int index_last_dummy = UINT_MAX;
+ return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy);
+}
+
/* ************************* END DIV ********************** */
/* ************************* READ DNA ********************** */
+BLI_INLINE const char *pad_up_4(const char *ptr)
+{
+ return (const char *)((((uintptr_t)ptr) + 3) & ~3);
+}
+
/**
* In sdna->data the data, now we convert that to something understandable
*/
-static void init_structDNA(SDNA *sdna, bool do_endian_swap)
+static bool init_structDNA(
+ SDNA *sdna, bool do_endian_swap,
+ const char **r_error_message)
{
int *data, *verg, gravity_fix = -1;
- intptr_t nr;
short *sp;
- char str[8], *cp;
+ 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) {
-
+ if (*data != *verg) {
+ *r_error_message = "SDNA error in SDNA file";
+ return false;
+ }
+ else {
+ const char *cp;
+
data++;
/* load names array */
@@ -375,20 +347,21 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
if (*data == *verg) {
data++;
- if (do_endian_swap) sdna->nr_names = le_int(*data);
- else sdna->nr_names = *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 {
- printf("NAME error in SDNA file\n");
- return;
+ *r_error_message = "NAME error in SDNA file";
+ return false;
}
- nr = 0;
cp = (char *)data;
- while (nr < sdna->nr_names) {
+ for (int nr = 0; nr < sdna->nr_names; nr++) {
sdna->names[nr] = cp;
/* "float gravity [3]" was parsed wrong giving both "gravity" and
@@ -403,32 +376,31 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
while (*cp) cp++;
cp++;
- nr++;
}
- nr = (intptr_t)cp; /* prevent BUS error */
- nr = (nr + 3) & ~3;
- cp = (char *)nr;
+
+ cp = pad_up_4(cp);
/* load type names array */
data = (int *)cp;
strcpy(str, "TYPE");
if (*data == *verg) {
data++;
-
- if (do_endian_swap) sdna->nr_types = le_int(*data);
- else sdna->nr_types = *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 {
- printf("TYPE error in SDNA file\n");
- return;
+ *r_error_message = "TYPE error in SDNA file";
+ return false;
}
- nr = 0;
cp = (char *)data;
- while (nr < sdna->nr_types) {
+ 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 */
@@ -441,11 +413,9 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
while (*cp) cp++;
cp++;
- nr++;
}
- nr = (intptr_t)cp; /* prevent BUS error */
- nr = (nr + 3) & ~3;
- cp = (char *)nr;
+
+ cp = pad_up_4(cp);
/* load typelen array */
data = (int *)cp;
@@ -456,20 +426,14 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->typelens = sp;
if (do_endian_swap) {
- short a, *spo = sp;
-
- a = sdna->nr_types;
- while (a--) {
- spo[0] = le_short(spo[0]);
- spo++;
- }
+ BLI_endian_switch_int16_array(sp, sdna->nr_types);
}
sp += sdna->nr_types;
}
else {
- printf("TLEN error in SDNA file\n");
- return;
+ *r_error_message = "TLEN error in SDNA file";
+ return false;
}
if (sdna->nr_types & 1) sp++; /* prevent BUS error */
@@ -479,74 +443,90 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
if (*data == *verg) {
data++;
- if (do_endian_swap) sdna->nr_structs = le_int(*data);
- else sdna->nr_structs = *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 {
- printf("STRC error in SDNA file\n");
- return;
+ *r_error_message = "STRC error in SDNA file";
+ return false;
}
- nr = 0;
sp = (short *)data;
- while (nr < sdna->nr_structs) {
+ for (int nr = 0; nr < sdna->nr_structs; nr++) {
sdna->structs[nr] = sp;
if (do_endian_swap) {
short a;
- sp[0] = le_short(sp[0]);
- sp[1] = le_short(sp[1]);
+ BLI_endian_switch_int16(&sp[0]);
+ BLI_endian_switch_int16(&sp[1]);
a = sp[1];
sp += 2;
while (a--) {
- sp[0] = le_short(sp[0]);
- sp[1] = le_short(sp[1]);
+ BLI_endian_switch_int16(&sp[0]);
+ BLI_endian_switch_int16(&sp[1]);
sp += 2;
}
}
else {
sp += 2 * sp[1] + 2;
}
-
- nr++;
}
+ }
- /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
- sp = findstruct_name(sdna, "ListBase");
- /* 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)) {
- printf("ListBase struct error! Needs it to calculate pointerize.\n");
- exit(1);
- /* well, at least sizeof(ListBase) is error proof! (ton) */
- }
-
+ {
/* second part of gravity problem, setting "gravity" type to void */
if (gravity_fix > -1) {
- for (nr = 0; nr < sdna->nr_structs; nr++) {
+ 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 (nr = 0; nr < sdna->nr_structs; nr++) {
+ for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
- BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(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;
}
/**
@@ -554,11 +534,11 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
*/
SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
- bool do_endian_swap, bool data_alloc)
+ bool do_endian_swap, bool data_alloc,
+ const char **r_error_message)
{
SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
-
- sdna->lastfind = 0;
+ const char *error_message = NULL;
sdna->datalen = datalen;
if (data_alloc) {
@@ -571,9 +551,44 @@ SDNA *DNA_sdna_from_data(
}
sdna->data_alloc = data_alloc;
- init_structDNA(sdna, do_endian_swap);
-
- return sdna;
+
+ if (init_structDNA(sdna, do_endian_swap, &error_message)) {
+ return sdna;
+ }
+ else {
+ if (r_error_message == NULL) {
+ fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
+ }
+ else {
+ *r_error_message = error_message;
+ }
+ DNA_sdna_free(sdna);
+ return NULL;
+ }
+}
+
+/**
+ * Using globals is acceptable here, the data is read-only and only changes between Blender versions.
+ *
+ * So it is safe to create once and reuse.
+ */
+static SDNA *g_sdna = NULL;
+
+void DNA_sdna_current_init(void)
+{
+ g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL);
+}
+
+const struct SDNA *DNA_sdna_current_get(void)
+{
+ BLI_assert(g_sdna != NULL);
+ return g_sdna;
+}
+
+void DNA_sdna_current_free(void)
+{
+ DNA_sdna_free(g_sdna);
+ g_sdna = NULL;
}
/* ******************** END READ DNA ********************** */
@@ -623,7 +638,7 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn
* - 1 Struct is the same (can be loaded with straight memory copy after any necessary endian conversion)
* - 2 Struct is different in some way (needs to be copied/converted field by field)
*/
-char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna)
+char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
{
int a, b;
const short *sp_old, *sp_new;
@@ -640,14 +655,19 @@ char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna)
/* we check all structs in 'oldsdna' and compare them with
* the structs in 'newsdna'
*/
+ unsigned int newsdna_index_last = 0;
for (a = 0; a < oldsdna->nr_structs; a++) {
sp_old = oldsdna->structs[a];
/* search for type in cur */
- sp_new = findstruct_name(newsdna, oldsdna->types[sp_old[0]]);
-
- if (sp_new) {
+ int sp_new_index = DNA_struct_find_nr_ex(newsdna, oldsdna->types[sp_old[0]], &newsdna_index_last);
+
+ /* The next indices will almost always match */
+ newsdna_index_last++;
+
+ if (sp_new_index != -1) {
+ sp_new = newsdna->structs[sp_new_index];
/* initial assumption */
compflags[a] = SDNA_CMP_NOT_EQUAL;
@@ -1037,8 +1057,8 @@ static void reconstruct_elem(
* \param cur Where to put converted struct contents
*/
static void reconstruct_struct(
- SDNA *newsdna,
- SDNA *oldsdna,
+ const SDNA *newsdna,
+ const SDNA *oldsdna,
const char *compflags,
int oldSDNAnr,
@@ -1056,6 +1076,10 @@ static void reconstruct_struct(
char *cpo, *cpc;
const char *name, *nameo;
+ unsigned int oldsdna_index_last = UINT_MAX;
+ unsigned int cursdna_index_last = UINT_MAX;
+
+
if (oldSDNAnr == -1) return;
if (curSDNAnr == -1) return;
@@ -1090,8 +1114,8 @@ static void reconstruct_struct(
cpo = find_elem(oldsdna, type, name, spo, data, &sppo);
if (cpo) {
- oldSDNAnr = DNA_struct_find_nr(oldsdna, type);
- curSDNAnr = DNA_struct_find_nr(newsdna, type);
+ oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last);
+ curSDNAnr = DNA_struct_find_nr_ex(newsdna, type, &cursdna_index_last);
/* array! */
mul = DNA_elem_array_size(name);
@@ -1132,7 +1156,7 @@ static void reconstruct_struct(
* \param oldSDNAnr Index of struct info within oldsdna
* \param data Struct data
*/
-void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
+void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data)
{
/* Recursive!
* If element is a struct, call recursive.
@@ -1141,6 +1165,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
const short *spo, *spc;
char *cur;
const char *type, *name;
+ unsigned int oldsdna_index_last = UINT_MAX;
if (oldSDNAnr == -1) return;
firststructtypenr = *(oldsdna->structs[0]);
@@ -1165,7 +1190,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
/* where does the old data start (is there one?) */
char *cpo = find_elem(oldsdna, type, name, spo, data, NULL);
if (cpo) {
- oldSDNAnr = DNA_struct_find_nr(oldsdna, type);
+ oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last);
mul = DNA_elem_array_size(name);
elena = elen / mul;
@@ -1223,7 +1248,9 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
* \param data Array of struct data
* \return An allocated reconstructed struct
*/
-void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
+void *DNA_struct_reconstruct(
+ const SDNA *newsdna, const SDNA *oldsdna,
+ char *compflags, int oldSDNAnr, int blocks, void *data)
{
int a, curSDNAnr, curlen = 0, oldlen;
const short *spo, *spc;
@@ -1263,7 +1290,6 @@ void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int
*/
int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
{
-
const int SDNAnr = DNA_struct_find_nr(sdna, stype);
const short * const spo = sdna->structs[SDNAnr];
const char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
@@ -1273,7 +1299,6 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch
bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name)
{
-
const int SDNAnr = DNA_struct_find_nr(sdna, stype);
if (SDNAnr != -1) {