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