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