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