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