|
Blender
V2.59
|
00001 /* dna_genfile.c 00002 * 00003 * Functions for struct-dna, the genetic file dot c! 00004 * 00005 * $Id: dna_genfile.c 36276 2011-04-21 15:53:30Z campbellbarton $ 00006 * 00007 * ***** BEGIN GPL LICENSE BLOCK ***** 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00024 * All rights reserved. 00025 * 00026 * The Original Code is: all of this file. 00027 * 00028 * Contributor(s): none yet. 00029 * 00030 * ***** END GPL LICENSE BLOCK ***** 00031 * DNA handling 00032 */ 00033 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 00043 #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN 00044 00045 #include "DNA_genfile.h" 00046 #include "DNA_sdna_types.h" // for SDNA ;-) 00047 00048 00049 /* gcc 4.1 on mingw was complaining that __int64 was already defined 00050 actually is saw the line below as typedef long long long long... 00051 Anyhow, since its already defined, its safe to do an ifndef here- Campbell */ 00052 #ifdef FREE_WINDOWS 00053 #ifndef __int64 00054 typedef long long __int64; 00055 #endif 00056 #endif 00057 00058 /* 00059 * - please note: no builtin security to detect input of double structs 00060 * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>) 00061 00062 Structure DNA data is added to each blender file and to each executable, this to detect 00063 in .blend files new veriables in structs, changed array sizes, etc. It's also used for 00064 converting endian and pointer size (32-64 bits) 00065 As an extra, Python uses a call to detect run-time the contents of a blender struct. 00066 00067 Create a structDNA: only needed when one of the input include (.h) files change. 00068 File Syntax: 00069 SDNA (4 bytes) (magic number) 00070 NAME (4 bytes) 00071 <nr> (4 bytes) amount of names (int) 00072 <string> 00073 <string> 00074 ... 00075 ... 00076 TYPE (4 bytes) 00077 <nr> amount of types (int) 00078 <string> 00079 <string> 00080 ... 00081 ... 00082 TLEN (4 bytes) 00083 <len> (short) the lengths of types 00084 <len> 00085 ... 00086 ... 00087 STRC (4 bytes) 00088 <nr> amount of structs (int) 00089 <typenr><nr_of_elems> <typenr><namenr> <typenr><namenr> ... 00090 00091 !!Remember to read/write integer and short aligned!! 00092 00093 While writing a file, the names of a struct is indicated with a type number, 00094 to be found with: type= findstruct_nr(SDNA *, char *) 00095 The value of 'type' corresponds with the the index within the structs array 00096 00097 For the moment: the complete DNA file is included in a .blend file. For 00098 the future we can think of smarter methods, like only included the used 00099 structs. Only needed to keep a file short though... 00100 00101 ALLOWED AND TESTED CHANGES IN STRUCTS: 00102 - type change (a char to float will be divided by 255) 00103 - location within a struct (everthing can be randomly mixed up) 00104 - struct within struct (within struct etc), this is recursive 00105 - adding new elements, will be default initialized zero 00106 - remving elements 00107 - change of array sizes 00108 - change of a pointer type: when the name doesn't change the contents is copied 00109 00110 NOT YET: 00111 - array (vec[3]) to float struct (vec3f) 00112 00113 DONE: 00114 - endian compatibility 00115 - pointer conversion (32-64 bits) 00116 00117 IMPORTANT: 00118 - do not use #defines in structs for array lengths, this cannot be read by the dna functions 00119 - do not use uint, but unsigned int instead, ushort and ulong are allowed 00120 - only use a long in Blender if you want this to be the size of a pointer. so it is 00121 32 bits or 64 bits, dependant at the cpu architecture 00122 - chars are always unsigned 00123 - aligment of variables has to be done in such a way, that any system does 00124 not create 'padding' (gaps) in structures. So make sure that: 00125 - short: 2 aligned 00126 - int: 4 aligned 00127 - float: 4 aligned 00128 - double: 8 aligned 00129 - long: 8 aligned 00130 - struct: 8 aligned 00131 - the sdna functions have several error prints builtin, always check blender running from a console. 00132 00133 */ 00134 00135 /* local */ 00136 static int le_int(int temp); 00137 static short le_short(short temp); 00138 00139 /* ************************* ENDIAN STUFF ********************** */ 00140 00141 static short le_short(short temp) 00142 { 00143 short new; 00144 char *rt=(char *)&temp, *rtn=(char *)&new; 00145 00146 rtn[0]= rt[1]; 00147 rtn[1]= rt[0]; 00148 00149 return new; 00150 } 00151 00152 00153 static int le_int(int temp) 00154 { 00155 int new; 00156 char *rt=(char *)&temp, *rtn=(char *)&new; 00157 00158 rtn[0]= rt[3]; 00159 rtn[1]= rt[2]; 00160 rtn[2]= rt[1]; 00161 rtn[3]= rt[0]; 00162 00163 return new; 00164 } 00165 00166 00167 /* ************************* MAKE DNA ********************** */ 00168 00169 /* allowed duplicate code from makesdna.c */ 00170 int DNA_elem_array_size(const char *astr, int len) 00171 { 00172 int a, mul=1; 00173 char str[100], *cp= NULL; 00174 00175 memcpy(str, astr, len+1); 00176 00177 for(a=0; a<len; a++) { 00178 if( str[a]== '[' ) { 00179 cp= &(str[a+1]); 00180 } 00181 else if( str[a]==']' && cp) { 00182 str[a]= 0; 00183 mul*= atoi(cp); 00184 } 00185 } 00186 00187 return mul; 00188 } 00189 00190 /* ************************* END MAKE DNA ********************** */ 00191 00192 /* ************************* DIV ********************** */ 00193 00194 void DNA_sdna_free(SDNA *sdna) 00195 { 00196 MEM_freeN(sdna->data); 00197 MEM_freeN((void *)sdna->names); 00198 MEM_freeN(sdna->types); 00199 MEM_freeN(sdna->structs); 00200 00201 MEM_freeN(sdna); 00202 } 00203 00204 static int ispointer(const char *name) 00205 { 00206 /* check if pointer or function pointer */ 00207 return (name[0]=='*' || (name[0]=='(' && name[1]=='*')); 00208 } 00209 00210 static int elementsize(SDNA *sdna, short type, short name) 00211 /* call with numbers from struct-array */ 00212 { 00213 int mul, namelen, len; 00214 const char *cp; 00215 00216 cp= sdna->names[name]; 00217 len= 0; 00218 00219 namelen= strlen(cp); 00220 /* is it a pointer or function pointer? */ 00221 if(ispointer(cp)) { 00222 /* has the naam an extra length? (array) */ 00223 mul= 1; 00224 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen); 00225 00226 len= sdna->pointerlen*mul; 00227 } 00228 else if( sdna->typelens[type] ) { 00229 /* has the naam an extra length? (array) */ 00230 mul= 1; 00231 if( cp[namelen-1]==']') mul= DNA_elem_array_size(cp, namelen); 00232 00233 len= mul*sdna->typelens[type]; 00234 00235 } 00236 00237 return len; 00238 } 00239 00240 #if 0 00241 static void printstruct(SDNA *sdna, short strnr) 00242 { 00243 /* is for debug */ 00244 int b, nr; 00245 short *sp; 00246 00247 sp= sdna->structs[strnr]; 00248 00249 printf("struct %s\n", sdna->types[ sp[0] ]); 00250 nr= sp[1]; 00251 sp+= 2; 00252 00253 for(b=0; b< nr; b++, sp+= 2) { 00254 printf(" %s %s\n", sdna->types[sp[0]], sdna->names[sp[1]]); 00255 } 00256 } 00257 #endif 00258 00259 static short *findstruct_name(SDNA *sdna, const char *str) 00260 { 00261 int a; 00262 short *sp= NULL; 00263 00264 00265 for(a=0; a<sdna->nr_structs; a++) { 00266 00267 sp= sdna->structs[a]; 00268 00269 if(strcmp( sdna->types[ sp[0] ], str )==0) return sp; 00270 } 00271 00272 return NULL; 00273 } 00274 00275 int DNA_struct_find_nr(SDNA *sdna, const char *str) 00276 { 00277 short *sp= NULL; 00278 int a; 00279 00280 if(sdna->lastfind<sdna->nr_structs) { 00281 sp= sdna->structs[sdna->lastfind]; 00282 if(strcmp( sdna->types[ sp[0] ], str )==0) return sdna->lastfind; 00283 } 00284 00285 for(a=0; a<sdna->nr_structs; a++) { 00286 00287 sp= sdna->structs[a]; 00288 00289 if(strcmp( sdna->types[ sp[0] ], str )==0) { 00290 sdna->lastfind= a; 00291 return a; 00292 } 00293 } 00294 00295 return -1; 00296 } 00297 00298 /* ************************* END DIV ********************** */ 00299 00300 /* ************************* READ DNA ********************** */ 00301 00302 static void init_structDNA(SDNA *sdna, int do_endian_swap) 00303 /* in sdna->data the data, now we convert that to something understandable */ 00304 { 00305 int *data, *verg, gravity_fix= -1; 00306 intptr_t nr; 00307 short *sp; 00308 char str[8], *cp; 00309 00310 verg= (int *)str; 00311 data= (int *)sdna->data; 00312 00313 strcpy(str, "SDNA"); 00314 if( *data == *verg ) { 00315 00316 data++; 00317 00318 /* load names array */ 00319 strcpy(str, "NAME"); 00320 if( *data == *verg ) { 00321 data++; 00322 00323 if(do_endian_swap) sdna->nr_names= le_int(*data); 00324 else sdna->nr_names= *data; 00325 00326 data++; 00327 sdna->names= MEM_callocN( sizeof(void *)*sdna->nr_names, "sdnanames"); 00328 } 00329 else { 00330 printf("NAME error in SDNA file\n"); 00331 return; 00332 } 00333 00334 nr= 0; 00335 cp= (char *)data; 00336 while(nr<sdna->nr_names) { 00337 sdna->names[nr]= cp; 00338 00339 /* "float gravity [3]" was parsed wrong giving both "gravity" and 00340 "[3]" members. we rename "[3]", and later set the type of 00341 "gravity" to "void" so the offsets work out correct */ 00342 if(*cp == '[' && strcmp(cp, "[3]")==0) { 00343 if(nr && strcmp(sdna->names[nr-1], "Cvi") == 0) { 00344 sdna->names[nr]= "gravity[3]"; 00345 gravity_fix= nr; 00346 } 00347 } 00348 00349 while( *cp) cp++; 00350 cp++; 00351 nr++; 00352 } 00353 nr= (intptr_t)cp; /* prevent BUS error */ 00354 nr= (nr+3) & ~3; 00355 cp= (char *)nr; 00356 00357 /* load type names array */ 00358 data= (int *)cp; 00359 strcpy(str, "TYPE"); 00360 if( *data == *verg ) { 00361 data++; 00362 00363 if(do_endian_swap) sdna->nr_types= le_int(*data); 00364 else sdna->nr_types= *data; 00365 00366 data++; 00367 sdna->types= MEM_callocN( sizeof(void *)*sdna->nr_types, "sdnatypes"); 00368 } 00369 else { 00370 printf("TYPE error in SDNA file\n"); 00371 return; 00372 } 00373 00374 nr= 0; 00375 cp= (char *)data; 00376 while(nr<sdna->nr_types) { 00377 sdna->types[nr]= cp; 00378 00379 /* this is a patch, to change struct names without a confict with SDNA */ 00380 /* be careful to use it, in this case for a system-struct (opengl/X) */ 00381 00382 if( *cp == 'b') { 00383 /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */ 00384 if( strcmp("bScreen", cp)==0 ) sdna->types[nr]= cp+1; 00385 } 00386 00387 while( *cp) cp++; 00388 cp++; 00389 nr++; 00390 } 00391 nr= (intptr_t)cp; /* prevent BUS error */ 00392 nr= (nr+3) & ~3; 00393 cp= (char *)nr; 00394 00395 /* load typelen array */ 00396 data= (int *)cp; 00397 strcpy(str, "TLEN"); 00398 if( *data == *verg ) { 00399 data++; 00400 sp= (short *)data; 00401 sdna->typelens= sp; 00402 00403 if(do_endian_swap) { 00404 short a, *spo= sp; 00405 00406 a= sdna->nr_types; 00407 while(a--) { 00408 spo[0]= le_short(spo[0]); 00409 spo++; 00410 } 00411 } 00412 00413 sp+= sdna->nr_types; 00414 } 00415 else { 00416 printf("TLEN error in SDNA file\n"); 00417 return; 00418 } 00419 if(sdna->nr_types & 1) sp++; /* prevent BUS error */ 00420 00421 /* load struct array */ 00422 data= (int *)sp; 00423 strcpy(str, "STRC"); 00424 if( *data == *verg ) { 00425 data++; 00426 00427 if(do_endian_swap) sdna->nr_structs= le_int(*data); 00428 else sdna->nr_structs= *data; 00429 00430 data++; 00431 sdna->structs= MEM_callocN( sizeof(void *)*sdna->nr_structs, "sdnastrcs"); 00432 } 00433 else { 00434 printf("STRC error in SDNA file\n"); 00435 return; 00436 } 00437 00438 nr= 0; 00439 sp= (short *)data; 00440 while(nr<sdna->nr_structs) { 00441 sdna->structs[nr]= sp; 00442 00443 if(do_endian_swap) { 00444 short a; 00445 00446 sp[0]= le_short(sp[0]); 00447 sp[1]= le_short(sp[1]); 00448 00449 a= sp[1]; 00450 sp+= 2; 00451 while(a--) { 00452 sp[0]= le_short(sp[0]); 00453 sp[1]= le_short(sp[1]); 00454 sp+= 2; 00455 } 00456 } 00457 else { 00458 sp+= 2*sp[1]+2; 00459 } 00460 00461 nr++; 00462 } 00463 00464 /* finally pointerlen: use struct ListBase to test it, never change the size of it! */ 00465 sp= findstruct_name(sdna, "ListBase"); 00466 /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */ 00467 00468 sdna->pointerlen= sdna->typelens[ sp[0] ]/2; 00469 00470 if(sp[1]!=2 || (sdna->pointerlen!=4 && sdna->pointerlen!=8)) { 00471 printf("ListBase struct error! Needs it to calculate pointerize.\n"); 00472 exit(0); 00473 /* well, at least sizeof(ListBase) is error proof! (ton) */ 00474 } 00475 00476 /* second part of gravity problem, setting "gravity" type to void */ 00477 if(gravity_fix > -1) { 00478 for(nr=0; nr<sdna->nr_structs; nr++) { 00479 sp= sdna->structs[nr]; 00480 if(strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) 00481 sp[10]= 9; 00482 } 00483 } 00484 } 00485 } 00486 00487 SDNA *DNA_sdna_from_data(void *data, int datalen, int do_endian_swap) 00488 { 00489 SDNA *sdna= MEM_mallocN(sizeof(*sdna), "sdna"); 00490 00491 sdna->lastfind= 0; 00492 00493 sdna->datalen= datalen; 00494 sdna->data= MEM_mallocN(datalen, "sdna_data"); 00495 memcpy(sdna->data, data, datalen); 00496 00497 init_structDNA(sdna, do_endian_swap); 00498 00499 return sdna; 00500 } 00501 00502 /* ******************** END READ DNA ********************** */ 00503 00504 /* ******************* HANDLE DNA ***************** */ 00505 00506 static void recurs_test_compflags(SDNA *sdna, char *compflags, int structnr) 00507 { 00508 int a, b, typenr, elems; 00509 short *sp; 00510 const char *cp; 00511 00512 /* check all structs, test if it's inside another struct */ 00513 sp= sdna->structs[structnr]; 00514 typenr= sp[0]; 00515 00516 for(a=0; a<sdna->nr_structs; a++) { 00517 if(a!=structnr && compflags[a]==1) { 00518 sp= sdna->structs[a]; 00519 elems= sp[1]; 00520 sp+= 2; 00521 for(b=0; b<elems; b++, sp+=2) { 00522 if(sp[0]==typenr) { 00523 cp= sdna->names[ sp[1] ]; 00524 if(!ispointer(cp)) { 00525 compflags[a]= 2; 00526 recurs_test_compflags(sdna, compflags, a); 00527 } 00528 } 00529 } 00530 } 00531 } 00532 00533 } 00534 00535 /* Unsure of exact function - compares the sdna argument to 00536 * newsdna and sets up the information necessary to convert 00537 * data written with a dna of oldsdna to inmemory data with a 00538 * structure defined by the newsdna sdna (I think). -zr 00539 */ 00540 00541 /* well, the function below is just a lookup table to speed 00542 * up reading files. doh! -ton 00543 */ 00544 00545 00546 char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna) 00547 { 00548 /* flag: 0: doesn't exist anymore (or not yet) 00549 * 1: is equal 00550 * 2: is different 00551 */ 00552 int a, b; 00553 short *spold, *spcur; 00554 const char *str1, *str2; 00555 char *compflags; 00556 00557 if(sdna->nr_structs==0) { 00558 printf("error: file without SDNA\n"); 00559 return NULL; 00560 } 00561 00562 compflags= MEM_callocN(sdna->nr_structs, "compflags"); 00563 00564 /* we check all structs in 'sdna' and compare them with 00565 * the structs in 'newsdna' 00566 */ 00567 00568 for(a=0; a<sdna->nr_structs; a++) { 00569 spold= sdna->structs[a]; 00570 00571 /* search for type in cur */ 00572 spcur= findstruct_name(newsdna, sdna->types[spold[0]]); 00573 00574 if(spcur) { 00575 compflags[a]= 2; 00576 00577 /* compare length and amount of elems */ 00578 if( spcur[1] == spold[1]) { 00579 if( newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]] ) { 00580 00581 /* same length, same amount of elems, now per type and name */ 00582 b= spold[1]; 00583 spold+= 2; 00584 spcur+= 2; 00585 while(b > 0) { 00586 str1= newsdna->types[spcur[0]]; 00587 str2= sdna->types[spold[0]]; 00588 if(strcmp(str1, str2)!=0) break; 00589 00590 str1= newsdna->names[spcur[1]]; 00591 str2= sdna->names[spold[1]]; 00592 if(strcmp(str1, str2)!=0) break; 00593 00594 /* same type and same name, now pointersize */ 00595 if(ispointer(str1)) { 00596 if(sdna->pointerlen!=newsdna->pointerlen) break; 00597 } 00598 00599 b--; 00600 spold+= 2; 00601 spcur+= 2; 00602 } 00603 if(b==0) compflags[a]= 1; 00604 00605 } 00606 } 00607 00608 } 00609 } 00610 00611 /* first struct in util.h is struct Link, this is skipped in compflags (als # 0). 00612 * was a bug, and this way dirty patched! Solve this later.... 00613 */ 00614 compflags[0]= 1; 00615 00616 /* Because structs can be inside structs, we recursively 00617 * set flags when a struct is altered 00618 */ 00619 for(a=0; a<sdna->nr_structs; a++) { 00620 if(compflags[a]==2) recurs_test_compflags(sdna, compflags, a); 00621 } 00622 00623 /* 00624 for(a=0; a<sdna->nr_structs; a++) { 00625 if(compflags[a]==2) { 00626 spold= sdna->structs[a]; 00627 printf("changed: %s\n", sdna->types[ spold[0] ]); 00628 } 00629 } 00630 */ 00631 00632 return compflags; 00633 } 00634 00635 static void cast_elem(char *ctype, char *otype, const char *name, char *curdata, char *olddata) 00636 { 00637 double val = 0.0; 00638 int arrlen, curlen=1, oldlen=1, ctypenr, otypenr; 00639 00640 arrlen= DNA_elem_array_size(name, strlen(name)); 00641 00642 /* define otypenr */ 00643 if(strcmp(otype, "char")==0 || (strcmp(otype, "const char")==0)) otypenr= 0; 00644 else if((strcmp(otype, "uchar")==0) || (strcmp(otype, "unsigned char")==0)) otypenr= 1; 00645 else if(strcmp(otype, "short")==0) otypenr= 2; 00646 else if((strcmp(otype, "ushort")==0)||(strcmp(otype, "unsigned short")==0)) otypenr= 3; 00647 else if(strcmp(otype, "int")==0) otypenr= 4; 00648 else if(strcmp(otype, "long")==0) otypenr= 5; 00649 else if((strcmp(otype, "ulong")==0)||(strcmp(otype, "unsigned long")==0)) otypenr= 6; 00650 else if(strcmp(otype, "float")==0) otypenr= 7; 00651 else if(strcmp(otype, "double")==0) otypenr= 8; 00652 else return; 00653 00654 /* define ctypenr */ 00655 if(strcmp(ctype, "char")==0) ctypenr= 0; 00656 else if(strcmp(ctype, "const char")==0) ctypenr= 0; 00657 else if((strcmp(ctype, "uchar")==0)||(strcmp(ctype, "unsigned char")==0)) ctypenr= 1; 00658 else if(strcmp(ctype, "short")==0) ctypenr= 2; 00659 else if((strcmp(ctype, "ushort")==0)||(strcmp(ctype, "unsigned short")==0)) ctypenr= 3; 00660 else if(strcmp(ctype, "int")==0) ctypenr= 4; 00661 else if(strcmp(ctype, "long")==0) ctypenr= 5; 00662 else if((strcmp(ctype, "ulong")==0)||(strcmp(ctype, "unsigned long")==0)) ctypenr= 6; 00663 else if(strcmp(ctype, "float")==0) ctypenr= 7; 00664 else if(strcmp(ctype, "double")==0) ctypenr= 8; 00665 else return; 00666 00667 /* define lengths */ 00668 if(otypenr < 2) oldlen= 1; 00669 else if(otypenr < 4) oldlen= 2; 00670 else if(otypenr < 8) oldlen= 4; 00671 else oldlen= 8; 00672 00673 if(ctypenr < 2) curlen= 1; 00674 else if(ctypenr < 4) curlen= 2; 00675 else if(ctypenr < 8) curlen= 4; 00676 else curlen= 8; 00677 00678 while(arrlen>0) { 00679 switch(otypenr) { 00680 case 0: 00681 val= *olddata; break; 00682 case 1: 00683 val= *( (unsigned char *)olddata); break; 00684 case 2: 00685 val= *( (short *)olddata); break; 00686 case 3: 00687 val= *( (unsigned short *)olddata); break; 00688 case 4: 00689 val= *( (int *)olddata); break; 00690 case 5: 00691 val= *( (int *)olddata); break; 00692 case 6: 00693 val= *( (unsigned int *)olddata); break; 00694 case 7: 00695 val= *( (float *)olddata); break; 00696 case 8: 00697 val= *( (double *)olddata); break; 00698 } 00699 00700 switch(ctypenr) { 00701 case 0: 00702 *curdata= val; break; 00703 case 1: 00704 *( (unsigned char *)curdata)= val; break; 00705 case 2: 00706 *( (short *)curdata)= val; break; 00707 case 3: 00708 *( (unsigned short *)curdata)= val; break; 00709 case 4: 00710 *( (int *)curdata)= val; break; 00711 case 5: 00712 *( (int *)curdata)= val; break; 00713 case 6: 00714 *( (unsigned int *)curdata)= val; break; 00715 case 7: 00716 if(otypenr<2) val/= 255; 00717 *( (float *)curdata)= val; break; 00718 case 8: 00719 if(otypenr<2) val/= 255; 00720 *( (double *)curdata)= val; break; 00721 } 00722 00723 olddata+= oldlen; 00724 curdata+= curlen; 00725 arrlen--; 00726 } 00727 } 00728 00729 static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, char *olddata) 00730 { 00731 #ifdef WIN32 00732 __int64 lval; 00733 #else 00734 long long lval; 00735 #endif 00736 int arrlen; 00737 00738 arrlen= DNA_elem_array_size(name, strlen(name)); 00739 00740 while(arrlen>0) { 00741 00742 if(curlen==oldlen) { 00743 memcpy(curdata, olddata, curlen); 00744 } 00745 else if(curlen==4 && oldlen==8) { 00746 #ifdef WIN32 00747 lval= *( (__int64 *)olddata ); 00748 #else 00749 lval= *( (long long *)olddata ); 00750 #endif 00751 *((int *)curdata) = lval>>3; /* is of course gambling! */ 00752 } 00753 else if(curlen==8 && oldlen==4) { 00754 #ifdef WIN32 00755 *( (__int64 *)curdata ) = *((int *)olddata); 00756 #else 00757 *( (long long *)curdata ) = *((int *)olddata); 00758 #endif 00759 } 00760 else { 00761 /* for debug */ 00762 printf("errpr: illegal pointersize! \n"); 00763 } 00764 00765 olddata+= oldlen; 00766 curdata+= curlen; 00767 arrlen--; 00768 00769 } 00770 } 00771 00772 static int elem_strcmp(const char *name, const char *oname) 00773 { 00774 int a=0; 00775 00776 /* strcmp without array part */ 00777 00778 while(1) { 00779 if(name[a] != oname[a]) return 1; 00780 if(name[a]=='[') break; 00781 if(name[a]==0) break; 00782 a++; 00783 } 00784 if(name[a] != oname[a]) return 1; 00785 return 0; 00786 } 00787 00788 static char *find_elem(SDNA *sdna, const char *type, const char *name, short *old, char *olddata, short **sppo) 00789 { 00790 int a, elemcount, len; 00791 const char *otype, *oname; 00792 00793 /* without arraypart, so names can differ: return old namenr and type */ 00794 00795 /* in old is the old struct */ 00796 elemcount= old[1]; 00797 old+= 2; 00798 for(a=0; a<elemcount; a++, old+=2) { 00799 00800 otype= sdna->types[old[0]]; 00801 oname= sdna->names[old[1]]; 00802 00803 len= elementsize(sdna, old[0], old[1]); 00804 00805 if( elem_strcmp(name, oname)==0 ) { /* naam equal */ 00806 if( strcmp(type, otype)==0 ) { /* type equal */ 00807 if(sppo) *sppo= old; 00808 return olddata; 00809 } 00810 00811 return NULL; 00812 } 00813 00814 olddata+= len; 00815 } 00816 return NULL; 00817 } 00818 00819 static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna, char *type, const char *name, char *curdata, short *old, char *olddata) 00820 { 00821 /* rules: test for NAME: 00822 - name equal: 00823 - cast type 00824 - name partially equal (array differs) 00825 - type equal: memcpy 00826 - types casten 00827 (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where 00828 can I force this?) 00829 */ 00830 int a, elemcount, len, array, oldsize, cursize, mul; 00831 char *otype; 00832 const char *oname, *cp; 00833 00834 /* is 'name' an array? */ 00835 cp= name; 00836 array= 0; 00837 while( *cp && *cp!='[') { 00838 cp++; array++; 00839 } 00840 if( *cp!= '[' ) array= 0; 00841 00842 /* in old is the old struct */ 00843 elemcount= old[1]; 00844 old+= 2; 00845 for(a=0; a<elemcount; a++, old+=2) { 00846 otype= oldsdna->types[old[0]]; 00847 oname= oldsdna->names[old[1]]; 00848 len= elementsize(oldsdna, old[0], old[1]); 00849 00850 if( strcmp(name, oname)==0 ) { /* name equal */ 00851 00852 if(ispointer(name)) { /* pointer of functionpointer afhandelen */ 00853 cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata); 00854 } 00855 else if( strcmp(type, otype)==0 ) { /* type equal */ 00856 memcpy(curdata, olddata, len); 00857 } 00858 else cast_elem(type, otype, name, curdata, olddata); 00859 00860 return; 00861 } 00862 else if(array) { /* name is an array */ 00863 00864 if(oname[array]=='[' && strncmp(name, oname, array)==0 ) { /* basis equal */ 00865 00866 cursize= DNA_elem_array_size(name, strlen(name)); 00867 oldsize= DNA_elem_array_size(oname, strlen(oname)); 00868 00869 if(ispointer(name)) { /* handle pointer or functionpointer */ 00870 if(cursize>oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata); 00871 else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata); 00872 } 00873 else if(name[0]=='*' || strcmp(type, otype)==0 ) { /* type equal */ 00874 mul= len/oldsize; 00875 mul*= (cursize < oldsize)? cursize: oldsize; 00876 memcpy(curdata, olddata, mul); 00877 00878 /* terminate strings */ 00879 if(oldsize > cursize && strcmp(type, "char")==0) 00880 curdata[mul-1]= 0; 00881 } 00882 else { 00883 if(cursize>oldsize) cast_elem(type, otype, oname, curdata, olddata); 00884 else cast_elem(type, otype, name, curdata, olddata); 00885 } 00886 return; 00887 } 00888 } 00889 olddata+= len; 00890 } 00891 } 00892 00893 static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur) 00894 { 00895 /* Recursive! 00896 * Per element from cur_struct, read data from old_struct. 00897 * If element is a struct, call recursive. 00898 */ 00899 int a, elemcount, elen, eleno, mul, mulo, firststructtypenr; 00900 short *spo, *spc, *sppo; 00901 char *type, *cpo, *cpc; 00902 const char *name, *nameo; 00903 00904 if(oldSDNAnr== -1) return; 00905 if(curSDNAnr== -1) return; 00906 00907 if( compflags[oldSDNAnr]==1 ) { /* if recursive: test for equal */ 00908 00909 spo= oldsdna->structs[oldSDNAnr]; 00910 elen= oldsdna->typelens[ spo[0] ]; 00911 memcpy( cur, data, elen); 00912 00913 return; 00914 } 00915 00916 firststructtypenr= *(newsdna->structs[0]); 00917 00918 spo= oldsdna->structs[oldSDNAnr]; 00919 spc= newsdna->structs[curSDNAnr]; 00920 00921 elemcount= spc[1]; 00922 00923 spc+= 2; 00924 cpc= cur; 00925 for(a=0; a<elemcount; a++, spc+=2) { 00926 type= newsdna->types[spc[0]]; 00927 name= newsdna->names[spc[1]]; 00928 00929 elen= elementsize(newsdna, spc[0], spc[1]); 00930 00931 /* test: is type a struct? */ 00932 if(spc[0]>=firststructtypenr && !ispointer(name)) { 00933 00934 /* where does the old struct data start (and is there an old one?) */ 00935 cpo= find_elem(oldsdna, type, name, spo, data, &sppo); 00936 00937 if(cpo) { 00938 oldSDNAnr= DNA_struct_find_nr(oldsdna, type); 00939 curSDNAnr= DNA_struct_find_nr(newsdna, type); 00940 00941 /* array! */ 00942 mul= DNA_elem_array_size(name, strlen(name)); 00943 nameo= oldsdna->names[sppo[1]]; 00944 mulo= DNA_elem_array_size(nameo, strlen(nameo)); 00945 00946 eleno= elementsize(oldsdna, sppo[0], sppo[1]); 00947 00948 elen/= mul; 00949 eleno/= mulo; 00950 00951 while(mul--) { 00952 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc); 00953 cpo+= eleno; 00954 cpc+= elen; 00955 00956 /* new struct array larger than old */ 00957 mulo--; 00958 if(mulo<=0) break; 00959 } 00960 } 00961 else cpc+= elen; 00962 } 00963 else { 00964 00965 reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data); 00966 cpc+= elen; 00967 00968 } 00969 } 00970 } 00971 00972 void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data) 00973 { 00974 /* Recursive! 00975 * If element is a struct, call recursive. 00976 */ 00977 int a, mul, elemcount, elen, elena, firststructtypenr; 00978 short *spo, *spc, skip; 00979 char *type, *cpo, *cur, cval; 00980 const char *name; 00981 00982 if(oldSDNAnr== -1) return; 00983 firststructtypenr= *(oldsdna->structs[0]); 00984 00985 spo= spc= oldsdna->structs[oldSDNAnr]; 00986 00987 elemcount= spo[1]; 00988 00989 spc+= 2; 00990 cur= data; 00991 00992 for(a=0; a<elemcount; a++, spc+=2) { 00993 type= oldsdna->types[spc[0]]; 00994 name= oldsdna->names[spc[1]]; 00995 00996 /* elementsize = including arraysize */ 00997 elen= elementsize(oldsdna, spc[0], spc[1]); 00998 00999 /* test: is type a struct? */ 01000 if(spc[0]>=firststructtypenr && !ispointer(name)) { 01001 /* where does the old data start (is there one?) */ 01002 cpo= find_elem(oldsdna, type, name, spo, data, NULL); 01003 if(cpo) { 01004 oldSDNAnr= DNA_struct_find_nr(oldsdna, type); 01005 01006 mul= DNA_elem_array_size(name, strlen(name)); 01007 elena= elen/mul; 01008 01009 while(mul--) { 01010 DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo); 01011 cpo += elena; 01012 } 01013 } 01014 } 01015 else { 01016 01017 if(ispointer(name)) { 01018 if(oldsdna->pointerlen==8) { 01019 01020 mul= DNA_elem_array_size(name, strlen(name)); 01021 cpo= cur; 01022 while(mul--) { 01023 cval= cpo[0]; cpo[0]= cpo[7]; cpo[7]= cval; 01024 cval= cpo[1]; cpo[1]= cpo[6]; cpo[6]= cval; 01025 cval= cpo[2]; cpo[2]= cpo[5]; cpo[5]= cval; 01026 cval= cpo[3]; cpo[3]= cpo[4]; cpo[4]= cval; 01027 01028 cpo+= 8; 01029 } 01030 01031 } 01032 } 01033 else { 01034 01035 if( spc[0]==2 || spc[0]==3 ) { /* short-ushort */ 01036 01037 /* exception: variable called blocktype/ipowin: derived from ID_ */ 01038 skip= 0; 01039 if(name[0]=='b' && name[1]=='l') { 01040 if(strcmp(name, "blocktype")==0) skip= 1; 01041 } 01042 else if(name[0]=='i' && name[1]=='p') { 01043 if(strcmp(name, "ipowin")==0) skip= 1; 01044 } 01045 01046 if(skip==0) { 01047 mul= DNA_elem_array_size(name, strlen(name)); 01048 cpo= cur; 01049 while(mul--) { 01050 cval= cpo[0]; 01051 cpo[0]= cpo[1]; 01052 cpo[1]= cval; 01053 cpo+= 2; 01054 } 01055 } 01056 } 01057 else if(spc[0]>3 && spc[0]<8) { /* int-long-ulong-float */ 01058 01059 mul= DNA_elem_array_size(name, strlen(name)); 01060 cpo= cur; 01061 while(mul--) { 01062 cval= cpo[0]; 01063 cpo[0]= cpo[3]; 01064 cpo[3]= cval; 01065 cval= cpo[1]; 01066 cpo[1]= cpo[2]; 01067 cpo[2]= cval; 01068 cpo+= 4; 01069 } 01070 } 01071 } 01072 } 01073 cur+= elen; 01074 } 01075 } 01076 01077 void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data) 01078 { 01079 int a, curSDNAnr, curlen=0, oldlen; 01080 short *spo, *spc; 01081 char *cur, *type, *cpc, *cpo; 01082 01083 /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */ 01084 spo= oldsdna->structs[oldSDNAnr]; 01085 type= oldsdna->types[ spo[0] ]; 01086 oldlen= oldsdna->typelens[ spo[0] ]; 01087 curSDNAnr= DNA_struct_find_nr(newsdna, type); 01088 01089 /* init data and alloc */ 01090 if(curSDNAnr >= 0) { 01091 spc= newsdna->structs[curSDNAnr]; 01092 curlen= newsdna->typelens[ spc[0] ]; 01093 } 01094 if(curlen==0) { 01095 return NULL; 01096 } 01097 01098 cur= MEM_callocN( blocks*curlen, "reconstruct"); 01099 cpc= cur; 01100 cpo= data; 01101 for(a=0; a<blocks; a++) { 01102 reconstruct_struct(newsdna, oldsdna, compflags, oldSDNAnr, cpo, curSDNAnr, cpc); 01103 cpc+= curlen; 01104 cpo+= oldlen; 01105 } 01106 01107 return cur; 01108 } 01109 01110 int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name) 01111 { 01112 01113 int SDNAnr= DNA_struct_find_nr(sdna, stype); 01114 short *spo= sdna->structs[SDNAnr]; 01115 char *cp= find_elem(sdna, vartype, name, spo, NULL, NULL); 01116 return (int)((intptr_t)cp); 01117 } 01118