/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** * DNA handling */ #ifdef HAVE_CONFIG_H #include #endif #ifndef WIN32 #include // for read close #else #include // for open close read #endif #include // strncmp #include // for printf #include // for atoi #include // for open O_RDONLY #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN #include "BLI_blenlib.h" // for BLI_filesize #include "BKE_utildefines.h" // for O_BINARY TRUE MIN2 #include "DNA_sdna_types.h" // for SDNA ;-) #include "BLO_writefile.h" #include "BLO_genfile.h" #include "genfile.h" /* * - pas op: geen beveiling tegen dubbele structen * - struct niet in DNA file: twee hekjes erboven (##) Aanmaken structDNA: alleen wanneer includes wijzigen. File Syntax: SDNA (4 bytes) (voor fileherkenning) NAME (4 bytes) (4 bytes) aantal namen (int) ... ... TYPE (4 bytes) aantal types (int) ... ... TLEN (4 bytes) (short) ... ... STRC (4 bytes) aantal structen (int) ... !!Denk aan integer en short aligned schrijven/lezen!! Bij het wegschrijven van files worden namen structen aangegeven met type= findstruct_nr(SDNA *, char *), 'type' correspondeert met nummer structarray in structDNA. Voor het moment: complete DNA file appenden achter blenderfile. In toekomst nadenken over slimmere methode (alleen gebruikte structen?, voorgeprepareerde DNA files? (TOT, OB, MAT ) TOEGESTANE EN GETESTE WIJZIGINGEN IN STRUCTS: - type verandering (bij chars naar float wordt door 255 gedeeld) - plek in struct (alles kan door elkaar) - struct in struct (in struct etc, is recursief) - nieuwe elementen toevoegen (standaard op 0) - elementen eruit (worden niet meer ingelezen) - array's groter/kleiner - verschillende typepointers met zelfde naam worden altijd gekopieerd. (NOG) NIET: - float-array (vec[3]) naar struct van floats (vec3f) GEDAAN: - DNA file in (achter) blender-executable plakken voor upward compatibility Gebruikte methode: het makesdna programma schrijft een c-file met een met spaties gevuld char-array van de juiste lengte. Makesdna maakt er een .o van en vult de spaties met de DNA file. - endian compatibility - 32 bits en 64 bits pointers LET OP: - uint mag niet in een struct, gebruik unsigned int. (backwards compatibility vanwege 64 bits code!) - structen moeten altijd (intern) 4/8-aligned en short-aligned zijn. de SDNA routine test hierop en print duidelijke errors. DNA files met align errors zijn onbruikbaar! - switch_endian doet alleen long long pointers, zodat ze veilig gecast kunnen worden naar 32 bits - casten van 64 naar 32 bits poinetrs: >>3. */ /* local */ static int le_int(int temp); static short le_short(short temp); /* ************************* ENDIAN STUFF ********************** */ static short le_short(short temp) { short new; char *rt=(char *)&temp, *rtn=(char *)&new; rtn[0]= rt[1]; rtn[1]= rt[0]; return new; } static int le_int(int temp) { int new; char *rt=(char *)&temp, *rtn=(char *)&new; rtn[0]= rt[3]; rtn[1]= rt[2]; rtn[2]= rt[1]; rtn[3]= rt[0]; return new; } /* ************************* MAKEN DNA ********************** */ /* allowed duplicate code from makesdna.c */ static int arraysize(char *astr, int len) { int a, mul=1; char str[100], *cp=0; memcpy(str, astr, len+1); for(a=0; adata); MEM_freeN(sdna->names); MEM_freeN(sdna->types); MEM_freeN(sdna->structs); MEM_freeN(sdna); } static int elementsize(struct SDNA *sdna, short type, short name) /* aanroepen met nummers uit struct-array */ { int mul, namelen, len; char *cp; cp= sdna->names[name]; len= 0; namelen= strlen(cp); /* is het een pointer of functiepointer? */ if(cp[0]=='*' || cp[1]=='*') { /* heeft de naam een extra lente? (array) */ mul= 1; if( cp[namelen-1]==']') mul= arraysize(cp, namelen); len= sdna->pointerlen*mul; } else if( sdna->typelens[type] ) { /* heeft de naam een extra lente? (array) */ mul= 1; if( cp[namelen-1]==']') mul= arraysize(cp, namelen); len= mul*sdna->typelens[type]; } return len; } #if 0 static void printstruct(struct SDNA *sdna, short strnr) { /* geef het structnummer door, is voor debug */ int b, nr; short *sp; sp= sdna->structs[strnr]; printf("struct %s\n", sdna->types[ sp[0] ]); nr= sp[1]; sp+= 2; for(b=0; b< nr; b++, sp+= 2) { printf(" %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]); } } #endif static short *findstruct_name(struct SDNA *sdna, char *str) { int a; short *sp=0; for(a=0; anr_structs; a++) { sp= sdna->structs[a]; if(strcmp( sdna->types[ sp[0] ], str )==0) return sp; } return 0; } int dna_findstruct_nr(struct SDNA *sdna, char *str) { short *sp=0; int a; if(sdna->lastfindnr_structs) { sp= sdna->structs[sdna->lastfind]; if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind; } for(a=0; anr_structs; a++) { sp= sdna->structs[a]; if(strcmp( sdna->types[ sp[0] ], str )==0) { sdna->lastfind= a; return a; } } return -1; } /* ************************* END DIV ********************** */ /* ************************* LEZEN DNA ********************** */ static void init_structDNA(struct SDNA *sdna, int do_endian_swap) /* in sdna->data staat de data, uit elkaar pulken */ { int *data, *verg; long nr; short *sp; char str[8], *cp; verg= (int *)str; data= (int *)sdna->data; strcpy(str, "SDNA"); if( *data == *verg ) { data++; /* laad namen array */ strcpy(str, "NAME"); if( *data == *verg ) { data++; if(do_endian_swap) sdna->nr_names= le_int(*data); else sdna->nr_names= *data; data++; sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames"); } else { printf("NAME error in SDNA file\n"); return; } nr= 0; cp= (char *)data; while(nrnr_names) { sdna->names[nr]= cp; while( *cp) cp++; cp++; nr++; } nr= (long)cp; /* BUS error voorkomen */ nr= (nr+3) & ~3; cp= (char *)nr; /* laad typenamen array */ data= (int *)cp; strcpy(str, "TYPE"); if( *data == *verg ) { data++; if(do_endian_swap) sdna->nr_types= le_int(*data); else sdna->nr_types= *data; data++; sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes"); } else { printf("TYPE error in SDNA file\n"); return; } nr= 0; cp= (char *)data; while(nrnr_types) { sdna->types[nr]= cp; /* met deze patch kunnen structnamen gewijzigd worden */ /* alleen gebruiken voor conflicten met systeem-structen (opengl/X) */ if( *cp == 'b') { /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */ if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1; } while( *cp) cp++; cp++; nr++; } nr= (long)cp; /* BUS error voorkomen */ nr= (nr+3) & ~3; cp= (char *)nr; /* laad typelen array */ data= (int *)cp; strcpy(str, "TLEN"); if( *data == *verg ) { data++; sp= (short *)data; sdna->typelens= sp; if(do_endian_swap) { short a, *spo= sp; a= sdna->nr_types; while(a--) { spo[0]= le_short(spo[0]); spo++; } } sp+= sdna->nr_types; } else { printf("TLEN error in SDNA file\n"); return; } if(sdna->nr_types & 1) sp++; /* BUS error voorkomen */ /* laad structen array */ data= (int *)sp; strcpy(str, "STRC"); if( *data == *verg ) { data++; if(do_endian_swap) sdna->nr_structs= le_int(*data); else sdna->nr_structs= *data; data++; sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs"); } else { printf("STRC error in SDNA file\n"); return; } nr= 0; sp= (short *)data; while(nrnr_structs) { sdna->structs[nr]= sp; if(do_endian_swap) { short a; sp[0]= le_short(sp[0]); sp[1]= le_short(sp[1]); a= sp[1]; sp+= 2; while(a--) { sp[0]= le_short(sp[0]); sp[1]= le_short(sp[1]); sp+= 2; } } else { sp+= 2*sp[1]+2; } nr++; } /* finally pointerlen: use struct ListBase to test it, never change the size of it! */ sp= findstruct_name(sdna, "ListBase"); sdna->pointerlen= sdna->typelens[ sp[0] ]/2; if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) { printf("ListBase struct error! Needs it to calculate pointerize.\n"); exit(0); } } } struct SDNA *dna_sdna_from_data(void *data, int datalen, int do_endian_swap) { struct SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna"); sdna->lastfind= 0; sdna->datalen= datalen; sdna->data= MEM_mallocN(datalen, "sdna_data"); memcpy(sdna->data, data, datalen); init_structDNA(sdna, do_endian_swap); return sdna; } /* XXX, this routine was added because at one * point I thought using the dna more would be * nice, but really thats a flawed idea, you * already know about your memory structures when * you are compiling no need to redirect that * through the DNA, the python stuff should be * changed to not use this routine (a bit * o' work). - zr */ int BLO_findstruct_offset(char *structname, char *member) { extern char DNAstr[]; /* DNA.c */ extern int DNAlen; struct SDNA *sdna; int a, offset; short *sp; sdna= dna_sdna_from_data(DNAstr, DNAlen, 0); sp= findstruct_name(sdna, structname); if(sp) { a= sp[1]; /* aantal elems */ sp+= 2; offset= 0; while(a--) { if(strcmp(sdna->names[sp[1]], member)==0) { dna_freestructDNA(sdna); return offset; } offset+= elementsize(sdna, sp[0], sp[1]); sp+= 2; } } dna_freestructDNA(sdna); return -1; } /* ******************** END LEZEN DNA ********************** */ /* ******************* AFHANDELEN DNA ***************** */ static void recurs_test_compflags(struct SDNA *sdna, char *compflags, int structnr) { int a, b, typenr, elems; short *sp; char *cp; /* loop alle structen af en test of deze struct in andere zit */ sp= sdna->structs[structnr]; typenr= sp[0]; for(a=0; anr_structs; a++) { if(a!=structnr && compflags[a]==1) { sp= sdna->structs[a]; elems= sp[1]; sp+= 2; for(b=0; bnames[ sp[1] ]; if(cp[0]!= '*') { compflags[a]= 2; recurs_test_compflags(sdna, compflags, a); } } } } } } /* Unsure of exact function - compares the sdna argument to * newsdna and sets up the information necessary to convert * data written with a dna of oldsdna to inmemory data with a * structure defined by the newsdna sdna (I think). -zr */ char *dna_get_structDNA_compareflags(struct SDNA *sdna, struct SDNA *newsdna) { /* flag: 0:bestaat niet meer (of nog niet) * 1: is gelijk * 2: is anders */ int a, b; short *spold, *spcur; char *str1, *str2; char *compflags; if(sdna->nr_structs==0) { printf("error: file without SDNA\n"); return NULL; } compflags= MEM_callocN(sdna->nr_structs, "compflags"); /* We lopen alle structs in 'sdna' af, vergelijken ze met * de structs in 'newsdna' */ for(a=0; anr_structs; a++) { spold= sdna->structs[a]; /* type zoeken in cur */ spcur= findstruct_name(newsdna, sdna->types[spold[0]]); if(spcur) { compflags[a]= 2; /* lengte en aantal elems vergelijken */ if( spcur[1] == spold[1]) { if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) { /* evenlang en evenveel elems, nu per type en naam */ b= spold[1]; spold+= 2; spcur+= 2; while(b > 0) { str1= newsdna->types[spcur[0]]; str2= sdna->types[spold[0]]; if(strcmp(str1, str2)!=0) break; str1= newsdna->names[spcur[1]]; str2= sdna->names[spold[1]]; if(strcmp(str1, str2)!=0) break; /* naam gelijk, type gelijk, nu nog pointersize, dit geval komt haast nooit voor! */ if(str1[0]=='*') { if(sdna->pointerlen!=newsdna->pointerlen) break; } b--; spold+= 2; spcur+= 2; } if(b==0) compflags[a]= 1; } } } } /* eerste struct in util.h is struct Link, deze wordt in de compflags overgeslagen (als # 0). * Vuile patch! Nog oplossen.... */ compflags[0]= 1; /* Aangezien structen in structen kunnen zitten gaan we recursief * vlaggen zetten als er een struct veranderd is */ for(a=0; anr_structs; a++) { if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a); } /* for(a=0; anr_structs; a++) { if(compflags[a]==2) { spold= sdna->structs[a]; printf("changed: %s\n", sdna->types[ spold[0] ]); } } */ return compflags; } static void cast_elem(char *ctype, char *otype, char *name, char *curdata, char *olddata) { double val = 0.0; int arrlen, curlen=1, oldlen=1, ctypenr, otypenr; arrlen= arraysize(name, strlen(name)); /* otypenr bepalen */ if(strcmp(otype, "char")==0) otypenr= 0; else if((strcmp(otype, "uchar")==0)||(strcmp(otype, "unsigned char")==0)) otypenr= 1; else if(strcmp(otype, "short")==0) otypenr= 2; else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3; else if(strcmp(otype, "int")==0) otypenr= 4; else if(strcmp(otype, "long")==0) otypenr= 5; else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6; else if(strcmp(otype, "float")==0) otypenr= 7; else if(strcmp(otype, "double")==0) otypenr= 8; else return; /* ctypenr bepalen */ if(strcmp(ctype, "char")==0) ctypenr= 0; else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1; else if(strcmp(ctype, "short")==0) ctypenr= 2; else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3; else if(strcmp(ctype, "int")==0) ctypenr= 4; else if(strcmp(ctype, "long")==0) ctypenr= 5; else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6; else if(strcmp(ctype, "float")==0) ctypenr= 7; else if(strcmp(ctype, "double")==0) ctypenr= 8; else return; /* lengtes bepalen */ if(otypenr < 2) oldlen= 1; else if(otypenr < 4) oldlen= 2; else if(otypenr < 8) oldlen= 4; else oldlen= 8; if(ctypenr < 2) curlen= 1; else if(ctypenr < 4) curlen= 2; else if(ctypenr < 8) curlen= 4; else curlen= 8; while(arrlen>0) { switch(otypenr) { case 0: val= *olddata; break; case 1: val= *( (unsigned char *)olddata); break; case 2: val= *( (short *)olddata); break; case 3: val= *( (unsigned short *)olddata); break; case 4: val= *( (int *)olddata); break; case 5: val= *( (int *)olddata); break; case 6: val= *( (unsigned int *)olddata); break; case 7: val= *( (float *)olddata); break; case 8: val= *( (double *)olddata); break; } switch(ctypenr) { case 0: *curdata= val; break; case 1: *( (unsigned char *)curdata)= val; break; case 2: *( (short *)curdata)= val; break; case 3: *( (unsigned short *)curdata)= val; break; case 4: *( (int *)curdata)= val; break; case 5: *( (int *)curdata)= val; break; case 6: *( (unsigned int *)curdata)= val; break; case 7: if(otypenr<2) val/= 255; *( (float *)curdata)= val; break; case 8: if(otypenr<2) val/= 255; *( (double *)curdata)= val; break; } olddata+= oldlen; curdata+= curlen; arrlen--; } } static void cast_pointer(int curlen, int oldlen, char *name, char *curdata, char *olddata) { #ifdef WIN32 __int64 lval; #else long long lval; #endif int arrlen; arrlen= arraysize(name, strlen(name)); while(arrlen>0) { if(curlen==oldlen) { memcpy(curdata, olddata, curlen); } else if(curlen==4 && oldlen==8) { #ifdef WIN32 lval= *( (__int64 *)olddata ); #else lval= *( (long long *)olddata ); #endif *((int *)curdata) = lval>>3; /* is natuurlijk een beetje een gok! */ } else if(curlen==8 && oldlen==4) { #ifdef WIN32 *( (__int64 *)curdata ) = *((int *)olddata); #else *( (long long *)curdata ) = *((int *)olddata); #endif } else { /* voor debug */ printf("errpr: illegal pointersize! \n"); } olddata+= oldlen; curdata+= curlen; arrlen--; } } static int elem_strcmp(char *name, char *oname) { int a=0; /* strcmp without array part */ while(TRUE) { if(name[a] != oname[a]) return 1; if(name[a]=='[') break; if(name[a]==0) break; a++; } if(name[a] != oname[a]) return 1; return 0; } static char *find_elem(struct SDNA *sdna, char *type, char *name, short *old, char *olddata, short **sppo) { int a, elemcount, len; char *otype, *oname; /* without arraypart, so names can differ: return old namenr and type */ /* in old staat de oude struct */ elemcount= old[1]; old+= 2; for(a=0; atypes[old[0]]; oname= sdna->names[old[1]]; len= elementsize(sdna, old[0], old[1]); if( elem_strcmp(name, oname)==0 ) { /* naam gelijk */ if( strcmp(type, otype)==0 ) { /* type gelijk */ if(sppo) *sppo= old; return olddata; } return 0; } olddata+= len; } return 0; } static void reconstruct_elem(struct SDNA *newsdna, struct SDNA *oldsdna, char *type, char *name, char *curdata, short *old, char *olddata) { /* regels: testen op NAAM: - naam volledig gelijk: - type casten - naam gedeeltelijk gelijk (array anders) - type gelijk: memcpy - types casten (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where can I force this? */ int a, elemcount, len, array, oldsize, cursize, mul; char *otype, *oname, *cp; /* is 'name' een array? */ cp= name; array= 0; while( *cp && *cp!='[') { cp++; array++; } if( *cp!= '[' ) array= 0; /* in old staat de oude struct */ elemcount= old[1]; old+= 2; for(a=0; atypes[old[0]]; oname= oldsdna->names[old[1]]; len= elementsize(oldsdna, old[0], old[1]); if( strcmp(name, oname)==0 ) { /* naam gelijk */ if( name[0]=='*') { /* pointer afhandelen */ cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata); } else if( strcmp(type, otype)==0 ) { /* type gelijk */ memcpy(curdata, olddata, len); } else cast_elem(type, otype, name, curdata, olddata); return; } else if(array) { /* de naam is een array */ if( strncmp(name, oname, array)==0 ) { /* basis gelijk */ cursize= arraysize(name, strlen(name)); oldsize= arraysize(oname, strlen(oname)); if( name[0]=='*') { /* pointer afhandelen */ if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata); else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata); } else if(name[0]=='*' || strcmp(type, otype)==0 ) { /* type gelijk */ mul= len/oldsize; mul*= MIN2(cursize, oldsize); memcpy(curdata, olddata, mul); } else { if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata); else cast_elem(type, otype, name, curdata, olddata); } return; } } olddata+= len; } } static void reconstruct_struct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur) { /* Recursief! * Per element van cur_struct data lezen uit old_struct. * Als element een struct is, recursief aanroepen. */ int a, elemcount, elen, eleno, mul, mulo, firststructtypenr; short *spo, *spc, *sppo; char *name, *nameo, *type, *cpo, *cpc; if(oldSDNAnr== -1) return; if(curSDNAnr== -1) return; if( compflags[oldSDNAnr]==1 ) { /* bij recurs: testen op gelijk */ spo= oldsdna->structs[oldSDNAnr]; elen= oldsdna->typelens[ spo[0] ]; memcpy( cur, data, elen); return; } firststructtypenr= *(newsdna->structs[0]); spo= oldsdna->structs[oldSDNAnr]; spc= newsdna->structs[curSDNAnr]; elemcount= spc[1]; spc+= 2; cpc= cur; for(a=0; atypes[spc[0]]; name= newsdna->names[spc[1]]; elen= elementsize(newsdna, spc[0], spc[1]); /* testen: is type een struct? */ if(spc[0]>=firststructtypenr && name[0]!='*') { /* waar start de oude struct data (is ie er wel?) */ cpo= find_elem(oldsdna, type, name, spo, data, &sppo); if(cpo) { oldSDNAnr= dna_findstruct_nr(oldsdna, type); curSDNAnr= dna_findstruct_nr(newsdna, type); /* array! */ mul= arraysize(name, strlen(name)); nameo= oldsdna->names[sppo[1]]; mulo= arraysize(nameo, strlen(nameo)); eleno= elementsize(oldsdna, sppo[0], sppo[1]); elen/= mul; eleno/= mulo; while(mul--) { reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc); cpo+= eleno; cpc+= elen; /* new struct array larger than old */ mulo--; if(mulo<=0) break; } } else cpc+= elen; } else { reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data); cpc+= elen; } } } void dna_switch_endian_struct(struct SDNA *oldsdna, int oldSDNAnr, char *data) { /* Recursief! * Als element een struct is, recursief aanroepen. */ int a, mul, elemcount, elen, elena, firststructtypenr; short *spo, *spc, skip; char *name, *type, *cpo, *cur, cval; if(oldSDNAnr== -1) return; firststructtypenr= *(oldsdna->structs[0]); spo= spc= oldsdna->structs[oldSDNAnr]; elemcount= spo[1]; spc+= 2; cur= data; for(a=0; atypes[spc[0]]; name= oldsdna->names[spc[1]]; /* elementsize = including arraysize */ elen= elementsize(oldsdna, spc[0], spc[1]); /* testen: is type een struct? */ if(spc[0]>=firststructtypenr && name[0]!='*') { /* waar start de oude struct data (is ie er wel?) */ cpo= find_elem(oldsdna, type, name, spo, data, 0); if(cpo) { oldSDNAnr= dna_findstruct_nr(oldsdna, type); mul= arraysize(name, strlen(name)); elena= elen/mul; while(mul--) { dna_switch_endian_struct(oldsdna, oldSDNAnr, cpo); cpo += elena; } } } else { if( name[0]=='*' ) { if(oldsdna->pointerlen==8) { mul= arraysize(name, strlen(name)); cpo= cur; while(mul--) { cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval; cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval; cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval; cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval; cpo+= 8; } } } else { if( spc[0]==2 || spc[0]==3 ) { /* short-ushort */ /* uitzondering: variable die blocktype/ipowin heet: van ID_ afgeleid */ skip= 0; if(name[0]=='b' && name[1]=='l') { if(strcmp(name, "blocktype")==0) skip= 1; } else if(name[0]=='i' && name[1]=='p') { if(strcmp(name, "ipowin")==0) skip= 1; } if(skip==0) { mul= arraysize(name, strlen(name)); cpo= cur; while(mul--) { cval= cpo[0]; cpo[0]= cpo[1]; cpo[1]= cval; cpo+= 2; } } } else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */ mul= arraysize(name, strlen(name)); cpo= cur; while(mul--) { cval= cpo[0]; cpo[0]= cpo[3]; cpo[3]= cval; cval= cpo[1]; cpo[1]= cpo[2]; cpo[2]= cval; cpo+= 4; } } } } cur+= elen; } } void *dna_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data) { int a, curSDNAnr, curlen=0, oldlen; short *spo, *spc; char *cur, *type, *cpc, *cpo; /* oldSDNAnr == structnr, we zoeken het corresponderende 'cur' nummer */ spo= oldsdna->structs[oldSDNAnr]; type= oldsdna->types[ spo[0] ]; oldlen= oldsdna->typelens[ spo[0] ]; curSDNAnr= dna_findstruct_nr(newsdna, type); /* data goedzetten en nieuwe calloc doen */ if(curSDNAnr >= 0) { spc= newsdna->structs[curSDNAnr]; curlen= newsdna->typelens[ spc[0] ]; } if(curlen==0) { return NULL; } cur= MEM_callocN( blocks*curlen, "reconstruct"); cpc= cur; cpo= data; for(a=0; a