3 * Functions for struct-dna, the genetic file dot c!
7 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version. The Blender
13 * Foundation also sells licenses for use in proprietary software under
14 * the Blender License. See http://www.blender.org/BL/ for information
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27 * All rights reserved.
29 * The Original Code is: all of this file.
31 * Contributor(s): none yet.
33 * ***** END GPL/BL DUAL LICENSE BLOCK *****
42 #include <unistd.h> // for read close
44 #include <io.h> // for open close read
47 #include <string.h> // strncmp
48 #include <stdio.h> // for printf
49 #include <stdlib.h> // for atoi
50 #include <fcntl.h> // for open O_RDONLY
52 #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
53 #include "BLI_blenlib.h" // for BLI_filesize
55 #include "BKE_utildefines.h" // for O_BINARY TRUE MIN2
57 #include "DNA_sdna_types.h" // for SDNA ;-)
59 #include "BLO_writefile.h"
60 #include "BLO_genfile.h"
64 /* gcc 4.1 on mingw was complaining that __int64 was alredy defined
65 actually is saw the line below as typedef long long long long...
66 Anyhow, since its alredy defined, its safe to do an ifndef here- Cambpell*/
69 typedef long long __int64;
74 * - please note: no builtin security to detect input of double structs
75 * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>)
77 Structure DNA data is added to each blender file and to each executable, this to detect
78 in .blend files new veriables in structs, changed array sizes, etc. It's also used for
79 converting endian and pointer size (32-64 bits)
80 As an extra, Python uses a call to detect run-time the contents of a blender struct.
82 Create a structDNA: only needed when one of the input include (.h) files change.
84 SDNA (4 bytes) (magic number)
86 <nr> (4 bytes) amount of names (int)
92 <nr> amount of types (int)
98 <len> (short) the lengths of types
103 <nr> amount of structs (int)
104 <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ...
106 !!Remember to read/write integer and short aligned!!
108 While writing a file, the names of a struct is indicated with a type number,
109 to be found with: type= findstruct_nr(SDNA *, char *)
110 The value of 'type' corresponds with the the index within the structs array
112 For the moment: the complete DNA file is included in a .blend file. For
113 the future we can think of smarter methods, like only included the used
114 structs. Only needed to keep a file short though...
116 ALLOWED AND TESTED CHANGES IN STRUCTS:
117 - type change (a char to float will be divided by 255)
118 - location within a struct (everthing can be randomly mixed up)
119 - struct within struct (within struct etc), this is recursive
120 - adding new elements, will be default initialized zero
122 - change of array sizes
123 - change of a pointer type: when the name doesn't change the contents is copied
126 - array (vec[3]) to float struct (vec3f)
129 - endian compatibility
130 - pointer conversion (32-64 bits)
133 - do not use #defines in structs for array lenghts, this cannot be read by the dna functions
134 - do not use uint, but unsigned int instead, ushort and ulong are allowed
135 - only use a long in Blender if you want this to be the size of a pointer. so it is
136 32 bits or 64 bits, dependant at the cpu architecture
137 - chars are always unsigned
138 - aligment of variables has to be done in such a way, that any system does
139 not create 'padding' (gaps) in structures. So make sure that:
146 - the sdna functions have several error prints builtin, always check blender running from a console.
151 static int le_int(int temp);
152 static short le_short(short temp);
154 /* ************************* ENDIAN STUFF ********************** */
156 static short le_short(short temp)
159 char *rt=(char *)&temp, *rtn=(char *)&new;
168 static int le_int(int temp)
171 char *rt=(char *)&temp, *rtn=(char *)&new;
182 /* ************************* MAKE DNA ********************** */
184 /* allowed duplicate code from makesdna.c */
185 static int arraysize(char *astr, int len)
188 char str[100], *cp=0;
190 memcpy(str, astr, len+1);
192 for(a=0; a<len; a++) {
196 else if( str[a]==']' && cp) {
205 /* ************************* END MAKE DNA ********************** */
207 /* ************************* DIV ********************** */
209 void dna_freestructDNA(struct SDNA *sdna)
211 MEM_freeN(sdna->data);
212 MEM_freeN(sdna->names);
213 MEM_freeN(sdna->types);
214 MEM_freeN(sdna->structs);
219 static int elementsize(struct SDNA *sdna, short type, short name)
220 /* call with numbers from struct-array */
222 int mul, namelen, len;
225 cp= sdna->names[name];
229 /* is it a pointer or function pointer? */
230 if(cp[0]=='*' || cp[1]=='*') {
231 /* has the naam an extra length? (array) */
233 if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
235 len= sdna->pointerlen*mul;
237 else if( sdna->typelens[type] ) {
238 /* has the naam an extra length? (array) */
240 if( cp[namelen-1]==']') mul= arraysize(cp, namelen);
242 len= mul*sdna->typelens[type];
250 static void printstruct(struct SDNA *sdna, short strnr)
256 sp= sdna->structs[strnr];
258 printf("struct %s\n", sdna->types[ sp[0] ]);
262 for(b=0; b< nr; b++, sp+= 2) {
263 printf(" %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]);
268 static short *findstruct_name(struct SDNA *sdna, char *str)
274 for(a=0; a<sdna->nr_structs; a++) {
276 sp= sdna->structs[a];
278 if(strcmp( sdna->types[ sp[0] ], str )==0) return sp;
284 int dna_findstruct_nr(struct SDNA *sdna, char *str)
289 if(sdna->lastfind<sdna->nr_structs) {
290 sp= sdna->structs[sdna->lastfind];
291 if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind;
294 for(a=0; a<sdna->nr_structs; a++) {
296 sp= sdna->structs[a];
298 if(strcmp( sdna->types[ sp[0] ], str )==0) {
307 /* ************************* END DIV ********************** */
309 /* ************************* READ DNA ********************** */
311 static void init_structDNA(struct SDNA *sdna, int do_endian_swap)
312 /* in sdna->data the data, now we convert that to something understandable */
320 data= (int *)sdna->data;
323 if( *data == *verg ) {
327 /* load names array */
329 if( *data == *verg ) {
332 if(do_endian_swap) sdna->nr_names= le_int(*data);
333 else sdna->nr_names= *data;
336 sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames");
339 printf("NAME error in SDNA file\n");
345 while(nr<sdna->nr_names) {
351 nr= (long)cp; /* prevent BUS error */
355 /* load type names array */
358 if( *data == *verg ) {
361 if(do_endian_swap) sdna->nr_types= le_int(*data);
362 else sdna->nr_types= *data;
365 sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes");
368 printf("TYPE error in SDNA file\n");
374 while(nr<sdna->nr_types) {
377 /* this is a patch, to change struct names without a confict with SDNA */
378 /* be careful to use it, in this case for a system-struct (opengl/X) */
381 /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
382 if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1;
389 nr= (long)cp; /* prevent BUS error */
393 /* load typelen array */
396 if( *data == *verg ) {
406 spo[0]= le_short(spo[0]);
414 printf("TLEN error in SDNA file\n");
417 if(sdna->nr_types & 1) sp++; /* prevent BUS error */
419 /* load struct array */
422 if( *data == *verg ) {
425 if(do_endian_swap) sdna->nr_structs= le_int(*data);
426 else sdna->nr_structs= *data;
429 sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs");
432 printf("STRC error in SDNA file\n");
438 while(nr<sdna->nr_structs) {
439 sdna->structs[nr]= sp;
444 sp[0]= le_short(sp[0]);
445 sp[1]= le_short(sp[1]);
450 sp[0]= le_short(sp[0]);
451 sp[1]= le_short(sp[1]);
462 /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
463 sp= findstruct_name(sdna, "ListBase");
464 /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
466 sdna->pointerlen= sdna->typelens[ sp[0] ]/2;
468 if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) {
469 printf("ListBase struct error! Needs it to calculate pointerize.\n");
471 /* well, at least sizeof(ListBase) is error proof! (ton) */
477 struct SDNA *dna_sdna_from_data(void *data, int datalen, int do_endian_swap)
479 struct SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna");
483 sdna->datalen= datalen;
484 sdna->data= MEM_mallocN(datalen, "sdna_data");
485 memcpy(sdna->data, data, datalen);
487 init_structDNA(sdna, do_endian_swap);
492 /* ******************** END READ DNA ********************** */
494 /* ******************* HANDLE DNA ***************** */
496 static void recurs_test_compflags(struct SDNA *sdna, char *compflags, int structnr)
498 int a, b, typenr, elems;
502 /* check all structs, test if it's inside another struct */
503 sp= sdna->structs[structnr];
506 for(a=0; a<sdna->nr_structs; a++) {
507 if(a!=structnr && compflags[a]==1) {
508 sp= sdna->structs[a];
511 for(b=0; b<elems; b++, sp+=2) {
513 cp= sdna->names[ sp[1] ];
516 recurs_test_compflags(sdna, compflags, a);
525 /* Unsure of exact function - compares the sdna argument to
526 * newsdna and sets up the information necessary to convert
527 * data written with a dna of oldsdna to inmemory data with a
528 * structure defined by the newsdna sdna (I think). -zr
531 /* well, the function below is just a lookup table to speed
532 * up reading files. doh! -ton
536 char *dna_get_structDNA_compareflags(struct SDNA *sdna, struct SDNA *newsdna)
538 /* flag: 0: doesn't exist anymore (or not yet)
543 short *spold, *spcur;
547 if(sdna->nr_structs==0) {
548 printf("error: file without SDNA\n");
552 compflags= MEM_callocN(sdna->nr_structs, "compflags");
554 /* we check all structs in 'sdna' and compare them with
555 * the structs in 'newsdna'
558 for(a=0; a<sdna->nr_structs; a++) {
559 spold= sdna->structs[a];
561 /* search for type in cur */
562 spcur= findstruct_name(newsdna, sdna->types[spold[0]]);
567 /* compare length and amount of elems */
568 if( spcur[1] == spold[1]) {
569 if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) {
571 /* same length, same amount of elems, now per type and name */
576 str1= newsdna->types[spcur[0]];
577 str2= sdna->types[spold[0]];
578 if(strcmp(str1, str2)!=0) break;
580 str1= newsdna->names[spcur[1]];
581 str2= sdna->names[spold[1]];
582 if(strcmp(str1, str2)!=0) break;
584 /* same type and same name, now pointersize */
586 if(sdna->pointerlen!=newsdna->pointerlen) break;
593 if(b==0) compflags[a]= 1;
601 /* first struct in util.h is struct Link, this is skipped in compflags (als # 0).
602 * was a bug, and this way dirty patched! Solve this later....
606 /* Because structs can be inside structs, we recursively
607 * set flags when a struct is altered
609 for(a=0; a<sdna->nr_structs; a++) {
610 if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a);
614 for(a=0; a<sdna->nr_structs; a++) {
615 if(compflags[a]==2) {
616 spold= sdna->structs[a];
617 printf("changed: %s\n", sdna->types[ spold[0] ]);
625 static void cast_elem(char *ctype, char *otype, char *name, char *curdata, char *olddata)
628 int arrlen, curlen=1, oldlen=1, ctypenr, otypenr;
630 arrlen= arraysize(name, strlen(name));
633 if(strcmp(otype, "char")==0) otypenr= 0;
634 else if((strcmp(otype, "uchar")==0)||(strcmp(otype, "unsigned char")==0)) otypenr= 1;
635 else if(strcmp(otype, "short")==0) otypenr= 2;
636 else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3;
637 else if(strcmp(otype, "int")==0) otypenr= 4;
638 else if(strcmp(otype, "long")==0) otypenr= 5;
639 else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6;
640 else if(strcmp(otype, "float")==0) otypenr= 7;
641 else if(strcmp(otype, "double")==0) otypenr= 8;
645 if(strcmp(ctype, "char")==0) ctypenr= 0;
646 else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1;
647 else if(strcmp(ctype, "short")==0) ctypenr= 2;
648 else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3;
649 else if(strcmp(ctype, "int")==0) ctypenr= 4;
650 else if(strcmp(ctype, "long")==0) ctypenr= 5;
651 else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6;
652 else if(strcmp(ctype, "float")==0) ctypenr= 7;
653 else if(strcmp(ctype, "double")==0) ctypenr= 8;
657 if(otypenr < 2) oldlen= 1;
658 else if(otypenr < 4) oldlen= 2;
659 else if(otypenr < 8) oldlen= 4;
662 if(ctypenr < 2) curlen= 1;
663 else if(ctypenr < 4) curlen= 2;
664 else if(ctypenr < 8) curlen= 4;
670 val= *olddata; break;
672 val= *( (unsigned char *)olddata); break;
674 val= *( (short *)olddata); break;
676 val= *( (unsigned short *)olddata); break;
678 val= *( (int *)olddata); break;
680 val= *( (int *)olddata); break;
682 val= *( (unsigned int *)olddata); break;
684 val= *( (float *)olddata); break;
686 val= *( (double *)olddata); break;
691 *curdata= val; break;
693 *( (unsigned char *)curdata)= val; break;
695 *( (short *)curdata)= val; break;
697 *( (unsigned short *)curdata)= val; break;
699 *( (int *)curdata)= val; break;
701 *( (int *)curdata)= val; break;
703 *( (unsigned int *)curdata)= val; break;
705 if(otypenr<2) val/= 255;
706 *( (float *)curdata)= val; break;
708 if(otypenr<2) val/= 255;
709 *( (double *)curdata)= val; break;
718 static void cast_pointer(int curlen, int oldlen, char *name, char *curdata, char *olddata)
727 arrlen= arraysize(name, strlen(name));
732 memcpy(curdata, olddata, curlen);
734 else if(curlen==4 && oldlen==8) {
736 lval= *( (__int64 *)olddata );
738 lval= *( (long long *)olddata );
740 *((int *)curdata) = lval>>3; /* is of course gambling! */
742 else if(curlen==8 && oldlen==4) {
744 *( (__int64 *)curdata ) = *((int *)olddata);
746 *( (long long *)curdata ) = *((int *)olddata);
751 printf("errpr: illegal pointersize! \n");
761 static int elem_strcmp(char *name, char *oname)
765 /* strcmp without array part */
768 if(name[a] != oname[a]) return 1;
769 if(name[a]=='[') break;
770 if(name[a]==0) break;
773 if(name[a] != oname[a]) return 1;
777 static char *find_elem(struct SDNA *sdna, char *type, char *name, short *old, char *olddata, short **sppo)
779 int a, elemcount, len;
782 /* without arraypart, so names can differ: return old namenr and type */
784 /* in old is the old struct */
787 for(a=0; a<elemcount; a++, old+=2) {
789 otype= sdna->types[old[0]];
790 oname= sdna->names[old[1]];
792 len= elementsize(sdna, old[0], old[1]);
794 if( elem_strcmp(name, oname)==0 ) { /* naam equal */
795 if( strcmp(type, otype)==0 ) { /* type equal */
808 static void reconstruct_elem(struct SDNA *newsdna, struct SDNA *oldsdna, char *type, char *name, char *curdata, short *old, char *olddata)
810 /* rules: test for NAME:
813 - name partially equal (array differs)
816 (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
819 int a, elemcount, len, array, oldsize, cursize, mul;
820 char *otype, *oname, *cp;
822 /* is 'name' an array? */
825 while( *cp && *cp!='[') {
828 if( *cp!= '[' ) array= 0;
830 /* in old is the old struct */
833 for(a=0; a<elemcount; a++, old+=2) {
834 otype= oldsdna->types[old[0]];
835 oname= oldsdna->names[old[1]];
836 len= elementsize(oldsdna, old[0], old[1]);
838 if( strcmp(name, oname)==0 ) { /* name equal */
840 if( name[0]=='*') { /* pointer afhandelen */
841 cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
843 else if( strcmp(type, otype)==0 ) { /* type equal */
844 memcpy(curdata, olddata, len);
846 else cast_elem(type, otype, name, curdata, olddata);
850 else if(array) { /* name is an array */
852 if(oname[array]=='[' && strncmp(name, oname, array)==0 ) { /* basis equal */
854 cursize= arraysize(name, strlen(name));
855 oldsize= arraysize(oname, strlen(oname));
857 if( name[0]=='*') { /* handle pointer */
858 if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
859 else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
861 else if(name[0]=='*' || strcmp(type, otype)==0 ) { /* type equal */
863 mul*= MIN2(cursize, oldsize);
864 memcpy(curdata, olddata, mul);
867 if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata);
868 else cast_elem(type, otype, name, curdata, olddata);
877 static void reconstruct_struct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
880 * Per element from cur_struct, read data from old_struct.
881 * If element is a struct, call recursive.
883 int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
884 short *spo, *spc, *sppo;
885 char *name, *nameo, *type, *cpo, *cpc;
887 if(oldSDNAnr== -1) return;
888 if(curSDNAnr== -1) return;
890 if( compflags[oldSDNAnr]==1 ) { /* if recursive: test for equal */
892 spo= oldsdna->structs[oldSDNAnr];
893 elen= oldsdna->typelens[ spo[0] ];
894 memcpy( cur, data, elen);
899 firststructtypenr= *(newsdna->structs[0]);
901 spo= oldsdna->structs[oldSDNAnr];
902 spc= newsdna->structs[curSDNAnr];
908 for(a=0; a<elemcount; a++, spc+=2) {
909 type= newsdna->types[spc[0]];
910 name= newsdna->names[spc[1]];
912 elen= elementsize(newsdna, spc[0], spc[1]);
914 /* test: is type a struct? */
915 if(spc[0]>=firststructtypenr && name[0]!='*') {
917 /* where does the old struct data start (and is there an old one?) */
918 cpo= find_elem(oldsdna, type, name, spo, data, &sppo);
921 oldSDNAnr= dna_findstruct_nr(oldsdna, type);
922 curSDNAnr= dna_findstruct_nr(newsdna, type);
925 mul= arraysize(name, strlen(name));
926 nameo= oldsdna->names[sppo[1]];
927 mulo= arraysize(nameo, strlen(nameo));
929 eleno= elementsize(oldsdna, sppo[0], sppo[1]);
935 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);
939 /* new struct array larger than old */
948 reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
955 void dna_switch_endian_struct(struct SDNA *oldsdna, int oldSDNAnr, char *data)
958 * If element is a struct, call recursive.
960 int a, mul, elemcount, elen, elena, firststructtypenr;
961 short *spo, *spc, skip;
962 char *name, *type, *cpo, *cur, cval;
964 if(oldSDNAnr== -1) return;
965 firststructtypenr= *(oldsdna->structs[0]);
967 spo= spc= oldsdna->structs[oldSDNAnr];
974 for(a=0; a<elemcount; a++, spc+=2) {
975 type= oldsdna->types[spc[0]];
976 name= oldsdna->names[spc[1]];
978 /* elementsize = including arraysize */
979 elen= elementsize(oldsdna, spc[0], spc[1]);
981 /* test: is type a struct? */
982 if(spc[0]>=firststructtypenr && name[0]!='*') {
983 /* where does the old data start (is there one?) */
984 cpo= find_elem(oldsdna, type, name, spo, data, 0);
986 oldSDNAnr= dna_findstruct_nr(oldsdna, type);
988 mul= arraysize(name, strlen(name));
992 dna_switch_endian_struct(oldsdna, oldSDNAnr, cpo);
1000 if(oldsdna->pointerlen==8) {
1002 mul= arraysize(name, strlen(name));
1005 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval;
1006 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval;
1007 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval;
1008 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval;
1017 if( spc[0]==2 || spc[0]==3 ) { /* short-ushort */
1019 /* exception: variable called blocktype/ipowin: derived from ID_ */
1021 if(name[0]=='b' && name[1]=='l') {
1022 if(strcmp(name, "blocktype")==0) skip= 1;
1024 else if(name[0]=='i' && name[1]=='p') {
1025 if(strcmp(name, "ipowin")==0) skip= 1;
1029 mul= arraysize(name, strlen(name));
1039 else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */
1041 mul= arraysize(name, strlen(name));
1059 void *dna_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
1061 int a, curSDNAnr, curlen=0, oldlen;
1063 char *cur, *type, *cpc, *cpo;
1065 /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */
1066 spo= oldsdna->structs[oldSDNAnr];
1067 type= oldsdna->types[ spo[0] ];
1068 oldlen= oldsdna->typelens[ spo[0] ];
1069 curSDNAnr= dna_findstruct_nr(newsdna, type);
1071 /* init data and alloc */
1072 if(curSDNAnr >= 0) {
1073 spc= newsdna->structs[curSDNAnr];
1074 curlen= newsdna->typelens[ spc[0] ];
1080 cur= MEM_callocN( blocks*curlen, "reconstruct");
1083 for(a=0; a<blocks; a++) {
1084 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc);