change customdata mask from an 'unsigned int' to an 'u_int64_t', since BMesh branch...
[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 if( strcmp(dna_type, "u_int64_t")==0)                                            return SDNA_TYPE_UINT64;
671         else                                                                                  return -1; /* invalid! */
672 }
673
674 static void cast_elem(const char *ctype, const char *otype, const char *name, char *curdata, char *olddata)
675 {
676         double val = 0.0;
677         int arrlen, curlen=1, oldlen=1;
678
679         eSDNA_Type ctypenr, otypenr;
680
681         arrlen= DNA_elem_array_size(name, strlen(name));
682
683         if ( (otypenr= sdna_type_nr(otype)) == -1 ||
684              (ctypenr= sdna_type_nr(ctype)) == -1 )
685         {
686                 return;
687         }
688
689         /* define lengths */
690         oldlen= DNA_elem_type_size(otypenr);
691         curlen= DNA_elem_type_size(ctypenr);
692
693         while(arrlen>0) {
694                 switch(otypenr) {
695                 case SDNA_TYPE_CHAR:
696                         val= *olddata; break;
697                 case SDNA_TYPE_UCHAR:
698                         val= *( (unsigned char *)olddata); break;
699                 case SDNA_TYPE_SHORT:
700                         val= *( (short *)olddata); break;
701                 case SDNA_TYPE_USHORT:
702                         val= *( (unsigned short *)olddata); break;
703                 case SDNA_TYPE_INT:
704                         val= *( (int *)olddata); break;
705                 case SDNA_TYPE_LONG:
706                         val= *( (int *)olddata); break;
707                 case SDNA_TYPE_ULONG:
708                         val= *( (unsigned int *)olddata); break;
709                 case SDNA_TYPE_FLOAT:
710                         val= *( (float *)olddata); break;
711                 case SDNA_TYPE_DOUBLE:
712                         val= *( (double *)olddata); break;
713                 case SDNA_TYPE_INT64:
714                         val= *( (int64_t *)olddata); break;
715                 case SDNA_TYPE_UINT64:
716                         val= *( (u_int64_t *)olddata); break;
717                 }
718                 
719                 switch(ctypenr) {
720                 case SDNA_TYPE_CHAR:
721                         *curdata= val; break;
722                 case SDNA_TYPE_UCHAR:
723                         *( (unsigned char *)curdata)= val; break;
724                 case SDNA_TYPE_SHORT:
725                         *( (short *)curdata)= val; break;
726                 case SDNA_TYPE_USHORT:
727                         *( (unsigned short *)curdata)= val; break;
728                 case SDNA_TYPE_INT:
729                         *( (int *)curdata)= val; break;
730                 case SDNA_TYPE_LONG:
731                         *( (int *)curdata)= val; break;
732                 case SDNA_TYPE_ULONG:
733                         *( (unsigned int *)curdata)= val; break;
734                 case SDNA_TYPE_FLOAT:
735                         if(otypenr<2) val/= 255;
736                         *( (float *)curdata)= val; break;
737                 case SDNA_TYPE_DOUBLE:
738                         if(otypenr<2) val/= 255;
739                         *( (double *)curdata)= val; break;
740                 case SDNA_TYPE_INT64:
741                         *( (int64_t *)curdata)= val; break;
742                 case SDNA_TYPE_UINT64:
743                         *( (u_int64_t *)curdata)= val; break;
744                 }
745
746                 olddata+= oldlen;
747                 curdata+= curlen;
748                 arrlen--;
749         }
750 }
751
752 static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, char *olddata)
753 {
754 #ifdef WIN32
755         __int64 lval;
756 #else
757         long long lval;
758 #endif
759         int arrlen;
760         
761         arrlen= DNA_elem_array_size(name, strlen(name));
762         
763         while(arrlen>0) {
764         
765                 if(curlen==oldlen) {
766                         memcpy(curdata, olddata, curlen);
767                 }
768                 else if(curlen==4 && oldlen==8) {
769 #ifdef WIN32                    
770                         lval= *( (__int64 *)olddata );
771 #else
772                         lval= *( (long long *)olddata );
773 #endif
774                         *((int *)curdata) = lval>>3;            /* is of course gambling! */
775                 }
776                 else if(curlen==8 && oldlen==4) {
777 #ifdef WIN32
778                          *( (__int64 *)curdata ) = *((int *)olddata);
779 #else
780                          *( (long long *)curdata ) = *((int *)olddata);
781 #endif
782                 }
783                 else {
784                         /* for debug */
785                         printf("errpr: illegal pointersize! \n");
786                 }
787                 
788                 olddata+= oldlen;
789                 curdata+= curlen;
790                 arrlen--;
791
792         }
793 }
794
795 static int elem_strcmp(const char *name, const char *oname)
796 {
797         int a=0;
798         
799         /* strcmp without array part */
800         
801         while(1) {
802                 if(name[a] != oname[a]) return 1;
803                 if(name[a]=='[') break;
804                 if(name[a]==0) break;
805                 a++;
806         }
807         return 0;
808 }
809
810 static char *find_elem(SDNA *sdna, const char *type, const char *name, short *old, char *olddata, short **sppo)
811 {
812         int a, elemcount, len;
813         const char *otype, *oname;
814         
815         /* without arraypart, so names can differ: return old namenr and type */
816         
817         /* in old is the old struct */
818         elemcount= old[1];
819         old+= 2;
820         for(a=0; a<elemcount; a++, old+=2) {
821         
822                 otype= sdna->types[old[0]];
823                 oname= sdna->names[old[1]];
824                 
825                 len= elementsize(sdna, old[0], old[1]);
826                 
827                 if( elem_strcmp(name, oname)==0 ) {     /* naam equal */
828                         if( strcmp(type, otype)==0 ) {  /* type equal */
829                                 if(sppo) *sppo= old;
830                                 return olddata;
831                         }
832                         
833                         return NULL;
834                 }
835                 
836                 olddata+= len;
837         }
838         return NULL;
839 }
840
841 static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna,
842                              char *type, const char *name, char *curdata, short *old, char *olddata)
843 {
844         /* rules: test for NAME:
845                         - name equal:
846                                 - cast type
847                         - name partially equal (array differs)
848                                 - type equal: memcpy
849                                 - types casten
850            (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
851            can I force this?)
852         */      
853         int a, elemcount, len, array, oldsize, cursize, mul;
854         char *otype;
855         const char *oname, *cp;
856         
857         /* is 'name' an array? */
858         cp= name;
859         array= 0;
860         while( *cp && *cp!='[') {
861                 cp++; array++;
862         }
863         if( *cp!= '[' ) array= 0;
864         
865         /* in old is the old struct */
866         elemcount= old[1];
867         old+= 2;
868         for(a=0; a<elemcount; a++, old+=2) {
869                 otype= oldsdna->types[old[0]];
870                 oname= oldsdna->names[old[1]];
871                 len= elementsize(oldsdna, old[0], old[1]);
872                 
873                 if( strcmp(name, oname)==0 ) {  /* name equal */
874                         
875                         if(ispointer(name)) {   /* pointer of functionpointer afhandelen */
876                                 cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
877                         }
878                         else if( strcmp(type, otype)==0 ) {     /* type equal */
879                                 memcpy(curdata, olddata, len);
880                         }
881                         else cast_elem(type, otype, name, curdata, olddata);
882
883                         return;
884                 }
885                 else if(array) {                /* name is an array */
886
887                         if(oname[array]=='[' && strncmp(name, oname, array)==0 ) {                      /* basis equal */
888                                 
889                                 cursize= DNA_elem_array_size(name, strlen(name));
890                                 oldsize= DNA_elem_array_size(oname, strlen(oname));
891
892                                 if(ispointer(name)) {           /* handle pointer or functionpointer */
893                                         if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
894                                         else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
895                                 }
896                                 else if(name[0]=='*' || strcmp(type, otype)==0 ) {      /* type equal */
897                                         mul= len/oldsize;
898                                         mul*= (cursize < oldsize)? cursize: oldsize;
899                                         memcpy(curdata, olddata, mul);
900                                         
901                                         /* terminate strings */
902                                         if(oldsize > cursize && strcmp(type, "char")==0)
903                                                 curdata[mul-1]= 0;
904                                 }
905                                 else {
906                                         if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata);
907                                         else cast_elem(type, otype, name, curdata, olddata);
908                                 }
909                                 return;
910                         }
911                 }
912                 olddata+= len;
913         }
914 }
915
916 static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna,
917                                char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
918 {
919         /* Recursive!
920          * Per element from cur_struct, read data from old_struct.
921          * If element is a struct, call recursive.
922          */
923         int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
924         short *spo, *spc, *sppo;
925         char *type, *cpo, *cpc;
926         const char *name, *nameo;
927
928         if(oldSDNAnr== -1) return;
929         if(curSDNAnr== -1) return;
930
931         if( compflags[oldSDNAnr]==1 ) {         /* if recursive: test for equal */
932         
933                 spo= oldsdna->structs[oldSDNAnr];
934                 elen= oldsdna->typelens[ spo[0] ];
935                 memcpy( cur, data, elen);
936                 
937                 return;
938         }
939
940         firststructtypenr= *(newsdna->structs[0]);
941
942         spo= oldsdna->structs[oldSDNAnr];
943         spc= newsdna->structs[curSDNAnr];
944
945         elemcount= spc[1];
946
947         spc+= 2;
948         cpc= cur;
949         for(a=0; a<elemcount; a++, spc+=2) {
950                 type= newsdna->types[spc[0]];
951                 name= newsdna->names[spc[1]];
952                 
953                 elen= elementsize(newsdna, spc[0], spc[1]);
954
955                 /* test: is type a struct? */
956                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
957                 
958                         /* where does the old struct data start (and is there an old one?) */
959                         cpo= find_elem(oldsdna, type, name, spo, data, &sppo);
960                         
961                         if(cpo) {
962                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
963                                 curSDNAnr= DNA_struct_find_nr(newsdna, type);
964                                 
965                                 /* array! */
966                                 mul= DNA_elem_array_size(name, strlen(name));
967                                 nameo= oldsdna->names[sppo[1]];
968                                 mulo= DNA_elem_array_size(nameo, strlen(nameo));
969                                 
970                                 eleno= elementsize(oldsdna, sppo[0], sppo[1]);
971                                 
972                                 elen/= mul;
973                                 eleno/= mulo;
974                                 
975                                 while(mul--) {
976                                         reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
977                                         cpo+= eleno;
978                                         cpc+= elen;
979                                         
980                                         /* new struct array larger than old */
981                                         mulo--;
982                                         if(mulo<=0) break;
983                                 }
984                         }
985                         else cpc+= elen;
986                 }
987                 else {
988
989                         reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
990                         cpc+= elen;
991
992                 }
993         }
994 }
995
996 void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
997 {
998         /* Recursive!
999          * If element is a struct, call recursive.
1000          */
1001         int a, mul, elemcount, elen, elena, firststructtypenr;
1002         short *spo, *spc, skip;
1003         char *type, *cpo, *cur, cval;
1004         const char *name;
1005
1006         if(oldSDNAnr== -1) return;
1007         firststructtypenr= *(oldsdna->structs[0]);
1008         
1009         spo= spc= oldsdna->structs[oldSDNAnr];
1010
1011         elemcount= spo[1];
1012
1013         spc+= 2;
1014         cur= data;
1015         
1016         for(a=0; a<elemcount; a++, spc+=2) {
1017                 type= oldsdna->types[spc[0]];
1018                 name= oldsdna->names[spc[1]];
1019                 
1020                 /* elementsize = including arraysize */
1021                 elen= elementsize(oldsdna, spc[0], spc[1]);
1022
1023                 /* test: is type a struct? */
1024                 if(spc[0]>=firststructtypenr  &&  !ispointer(name)) {
1025                         /* where does the old data start (is there one?) */
1026                         cpo= find_elem(oldsdna, type, name, spo, data, NULL);
1027                         if(cpo) {
1028                                 oldSDNAnr= DNA_struct_find_nr(oldsdna, type);
1029                                 
1030                                 mul= DNA_elem_array_size(name, strlen(name));
1031                                 elena= elen/mul;
1032
1033                                 while(mul--) {
1034                                         DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo);
1035                                         cpo += elena;
1036                                 }
1037                         }
1038                 }
1039                 else {
1040                         
1041                         if(ispointer(name)) {
1042                                 if(oldsdna->pointerlen==8) {
1043                                         
1044                                         mul= DNA_elem_array_size(name, strlen(name));
1045                                         cpo= cur;
1046                                         while(mul--) {
1047                                                 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
1048                                                 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
1049                                                 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
1050                                                 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
1051                                                 
1052                                                 cpo+= 8;
1053                                         }
1054                                         
1055                                 }
1056                         }
1057                         else {
1058                                 
1059                                 if ( spc[0]==SDNA_TYPE_SHORT ||
1060                                      spc[0]==SDNA_TYPE_USHORT )
1061                                 {
1062                                         
1063                                         /* exception: variable called blocktype/ipowin: derived from ID_  */
1064                                         skip= 0;
1065                                         if(name[0]=='b' && name[1]=='l') {
1066                                                 if(strcmp(name, "blocktype")==0) skip= 1;
1067                                         }
1068                                         else if(name[0]=='i' && name[1]=='p') {
1069                                                 if(strcmp(name, "ipowin")==0) skip= 1;
1070                                         }
1071                                         
1072                                         if(skip==0) {
1073                                                 mul= DNA_elem_array_size(name, strlen(name));
1074                                                 cpo= cur;
1075                                                 while(mul--) {
1076                                                         cval= cpo[0];
1077                                                         cpo[0]= cpo[1];
1078                                                         cpo[1]= cval;
1079                                                         cpo+= 2;
1080                                                 }
1081                                         }
1082                                 }
1083                                 else if ( (spc[0]==SDNA_TYPE_INT    ||
1084                                            spc[0]==SDNA_TYPE_LONG   ||
1085                                            spc[0]==SDNA_TYPE_ULONG  ||
1086                                            spc[0]==SDNA_TYPE_FLOAT))
1087                                 {
1088
1089                                         mul= DNA_elem_array_size(name, strlen(name));
1090                                         cpo= cur;
1091                                         while(mul--) {
1092                                                 cval= cpo[0];
1093                                                 cpo[0]= cpo[3];
1094                                                 cpo[3]= cval;
1095                                                 cval= cpo[1];
1096                                                 cpo[1]= cpo[2];
1097                                                 cpo[2]= cval;
1098                                                 cpo+= 4;
1099                                         }
1100                                 }
1101                                 else if ( (spc[0]==SDNA_TYPE_INT64) ||
1102                                           (spc[0]==SDNA_TYPE_UINT64))
1103                                 {
1104                                         mul= DNA_elem_array_size(name, strlen(name));
1105                                         cpo= cur;
1106                                         while(mul--) {
1107                                                 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
1108                                                 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
1109                                                 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
1110                                                 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
1111
1112                                                 cpo+= 8;
1113                                         }
1114                                 }
1115                         }
1116                 }
1117                 cur+= elen;
1118         }
1119 }
1120
1121 void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
1122 {
1123         int a, curSDNAnr, curlen=0, oldlen;
1124         short *spo, *spc;
1125         char *cur, *type, *cpc, *cpo;
1126         
1127         /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */
1128         spo= oldsdna->structs[oldSDNAnr];
1129         type= oldsdna->types[ spo[0] ];
1130         oldlen= oldsdna->typelens[ spo[0] ];
1131         curSDNAnr= DNA_struct_find_nr(newsdna, type);
1132
1133         /* init data and alloc */
1134         if(curSDNAnr >= 0) {
1135                 spc= newsdna->structs[curSDNAnr];
1136                 curlen= newsdna->typelens[ spc[0] ];
1137         }
1138         if(curlen==0) {
1139                 return NULL;
1140         }
1141
1142         cur= MEM_callocN( blocks*curlen, "reconstruct");
1143         cpc= cur;
1144         cpo= data;
1145         for(a=0; a<blocks; a++) {
1146                 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
1147                 cpc+= curlen;
1148                 cpo+= oldlen;
1149         }
1150
1151         return cur;
1152 }
1153
1154 int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
1155 {
1156         
1157         int SDNAnr= DNA_struct_find_nr(sdna, stype);
1158         short *spo= sdna->structs[SDNAnr];
1159         char *cp= find_elem(sdna, vartype, name, spo, NULL, NULL);
1160         return (int)((intptr_t)cp);
1161 }
1162
1163 int DNA_elem_type_size(const eSDNA_Type elem_nr)
1164 {
1165         /* should containt all enum types */
1166         switch (elem_nr) {
1167                 case SDNA_TYPE_CHAR:
1168                 case SDNA_TYPE_UCHAR:
1169                         return 1;
1170                 case SDNA_TYPE_SHORT:
1171                 case SDNA_TYPE_USHORT:
1172                         return 2;
1173                 case SDNA_TYPE_INT:
1174                 case SDNA_TYPE_LONG:
1175                 case SDNA_TYPE_ULONG:
1176                 case SDNA_TYPE_FLOAT:
1177                         return 4;
1178                 case SDNA_TYPE_DOUBLE:
1179                 case SDNA_TYPE_INT64:
1180                 case SDNA_TYPE_UINT64:
1181                         return 8;
1182         }
1183
1184         /* weak */
1185         return 8;
1186 }