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