3 Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
23 //this define will force traversal of structures, to check backward (and forward) compatibility
24 //#define TEST_BACKWARD_FORWARD_COMPATIBILITY
27 using namespace bParse;
30 // ----------------------------------------------------- //
37 // ----------------------------------------------------- //
43 // ----------------------------------------------------- //
44 bool bDNA::lessThan(bDNA *file)
46 return ( m_Names.size() < file->m_Names.size());
49 // ----------------------------------------------------- //
50 char *bDNA::getName(int ind)
52 assert(ind <= (int)m_Names.size());
53 return m_Names[ind].m_name;
57 // ----------------------------------------------------- //
58 char *bDNA::getType(int ind)
60 assert(ind<= (int)mTypes.size());
65 // ----------------------------------------------------- //
66 short *bDNA::getStruct(int ind)
68 assert(ind <= (int)mStructs.size());
73 // ----------------------------------------------------- //
74 short bDNA::getLength(int ind)
76 assert(ind <= (int)mTlens.size());
81 // ----------------------------------------------------- //
82 int bDNA::getReverseType(short type)
85 int* intPtr = mStructReverse.find(type);
92 // ----------------------------------------------------- //
93 int bDNA::getReverseType(const char *type)
96 btHashString key(type);
97 int* valuePtr = mTypeLookup.find(key);
104 // ----------------------------------------------------- //
105 int bDNA::getNumStructs()
107 return (int)mStructs.size();
110 // ----------------------------------------------------- //
111 bool bDNA::flagNotEqual(int dna_nr)
113 assert(dna_nr <= (int)mCMPFlags.size());
114 return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
117 // ----------------------------------------------------- //
118 bool bDNA::flagEqual(int dna_nr)
120 assert(dna_nr <= (int)mCMPFlags.size());
121 int flag = mCMPFlags[dna_nr];
122 return flag == FDF_STRUCT_EQU;
125 // ----------------------------------------------------- //
126 bool bDNA::flagNone(int dna_nr)
128 assert(dna_nr <= (int)mCMPFlags.size());
129 return mCMPFlags[dna_nr] == FDF_NONE;
132 // ----------------------------------------------------- //
133 int bDNA::getPointerSize()
138 // ----------------------------------------------------- //
139 void bDNA::initRecurseCmpFlags(int iter)
141 // iter is FDF_STRUCT_NEQU
143 short *oldStrc = mStructs[iter];
144 short type = oldStrc[0];
146 for (int i=0; i<(int)mStructs.size(); i++)
148 if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
150 short *curStruct = mStructs[i];
151 int eleLen = curStruct[1];
154 for (int j=0; j<eleLen; j++, curStruct+=2)
156 if (curStruct[0] == type)
158 //char *name = m_Names[curStruct[1]].m_name;
159 //if (name[0] != '*')
160 if (m_Names[curStruct[1]].m_isPointer)
162 mCMPFlags[i] = FDF_STRUCT_NEQU;
163 initRecurseCmpFlags(i);
171 // ----------------------------------------------------- //
172 void bDNA::initCmpFlags(bDNA *memDNA)
175 // compare the file to memory
176 // this ptr should be the file data
179 assert(!m_Names.size() == 0 && "SDNA empty!");
180 mCMPFlags.resize(mStructs.size(), FDF_NONE);
185 for ( i=0; i<(int)mStructs.size(); i++)
187 short *oldStruct = mStructs[i];
189 int oldLookup = getReverseType(oldStruct[0]);
192 mCMPFlags[i] = FDF_NONE;
195 //char* typeName = mTypes[oldStruct[0]];
197 //#define SLOW_FORWARD_COMPATIBLE 1
198 #ifdef SLOW_FORWARD_COMPATIBLE
199 char* typeName = mTypes[oldLookup];
200 int newLookup = memDNA->getReverseType(typeName);
203 mCMPFlags[i] = FDF_NONE;
206 short *curStruct = memDNA->mStructs[newLookup];
210 if (oldLookup < memDNA->mStructs.size())
212 short *curStruct = memDNA->mStructs[oldLookup];
218 mCMPFlags[i] = FDF_STRUCT_NEQU;
220 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
222 if (curStruct[1] == oldStruct[1])
225 if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
228 int elementLength = oldStruct[1];
235 for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
238 //const char* typeFileDNA = mTypes[oldStruct[0]];
239 //const char* typeMemDNA = mTypes[curStruct[0]];
240 if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
247 if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
255 mCMPFlags[i] = FDF_STRUCT_EQU;
267 for ( i=0; i<(int)mStructs.size(); i++)
269 if (mCMPFlags[i] == FDF_STRUCT_NEQU)
270 initRecurseCmpFlags(i);
277 static int name_is_array(char* name, int* dim1, int* dim2) {
278 int len = strlen(name);
279 /*fprintf(stderr,"[%s]",name);*/
281 if (name[len-1] != ']')
293 bp = strchr(name, '[');
298 while (++bp < name+len-1) {
303 if (c <= '9' && c >= '0') {
307 printf("array parse error.\n");
315 /* find second dim, if any. */
316 bp = strchr(bp, '[');
318 return 1; /* at least we got the first dim. */
321 while (++bp < name+len-1) {
326 if (c <= '9' && c >= '0') {
330 printf("array2 parse error.\n");
347 // ----------------------------------------------------- //
348 void bDNA::init(char *data, int len, bool swap)
350 int *intPtr=0;short *shtPtr=0;
351 char *cp = 0;int dataLen =0;long nr=0;
355 SDNA (4 bytes) (magic number)
357 <nr> (4 bytes) amount of names (int)
362 if (strncmp(data, "SDNA", 4)==0)
371 if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
372 else dataLen = *intPtr;
377 for ( i=0; i<dataLen; i++)
381 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
382 name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
383 m_Names.push_back(info);
402 <nr> amount of types (int)
408 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
410 if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
411 else dataLen = *intPtr;
415 for ( i=0; i<dataLen; i++)
417 mTypes.push_back(cp);
435 <len> (short) the lengths of types
441 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
443 dataLen = (int)mTypes.size();
445 shtPtr = (short*)intPtr;
446 for ( i=0; i<dataLen; i++, shtPtr++)
449 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
450 mTlens.push_back(shtPtr[0]);
453 if (dataLen & 1) shtPtr++;
457 <nr> amount of structs (int)
466 intPtr = (int*)shtPtr;
468 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
470 if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
471 else dataLen = *intPtr;
475 shtPtr = (short*)intPtr;
476 for ( i=0; i<dataLen; i++)
478 mStructs.push_back (shtPtr);
481 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
482 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
487 for (int a=0; a<len; a++, shtPtr+=2)
489 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
490 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
494 shtPtr+= (2*shtPtr[1])+2;
498 // build reverse lookups
499 for ( i=0; i<(int)mStructs.size(); i++)
501 short *strc = mStructs.at(i);
502 if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
504 mPtrLen = mTlens[strc[0]]/2;
507 mStructReverse.insert(strc[0], i);
508 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
513 // ----------------------------------------------------- //
514 int bDNA::getArraySize(char* string)
517 int len = strlen(string);
521 for (int i=0; i<len; i++)
532 // print (string << ' ' << ret);
537 void bDNA::dumpTypeDefinitions()
541 int numTypes = mTypes.size();
543 for (i=0;i<numTypes;i++)
548 for ( i=0; i<(int)mStructs.size(); i++)
551 short *oldStruct = mStructs[i];
553 int oldLookup = getReverseType(oldStruct[0]);
556 mCMPFlags[i] = FDF_NONE;
560 short* newStruct = mStructs[oldLookup];
561 char* typeName = mTypes[newStruct[0]];
562 printf("%3d: %s ",i,typeName);
564 //char *name = mNames[oldStruct[1]];
565 int len = oldStruct[1];
566 printf(" (%d fields) ",len);
571 for (j=0; j<len; ++j,oldStruct+=2) {
572 const char* name = m_Names[oldStruct[1]].m_name;
573 printf("%s %s", mTypes[oldStruct[0]],name);
575 int arrayDimensions = getArraySizeNew(oldStruct[1]);
577 if (m_Names[oldStruct[1]].m_isPointer)
579 elemNumBytes = VOID_IS_8 ? 8 : 4;
582 elemNumBytes = getLength(oldStruct[0]);
584 printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
591 totalBytes+=elemNumBytes*arrayDimensions;
593 printf("\ntotalBytes=%d\n\n",totalBytes);
600 /* dump out display of types and their sizes */
601 for (i=0; i<bf->types_count; ++i) {
602 /* if (!bf->types[i].is_struct)*/
604 printf("%3d: sizeof(%s%s)=%d",
606 bf->types[i].is_struct ? "struct " : "atomic ",
607 bf->types[i].name, bf->types[i].size);
608 if (bf->types[i].is_struct) {
610 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
611 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
613 bf->types[bf->types[i].fieldtypes[j]].name,
614 bf->names[bf->types[i].fieldnames[j]]);
615 if (j == bf->types[i].fieldtypes_count-1) {