use ghash for DNA_struct_find_nr(), gives ~18% speedup on loading sintel lite, will...
[blender.git] / source / blender / makesdna / intern / dna_genfile.c
1 /* dna_genfile.c
2  *
3  * Functions for struct-dna, the genetic file dot c!
4  *
5  * $Id$
6  *
7  * ***** BEGIN GPL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  * DNA handling
32  */
33
34 /** \file blender/makesdna/intern/dna_genfile.c
35  *  \ingroup DNA
36  */
37
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
44
45 #ifdef WITH_DNA_GHASH
46 #  include "BLI_ghash.h"
47 #endif
48
49 #include "DNA_genfile.h"
50 #include "DNA_sdna_types.h" // for SDNA ;-)
51
52
53 /* gcc 4.1 on mingw was complaining that __int64 was already defined
54 actually is saw the line below as typedef long long long long... 
55 Anyhow, since its already defined, its safe to do an ifndef here- Campbell */
56 #ifdef FREE_WINDOWS
57 #ifndef __int64
58 typedef long long __int64;
59 #endif
60 #endif
61
62 /*
63  * - please note: no builtin security to detect input of double structs
64  * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>)
65
66 Structure DNA data is added to each blender file and to each executable, this to detect
67 in .blend files new veriables in structs, changed array sizes, etc. It's also used for
68 converting endian and pointer size (32-64 bits)
69 As an extra, Python uses a call to detect run-time the contents of a blender struct.
70
71 Create a structDNA: only needed when one of the input include (.h) files change.
72 File Syntax:
73         SDNA (4 bytes) (magic number)
74         NAME (4 bytes)
75         <nr> (4 bytes) amount of names (int)
76         <string> 
77         <string>
78         ...
79         ...
80         TYPE (4 bytes)
81         <nr> amount of types (int)
82         <string>
83         <string>
84         ...
85         ...
86         TLEN (4 bytes)
87         <len> (short) the lengths of types
88         <len>
89         ...
90         ...
91         STRC (4 bytes)
92         <nr> amount of structs (int)
93         <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
94         
95 !!Remember to read/write integer and short aligned!!
96
97  While writing a file, the names of a struct is indicated with a type number,
98  to be found with: type= findstruct_nr(SDNA *, char *)
99  The value of 'type' corresponds with the the index within the structs array
100
101  For the moment: the complete DNA file is included in a .blend file. For
102  the future we can think of smarter methods, like only included the used
103  structs. Only needed to keep a file short though...
104
105 ALLOWED AND TESTED CHANGES IN STRUCTS:
106  - type change (a char to float will be divided by 255)
107  - location within a struct (everthing can be randomly mixed up)
108  - struct within struct (within struct etc), this is recursive
109  - adding new elements, will be default initialized zero
110  - remving elements
111  - change of array sizes
112  - change of a pointer type: when the name doesn't change the contents is copied
113
114 NOT YET:
115  - array (vec[3]) to float struct (vec3f)
116
117 DONE:
118  - endian compatibility
119  - pointer conversion (32-64 bits)
120
121 IMPORTANT:
122  - do not use #defines in structs for array lengths, this cannot be read by the dna functions
123  - do not use uint, but unsigned int instead, ushort and ulong are allowed
124  - only use a long in Blender if you want this to be the size of a pointer. so it is
125    32 bits or 64 bits, dependant at the cpu architecture
126  - chars are always unsigned
127  - aligment of variables has to be done in such a way, that any system does
128    not create 'padding' (gaps) in structures. So make sure that:
129    - short: 2 aligned
130    - int: 4 aligned
131    - float: 4 aligned
132    - double: 8 aligned
133    - long: 8 aligned
134    - struct: 8 aligned
135  - the sdna functions have several error prints builtin, always check blender running from a console.
136  
137 */
138
139 /* local */
140 static int le_int(int temp);
141 static short le_short(short temp);
142
143 /* ************************* ENDIAN STUFF ********************** */
144
145 static short le_short(short temp)
146 {
147         short new;
148         char *rt=(char *)&temp, *rtn=(char *)&new;
149
150         rtn[0]= rt[1];
151         rtn[1]= rt[0];
152
153         return new;
154 }
155
156
157 static int le_int(int temp)
158 {
159         int new;
160         char *rt=(char *)&temp, *rtn=(char *)&new;
161
162         rtn[0]= rt[3];
163         rtn[1]= rt[2];
164         rtn[2]= rt[1];
165         rtn[3]= rt[0];
166
167         return new;
168 }
169
170
171 /* ************************* MAKE DNA ********************** */
172
173 /* allowed duplicate code from makesdna.c */
174 int DNA_elem_array_size(const char *astr, int len)
175 {
176         int a, mul=1;
177         char str[100], *cp= NULL;
178
179         memcpy(str, astr, len+1);
180
181         for(a=0; a<len; a++) {
182                 if( str[a]== '[' ) {
183                         cp= &(str[a+1]);
184                 }
185                 else if( str[a]==']' && cp) {
186                         str[a]= 0;
187                         mul*= atoi(cp);
188                 }
189         }
190
191         return mul;
192 }
193
194 /* ************************* END MAKE DNA ********************** */
195
196 /* ************************* DIV ********************** */
197
198 void DNA_sdna_free(SDNA *sdna)
199 {
200         MEM_freeN(sdna->data);
201         MEM_freeN((void *)sdna->names);
202         MEM_freeN(sdna->types);
203         MEM_freeN(sdna->structs);
204
205 #ifdef WITH_DNA_GHASH
206         BLI_ghash_free(sdna->structs_map, NULL, NULL);
207 #endif
208
209         MEM_freeN(sdna);
210 }
211
212 static int ispointer(const char *name)
213 {
214         /* check if pointer or function pointer */
215         return (name[0]=='*' || (name[0]=='(' && name[1]=='*'));
216 }
217
218 static int elementsize(SDNA *sdna, short type, short name)
219 /* call with numbers from struct-array */
220 {
221         int mul, namelen, len;
222         const char *cp;
223         
224         cp= sdna->names[name];
225         len= 0;
226         
227         namelen= strlen(cp);
228         /* is it a pointer or function pointer? */
229         if(ispointer(cp)) {
230                 /* has the naam an extra length? (array) */
231                 mul= 1;
232                 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen);
233                 
234                 len= sdna->pointerlen*mul;
235         }
236         else if( sdna->typelens[type] ) {
237                 /* has the naam an extra length? (array) */
238                 mul= 1;
239                 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen);
240                 
241                 len= mul*sdna->typelens[type];
242                 
243         }
244         
245         return len;
246 }
247
248 #if 0
249 static void printstruct(SDNA *sdna, short strnr)
250 {
251         /* is for debug */
252         int b, nr;
253         short *sp;
254         
255         sp= sdna->structs[strnr];
256         
257         printf("struct %s\n", sdna->types[ sp[0] ]);
258         nr= sp[1];
259         sp+= 2;
260         
261         for(b=0; b< nr; b++, sp+= 2) {
262                 printf("   %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]);
263         }
264 }
265 #endif
266
267 static short *findstruct_name(SDNA *sdna, const char *str)
268 {
269         int a;
270         short *sp= NULL;
271
272
273         for(a=0; a<sdna->nr_structs; a++) {
274
275                 sp= sdna->structs[a];
276                 
277                 if(strcmp( sdna->types[ sp[0] ], str )==0) return sp;
278         }
279         
280         return NULL;
281 }
282
283 int DNA_struct_find_nr(SDNA *sdna, const char *str)
284 {
285         short *sp= NULL;
286
287         if(sdna->lastfind<sdna->nr_structs) {
288                 sp= sdna->structs[sdna->lastfind];
289                 if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind;
290         }
291
292 #ifdef WITH_DNA_GHASH
293         return (intptr_t)BLI_ghash_lookup(sdna->structs_map, str) - 1;
294 #else
295         {
296                 int a;
297
298                 for(a=0; a<sdna->nr_structs; a++) {
299
300                         sp= sdna->structs[a];
301
302                         if(strcmp( sdna->types[ sp[0] ], str )==0) {
303                                 sdna->lastfind= a;
304                                 return a;
305                         }
306                 }
307         }
308         return -1;
309 #endif
310 }
311
312 /* ************************* END DIV ********************** */
313
314 /* ************************* READ DNA ********************** */
315
316 static void init_structDNA(SDNA *sdna, int do_endian_swap)
317 /* in sdna->data the data, now we convert that to something understandable */
318 {
319         int *data, *verg, gravity_fix= -1;
320         intptr_t nr;
321         short *sp;
322         char str[8], *cp;
323         
324         verg= (int *)str;
325         data= (int *)sdna->data;
326
327         strcpy(str, "SDNA");
328         if( *data == *verg ) {
329         
330                 data++;
331                 
332                 /* load names array */
333                 strcpy(str, "NAME");
334                 if( *data == *verg ) {
335                         data++;
336                         
337                         if(do_endian_swap) sdna->nr_names= le_int(*data);
338                         else sdna->nr_names= *data;
339                         
340                         data++;
341                         sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames");
342                 }
343                 else {
344                         printf("NAME error in SDNA file\n");
345                         return;
346                 }
347                 
348                 nr= 0;
349                 cp= (char *)data;
350                 while(nr<sdna->nr_names) {
351                         sdna->names[nr]= cp;
352
353                         /* "float gravity [3]" was parsed wrong giving both "gravity" and
354                            "[3]"  members. we rename "[3]", and later set the type of
355                            "gravity" to "void" so the offsets work out correct */
356                         if(*cp == '[' && strcmp(cp, "[3]")==0) {
357                                 if(nr && strcmp(sdna->names[nr-1], "Cvi") == 0) {
358                                         sdna->names[nr]= "gravity[3]";
359                                         gravity_fix= nr;
360                                 }
361                         }
362
363                         while( *cp) cp++;
364                         cp++;
365                         nr++;
366                 }
367                 nr= (intptr_t)cp;               /* prevent BUS error */
368                 nr= (nr+3) & ~3;
369                 cp= (char *)nr;
370                 
371                 /* load type names array */
372                 data= (int *)cp;
373                 strcpy(str, "TYPE");
374                 if( *data == *verg ) {
375                         data++;
376                         
377                         if(do_endian_swap) sdna->nr_types= le_int(*data);
378                         else sdna->nr_types= *data;
379                         
380                         data++;
381                         sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes");
382                 }
383                 else {
384                         printf("TYPE error in SDNA file\n");
385                         return;
386                 }
387                 
388                 nr= 0;
389                 cp= (char *)data;
390                 while(nr<sdna->nr_types) {
391                         sdna->types[nr]= cp;
392                         
393                         /* this is a patch, to change struct names without a confict with SDNA */
394                         /* be careful to use it, in this case for a system-struct (opengl/X) */
395                         
396                         if( *cp == 'b') {
397                                 /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
398                                 if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1;
399                         }
400                         
401                         while( *cp) cp++;
402                         cp++;
403                         nr++;
404                 }
405                 nr= (intptr_t)cp;               /* prevent BUS error */
406                 nr= (nr+3) & ~3;
407                 cp= (char *)nr;
408                 
409                 /* load typelen array */
410                 data= (int *)cp;
411                 strcpy(str, "TLEN");
412                 if( *data == *verg ) {
413                         data++;
414                         sp= (short *)data;
415                         sdna->typelens= sp;
416                         
417                         if(do_endian_swap) {
418                                 short a, *spo= sp;
419                                 
420                                 a= sdna->nr_types;
421                                 while(a--) {
422                                         spo[0]= le_short(spo[0]);
423                                         spo++;
424                                 }
425                         }
426                         
427                         sp+= sdna->nr_types;
428                 }
429                 else {
430                         printf("TLEN error in SDNA file\n");
431                         return;
432                 }
433                 if(sdna->nr_types & 1) sp++;    /* prevent BUS error */
434
435                 /* load struct array */
436                 data= (int *)sp;
437                 strcpy(str, "STRC");
438                 if( *data == *verg ) {
439                         data++;
440                         
441                         if(do_endian_swap) sdna->nr_structs= le_int(*data);
442                         else sdna->nr_structs= *data;
443                         
444                         data++;
445                         sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs");
446                 }
447                 else {
448                         printf("STRC error in SDNA file\n");
449                         return;
450                 }
451                 
452                 nr= 0;
453                 sp= (short *)data;
454                 while(nr<sdna->nr_structs) {
455                         sdna->structs[nr]= sp;
456                         
457                         if(do_endian_swap) {
458                                 short a;
459                                 
460                                 sp[0]= le_short(sp[0]);
461                                 sp[1]= le_short(sp[1]);
462                                 
463                                 a= sp[1];
464                                 sp+= 2;
465                                 while(a--) {
466                                         sp[0]= le_short(sp[0]);
467                                         sp[1]= le_short(sp[1]);
468                                         sp+= 2;
469                                 }
470                         }
471                         else {
472                                 sp+= 2*sp[1]+2;
473                         }
474                         
475                         nr++;
476                 }
477
478                 /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
479                 sp= findstruct_name(sdna, "ListBase");
480                 /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
481                 
482                 sdna->pointerlen= sdna->typelens[ sp[0] ]/2;
483
484                 if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) {
485                         printf("ListBase struct error! Needs it to calculate pointerize.\n");
486                         exit(0);
487                         /* well, at least sizeof(ListBase) is error proof! (ton) */
488                 }
489                 
490                 /* second part of gravity problem, setting "gravity" type to void */
491                 if(gravity_fix > -1) {
492                         for(nr=0; nr<sdna->nr_structs; nr++) {
493                                 sp= sdna->structs[nr];
494                                 if(strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0)
495                                         sp[10]= 9;
496                         }
497                 }
498
499 #ifdef WITH_DNA_GHASH
500                 /* create a ghash lookup to speed up */
501                 sdna->structs_map= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "init_structDNA gh");
502
503                 for(nr = 0; nr < sdna->nr_structs; nr++) {
504                         sp= sdna->structs[nr];
505                         BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], (void *)(nr + 1));
506                 }
507 #endif
508         }
509 }
510
511 SDNA *DNA_sdna_from_data(void *data, int datalen, int do_endian_swap)
512 {
513         SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna");
514         
515         sdna->lastfind= 0;
516
517         sdna->datalen= datalen;
518         sdna->data= MEM_mallocN(datalen, "sdna_data");
519         memcpy(sdna->data, data, datalen);
520         
521         init_structDNA(sdna, do_endian_swap);
522         
523         return sdna;
524 }
525
526 /* ******************** END READ DNA ********************** */
527
528 /* ******************* HANDLE DNA ***************** */
529
530 static void recurs_test_compflags(SDNA *sdna, char *compflags, int structnr)
531 {
532         int a, b, typenr, elems;
533         short *sp;
534         const char *cp;
535         
536         /* check all structs, test if it's inside another struct */
537         sp= sdna->structs[structnr];
538         typenr= sp[0];
539         
540         for(a=0; a<sdna->nr_structs; a++) {
541                 if(a!=structnr && compflags[a]==1) {
542                         sp= sdna->structs[a];
543                         elems= sp[1];
544                         sp+= 2;
545                         for(b=0; b<elems; b++, sp+=2) {
546                                 if(sp[0]==typenr) {
547                                         cp= sdna->names[ sp[1] ];
548                                         if(!ispointer(cp)) {
549                                                 compflags[a]= 2;
550                                                 recurs_test_compflags(sdna, compflags, a);
551                                         }
552                                 }
553                         }
554                 }
555         }
556         
557 }
558
559         /* Unsure of exact function - compares the sdna argument to
560          * newsdna and sets up the information necessary to convert
561          * data written with a dna of oldsdna to inmemory data with a
562          * structure defined by the newsdna sdna (I think). -zr
563          */
564
565 /* well, the function below is just a lookup table to speed
566  * up reading files. doh! -ton
567  */
568
569
570 char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna)
571 {
572         /* flag: 0: doesn't exist anymore (or not yet)
573          *       1: is equal
574          *       2: is different
575          */
576         int a, b;
577         short *spold, *spcur;
578         const char *str1, *str2;
579         char *compflags;
580         
581         if(sdna->nr_structs==0) {
582                 printf("error: file without SDNA\n");
583                 return NULL;
584         }
585                 
586         compflags= MEM_callocN(sdna->nr_structs, "compflags");
587
588         /* we check all structs in 'sdna' and compare them with 
589          * the structs in 'newsdna'
590          */
591         
592         for(a=0; a<sdna->nr_structs; a++) {
593                 spold= sdna->structs[a];
594                 
595                 /* search for type in cur */
596                 spcur= findstruct_name(newsdna, sdna->types[spold[0]]);
597                 
598                 if(spcur) {
599                         compflags[a]= 2;
600                         
601                         /* compare length and amount of elems */
602                         if( spcur[1] == spold[1]) {
603                                 if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) {
604
605                                         /* same length, same amount of elems, now per type and name */
606                                         b= spold[1];
607                                         spold+= 2;
608                                         spcur+= 2;
609                                         while(b > 0) {
610                                                 str1= newsdna->types[spcur[0]];
611                                                 str2= sdna->types[spold[0]];
612                                                 if(strcmp(str1, str2)!=0) break;
613
614                                                 str1= newsdna->names[spcur[1]];
615                                                 str2= sdna->names[spold[1]];
616                                                 if(strcmp(str1, str2)!=0) break;
617
618                                                 /* same type and same name, now pointersize */
619                                                 if(ispointer(str1)) {
620                                                         if(sdna->pointerlen!=newsdna->pointerlen) break;
621                                                 }
622
623                                                 b--;
624                                                 spold+= 2;
625                                                 spcur+= 2;
626                                         }
627                                         if(b==0) compflags[a]= 1;
628
629                                 }
630                         }
631                         
632                 }
633         }
634
635         /* first struct in util.h is struct Link, this is skipped in compflags (als # 0).
636          * was a bug, and this way dirty patched! Solve this later....
637          */
638         compflags[0]= 1;
639
640         /* Because structs can be inside structs, we recursively
641          * set flags when a struct is altered
642          */
643         for(a=0; a<sdna->nr_structs; a++) {
644                 if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a);
645         }
646         
647 /*
648         for(a=0; a<sdna->nr_structs; a++) {
649                 if(compflags[a]==2) {
650                         spold= sdna->structs[a];
651                         printf("changed: %s\n", sdna->types[ spold[0] ]);
652                 }
653         }
654 */
655
656         return compflags;
657 }
658
659 static void cast_elem(char *ctype, char *otype, const char *name, char *curdata, char *olddata)
660 {
661         double val = 0.0;
662         int arrlen, curlen=1, oldlen=1, ctypenr, otypenr;
663         
664         arrlen= DNA_elem_array_size(name, strlen(name));
665         
666         /* define otypenr */
667         if(strcmp(otype, "char")==0 || (strcmp(otype, "const char")==0)) otypenr= 0; 
668         else if((strcmp(otype, "uchar")==0) || (strcmp(otype, "unsigned char")==0)) otypenr= 1;
669         else if(strcmp(otype, "short")==0) otypenr= 2; 
670         else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3;
671         else if(strcmp(otype, "int")==0) otypenr= 4;
672         else if(strcmp(otype, "long")==0) otypenr= 5;
673         else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6;
674         else if(strcmp(otype, "float")==0) otypenr= 7;
675         else if(strcmp(otype, "double")==0) otypenr= 8;
676         else return;
677         
678         /* define ctypenr */
679         if(strcmp(ctype, "char")==0) ctypenr= 0; 
680         else if(strcmp(ctype, "const char")==0) ctypenr= 0; 
681         else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1;
682         else if(strcmp(ctype, "short")==0) ctypenr= 2; 
683         else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3;
684         else if(strcmp(ctype, "int")==0) ctypenr= 4;
685         else if(strcmp(ctype, "long")==0) ctypenr= 5;
686         else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6;
687         else if(strcmp(ctype, "float")==0) ctypenr= 7;
688         else if(strcmp(ctype, "double")==0) ctypenr= 8;
689         else return;
690
691         /* define lengths */
692         if(otypenr < 2) oldlen= 1;
693         else if(otypenr < 4) oldlen= 2;
694         else if(otypenr < 8) oldlen= 4;
695         else oldlen= 8;
696
697         if(ctypenr < 2) curlen= 1;
698         else if(ctypenr < 4) curlen= 2;
699         else if(ctypenr < 8) curlen= 4;
700         else curlen= 8;
701         
702         while(arrlen>0) {
703                 switch(otypenr) {
704                 case 0:
705                         val= *olddata; break;
706                 case 1:
707                         val= *( (unsigned char *)olddata); break;
708                 case 2:
709                         val= *( (short *)olddata); break;
710                 case 3:
711                         val= *( (unsigned short *)olddata); break;
712                 case 4:
713                         val= *( (int *)olddata); break;
714                 case 5:
715                         val= *( (int *)olddata); break;
716                 case 6:
717                         val= *( (unsigned int *)olddata); break;
718                 case 7:
719                         val= *( (float *)olddata); break;
720                 case 8:
721                         val= *( (double *)olddata); break;
722                 }
723                 
724                 switch(ctypenr) {
725                 case 0:
726                         *curdata= val; break;
727                 case 1:
728                         *( (unsigned char *)curdata)= val; break;
729                 case 2:
730                         *( (short *)curdata)= val; break;
731                 case 3:
732                         *( (unsigned short *)curdata)= val; break;
733                 case 4:
734                         *( (int *)curdata)= val; break;
735                 case 5:
736                         *( (int *)curdata)= val; break;
737                 case 6:
738                         *( (unsigned int *)curdata)= val; break;
739                 case 7:
740                         if(otypenr<2) val/= 255;
741                         *( (float *)curdata)= val; break;
742                 case 8:
743                         if(otypenr<2) val/= 255;
744                         *( (double *)curdata)= val; break;
745                 }
746
747                 olddata+= oldlen;
748                 curdata+= curlen;
749                 arrlen--;
750         }
751 }
752
753 static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, char *olddata)
754 {
755 #ifdef WIN32
756         __int64 lval;
757 #else
758         long long lval;
759 #endif
760         int arrlen;
761         
762         arrlen= DNA_elem_array_size(name, strlen(name));
763         
764         while(arrlen>0) {
765         
766                 if(curlen==oldlen) {
767                         memcpy(curdata, olddata, curlen);
768                 }
769                 else if(curlen==4 && oldlen==8) {
770 #ifdef WIN32                    
771                         lval= *( (__int64 *)olddata );
772 #else
773                         lval= *( (long long *)olddata );
774 #endif
775                         *((int *)curdata) = lval>>3;            /* is of course gambling! */
776                 }
777                 else if(curlen==8 && oldlen==4) {
778 #ifdef WIN32
779                          *( (__int64 *)curdata ) = *((int *)olddata);
780 #else
781                          *( (long long *)curdata ) = *((int *)olddata);
782 #endif
783                 }
784                 else {
785                         /* for debug */
786                         printf("errpr: illegal pointersize! \n");
787                 }
788                 
789                 olddata+= oldlen;
790                 curdata+= curlen;
791                 arrlen--;
792
793         }
794 }
795
796 static int elem_strcmp(const char *name, const char *oname)
797 {
798         int a=0;
799         
800         /* strcmp without array part */
801         
802         while(1) {
803                 if(name[a] != oname[a]) return 1;
804                 if(name[a]=='[') break;
805                 if(name[a]==0) break;
806                 a++;
807         }
808         if(name[a] != oname[a]) return 1;
809         return 0;
810 }
811
812 static char *find_elem(SDNA *sdna, const char *type, const char *name, short *old, char *olddata, short **sppo)
813 {
814         int a, elemcount, len;
815         const char *otype, *oname;
816         
817         /* without arraypart, so names can differ: return old namenr and type */
818         
819         /* in old is the old struct */
820         elemcount= old[1];
821         old+= 2;
822         for(a=0; a<elemcount; a++, old+=2) {
823         
824                 otype= sdna->types[old[0]];
825                 oname= sdna->names[old[1]];
826                 
827                 len= elementsize(sdna, old[0], old[1]);
828                 
829                 if( elem_strcmp(name, oname)==0 ) {     /* naam equal */
830                         if( strcmp(type, otype)==0 ) {  /* type equal */
831                                 if(sppo) *sppo= old;
832                                 return olddata;
833                         }
834                         
835                         return NULL;
836                 }
837                 
838                 olddata+= len;
839         }
840         return NULL;
841 }
842
843 static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna, char *type, const char *name, char *curdata, short *old, char *olddata)
844 {
845         /* rules: test for NAME:
846                         - name equal:
847                                 - cast type
848                         - name partially equal (array differs)
849                                 - type equal: memcpy
850                                 - types casten
851            (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
852            can I force this?)
853         */      
854         int a, elemcount, len, array, oldsize, cursize, mul;
855         char *otype;
856         const char *oname, *cp;
857         
858         /* is 'name' an array? */
859         cp= name;
860         array= 0;
861         while( *cp && *cp!='[') {
862                 cp++; array++;
863         }
864         if( *cp!= '[' ) array= 0;
865         
866         /* in old is the old struct */
867         elemcount= old[1];
868         old+= 2;
869         for(a=0; a<elemcount; a++, old+=2) {
870                 otype= oldsdna->types[old[0]];
871                 oname= oldsdna->names[old[1]];
872                 len= elementsize(oldsdna, old[0], old[1]);
873                 
874                 if( strcmp(name, oname)==0 ) {  /* name equal */
875                         
876                         if(ispointer(name)) {   /* pointer of functionpointer afhandelen */
877                                 cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
878                         }
879                         else if( strcmp(type, otype)==0 ) {     /* type equal */
880                                 memcpy(curdata, olddata, len);
881                         }
882                         else cast_elem(type, otype, name, curdata, olddata);
883
884                         return;
885                 }
886                 else if(array) {                /* name is an array */
887
888                         if(oname[array]=='[' && strncmp(name, oname, array)==0 ) {                      /* basis equal */
889                                 
890                                 cursize= DNA_elem_array_size(name, strlen(name));
891                                 oldsize= DNA_elem_array_size(oname, strlen(oname));
892
893                                 if(ispointer(name)) {           /* handle pointer or functionpointer */
894                                         if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
895                                         else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
896                                 }
897                                 else if(name[0]=='*' || strcmp(type, otype)==0 ) {      /* type equal */
898                                         mul= len/oldsize;
899                                         mul*= (cursize < oldsize)? cursize: oldsize;
900                                         memcpy(curdata, olddata, mul);
901                                         
902                                         /* terminate strings */
903                                         if(oldsize > cursize && strcmp(type, "char")==0)
904                                                 curdata[mul-1]= 0;
905                                 }
906                                 else {
907                                         if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata);
908                                         else cast_elem(type, otype, name, curdata, olddata);
909                                 }
910                                 return;
911                         }
912                 }
913                 olddata+= len;
914         }
915 }
916
917 static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
918 {
919         /* Recursive!
920          * Per element from cur_struct, read data from old_struct.
921          * If element is a struct, call recursive.
922          */
923         int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
924         short *spo, *spc, *sppo;
925         char *type, *cpo, *cpc;
926         const char *name, *nameo;
927
928         if(oldSDNAnr== -1) return;
929         if(curSDNAnr== -1) return;
930
931         if( compflags[oldSDNAnr]==1 ) {         /* if recursive: test for equal */
932         
933                 spo= oldsdna->structs[oldSDNAnr];
934                 elen= oldsdna->typelens[ spo[0] ];
935                 memcpy( cur, data, elen);
936                 
937                 return;
938         }
939
940         firststructtypenr= *(newsdna->structs[0]);
941
942         spo= oldsdna->structs[oldSDNAnr];
943         spc= newsdna->structs[curSDNAnr];
944
945         elemcount= spc[1];
946
947         spc+= 2;
948         cpc= cur;
949         for(a=0; a<elemcount; a++, spc+=2) {
950                 type= newsdna->types[spc[0]];
951                 name= newsdna->names[spc[1]];
952                 
953                 elen= elementsize(newsdna, spc[0], spc[1]);
954
955                 /* test: is type a struct? */
956                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
957                 
958                         /* where does the old struct data start (and is there an old one?) */
959                         cpo= find_elem(oldsdna, type, name, spo, data, &sppo);
960                         
961                         if(cpo) {
962                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
963                                 curSDNAnr= DNA_struct_find_nr(newsdna, type);
964                                 
965                                 /* array! */
966                                 mul= DNA_elem_array_size(name, strlen(name));
967                                 nameo= oldsdna->names[sppo[1]];
968                                 mulo= DNA_elem_array_size(nameo, strlen(nameo));
969                                 
970                                 eleno= elementsize(oldsdna, sppo[0], sppo[1]);
971                                 
972                                 elen/= mul;
973                                 eleno/= mulo;
974                                 
975                                 while(mul--) {
976                                         reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
977                                         cpo+= eleno;
978                                         cpc+= elen;
979                                         
980                                         /* new struct array larger than old */
981                                         mulo--;
982                                         if(mulo<=0) break;
983                                 }
984                         }
985                         else cpc+= elen;
986                 }
987                 else {
988
989                         reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
990                         cpc+= elen;
991
992                 }
993         }
994 }
995
996 void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
997 {
998         /* Recursive!
999          * If element is a struct, call recursive.
1000          */
1001         int a, mul, elemcount, elen, elena, firststructtypenr;
1002         short *spo, *spc, skip;
1003         char *type, *cpo, *cur, cval;
1004         const char *name;
1005
1006         if(oldSDNAnr== -1) return;
1007         firststructtypenr= *(oldsdna->structs[0]);
1008         
1009         spo= spc= oldsdna->structs[oldSDNAnr];
1010
1011         elemcount= spo[1];
1012
1013         spc+= 2;
1014         cur= data;
1015         
1016         for(a=0; a<elemcount; a++, spc+=2) {
1017                 type= oldsdna->types[spc[0]];
1018                 name= oldsdna->names[spc[1]];
1019                 
1020                 /* elementsize = including arraysize */
1021                 elen= elementsize(oldsdna, spc[0], spc[1]);
1022
1023                 /* test: is type a struct? */
1024                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
1025                         /* where does the old data start (is there one?) */
1026                         cpo= find_elem(oldsdna, type, name, spo, data, NULL);
1027                         if(cpo) {
1028                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
1029                                 
1030                                 mul= DNA_elem_array_size(name, strlen(name));
1031                                 elena= elen/mul;
1032
1033                                 while(mul--) {
1034                                         DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo);
1035                                         cpo += elena;
1036                                 }
1037                         }
1038                 }
1039                 else {
1040                         
1041                         if(ispointer(name)) {
1042                                 if(oldsdna->pointerlen==8) {
1043                                         
1044                                         mul= DNA_elem_array_size(name, strlen(name));
1045                                         cpo= cur;
1046                                         while(mul--) {
1047                                                 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
1048                                                 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
1049                                                 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
1050                                                 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
1051                                                 
1052                                                 cpo+= 8;
1053                                         }
1054                                         
1055                                 }
1056                         }
1057                         else {
1058                                 
1059                                 if( spc[0]==2 || spc[0]==3 ) {  /* short-ushort */
1060                                         
1061                                         /* exception: variable called blocktype/ipowin: derived from ID_  */
1062                                         skip= 0;
1063                                         if(name[0]=='b' && name[1]=='l') {
1064                                                 if(strcmp(name, "blocktype")==0) skip= 1;
1065                                         }
1066                                         else if(name[0]=='i' && name[1]=='p') {
1067                                                 if(strcmp(name, "ipowin")==0) skip= 1;
1068                                         }
1069                                         
1070                                         if(skip==0) {
1071                                                 mul= DNA_elem_array_size(name, strlen(name));
1072                                                 cpo= cur;
1073                                                 while(mul--) {
1074                                                         cval= cpo[0];
1075                                                         cpo[0]= cpo[1];
1076                                                         cpo[1]= cval;
1077                                                         cpo+= 2;
1078                                                 }
1079                                         }
1080                                 }
1081                                 else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */
1082
1083                                         mul= DNA_elem_array_size(name, strlen(name));
1084                                         cpo= cur;
1085                                         while(mul--) {
1086                                                 cval= cpo[0];
1087                                                 cpo[0]= cpo[3];
1088                                                 cpo[3]= cval;
1089                                                 cval= cpo[1];
1090                                                 cpo[1]= cpo[2];
1091                                                 cpo[2]= cval;
1092                                                 cpo+= 4;
1093                                         }
1094                                 }
1095                         }
1096                 }
1097                 cur+= elen;
1098         }
1099 }
1100
1101 void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
1102 {
1103         int a, curSDNAnr, curlen=0, oldlen;
1104         short *spo, *spc;
1105         char *cur, *type, *cpc, *cpo;
1106         
1107         /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */
1108         spo= oldsdna->structs[oldSDNAnr];
1109         type= oldsdna->types[ spo[0] ];
1110         oldlen= oldsdna->typelens[ spo[0] ];
1111         curSDNAnr= DNA_struct_find_nr(newsdna, type);
1112
1113         /* init data and alloc */
1114         if(curSDNAnr >= 0) {
1115                 spc= newsdna->structs[curSDNAnr];
1116                 curlen= newsdna->typelens[ spc[0] ];
1117         }
1118         if(curlen==0) {
1119                 return NULL;
1120         }
1121
1122         cur= MEM_callocN( blocks*curlen, "reconstruct");
1123         cpc= cur;
1124         cpo= data;
1125         for(a=0; a<blocks; a++) {
1126                 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
1127                 cpc+= curlen;
1128                 cpo+= oldlen;
1129         }
1130
1131         return cur;
1132 }
1133
1134 int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
1135 {
1136         
1137         int SDNAnr= DNA_struct_find_nr(sdna, stype);
1138         short *spo= sdna->structs[SDNAnr];
1139         char *cp= find_elem(sdna, vartype, name, spo, NULL, NULL);
1140         return (int)((intptr_t)cp);
1141 }
1142