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