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