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
26 using namespace bParse;
28 // ----------------------------------------------------- //
35 // ----------------------------------------------------- //
41 // ----------------------------------------------------- //
42 bool bDNA::lessThan(bDNA *file)
44 return (m_Names.size() < file->m_Names.size());
47 // ----------------------------------------------------- //
48 char *bDNA::getName(int ind)
50 assert(ind <= (int)m_Names.size());
51 return m_Names[ind].m_name;
54 // ----------------------------------------------------- //
55 char *bDNA::getType(int ind)
57 assert(ind <= (int)mTypes.size());
61 // ----------------------------------------------------- //
62 short *bDNA::getStruct(int ind)
64 assert(ind <= (int)mStructs.size());
68 // ----------------------------------------------------- //
69 short bDNA::getLength(int ind)
71 assert(ind <= (int)mTlens.size());
75 // ----------------------------------------------------- //
76 int bDNA::getReverseType(short type)
78 int *intPtr = mStructReverse.find(type);
85 // ----------------------------------------------------- //
86 int bDNA::getReverseType(const char *type)
88 b3HashString key(type);
89 int *valuePtr = mTypeLookup.find(key);
96 // ----------------------------------------------------- //
97 int bDNA::getNumStructs()
99 return (int)mStructs.size();
102 // ----------------------------------------------------- //
103 bool bDNA::flagNotEqual(int dna_nr)
105 assert(dna_nr <= (int)mCMPFlags.size());
106 return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
109 // ----------------------------------------------------- //
110 bool bDNA::flagEqual(int dna_nr)
112 assert(dna_nr <= (int)mCMPFlags.size());
113 int flag = mCMPFlags[dna_nr];
114 return flag == FDF_STRUCT_EQU;
117 // ----------------------------------------------------- //
118 bool bDNA::flagNone(int dna_nr)
120 assert(dna_nr <= (int)mCMPFlags.size());
121 return mCMPFlags[dna_nr] == FDF_NONE;
124 // ----------------------------------------------------- //
125 int bDNA::getPointerSize()
130 // ----------------------------------------------------- //
131 void bDNA::initRecurseCmpFlags(int iter)
133 // iter is FDF_STRUCT_NEQU
135 short *oldStrc = mStructs[iter];
136 short type = oldStrc[0];
138 for (int i = 0; i < (int)mStructs.size(); i++)
140 if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
142 short *curStruct = mStructs[i];
143 int eleLen = curStruct[1];
146 for (int j = 0; j < eleLen; j++, curStruct += 2)
148 if (curStruct[0] == type)
150 //char *name = m_Names[curStruct[1]].m_name;
151 //if (name[0] != '*')
152 if (m_Names[curStruct[1]].m_isPointer)
154 mCMPFlags[i] = FDF_STRUCT_NEQU;
155 initRecurseCmpFlags(i);
163 // ----------------------------------------------------- //
164 void bDNA::initCmpFlags(bDNA *memDNA)
166 // compare the file to memory
167 // this ptr should be the file data
169 assert(!(m_Names.size() == 0)); // && "SDNA empty!");
170 mCMPFlags.resize(mStructs.size(), FDF_NONE);
173 for (i = 0; i < (int)mStructs.size(); i++)
175 short *oldStruct = mStructs[i];
177 int oldLookup = getReverseType(oldStruct[0]);
180 mCMPFlags[i] = FDF_NONE;
183 //char* typeName = mTypes[oldStruct[0]];
185 //#define SLOW_FORWARD_COMPATIBLE 1
186 #ifdef SLOW_FORWARD_COMPATIBLE
187 char *typeName = mTypes[oldLookup];
188 int newLookup = memDNA->getReverseType(typeName);
191 mCMPFlags[i] = FDF_NONE;
194 short *curStruct = memDNA->mStructs[newLookup];
198 if (oldLookup < memDNA->mStructs.size())
200 short *curStruct = memDNA->mStructs[oldLookup];
204 mCMPFlags[i] = FDF_STRUCT_NEQU;
206 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
208 if (curStruct[1] == oldStruct[1])
211 if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
214 int elementLength = oldStruct[1];
219 for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
222 //const char* typeFileDNA = mTypes[oldStruct[0]];
223 //const char* typeMemDNA = mTypes[curStruct[0]];
224 if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
231 if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
239 mCMPFlags[i] = FDF_STRUCT_EQU;
247 for (i = 0; i < (int)mStructs.size(); i++)
249 if (mCMPFlags[i] == FDF_STRUCT_NEQU)
250 initRecurseCmpFlags(i);
254 static int name_is_array(char *name, int *dim1, int *dim2)
256 int len = strlen(name);
257 /*fprintf(stderr,"[%s]",name);*/
259 if (name[len-1] != ']')
273 bp = strchr(name, '[');
279 while (++bp < name + len - 1)
286 if (c <= '9' && c >= '0')
293 printf("array parse error.\n");
302 /* find second dim, if any. */
303 bp = strchr(bp, '[');
306 return 1; /* at least we got the first dim. */
309 while (++bp < name + len - 1)
316 if (c <= '9' && c >= '0')
323 printf("array2 parse error.\n");
343 // ----------------------------------------------------- //
344 void bDNA::init(char *data, int len, bool swap)
351 intPtr = (int *)data;
354 SDNA (4 bytes) (magic number)
356 <nr> (4 bytes) amount of names (int)
361 if (strncmp(data, "SDNA", 4) == 0)
371 *intPtr = ChunkUtils::swapInt(*intPtr);
378 for (i = 0; i < dataLen; i++)
382 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
383 name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
384 m_Names.push_back(info);
389 cp = b3AlignPointer(cp, 4);
393 <nr> amount of types (int)
399 assert(strncmp(cp, "TYPE", 4) == 0);
404 *intPtr = ChunkUtils::swapInt(*intPtr);
410 for (i = 0; i < dataLen; i++)
412 mTypes.push_back(cp);
417 cp = b3AlignPointer(cp, 4);
421 <len> (short) the lengths of types
427 assert(strncmp(cp, "TLEN", 4) == 0);
430 dataLen = (int)mTypes.size();
432 shtPtr = (short *)intPtr;
433 for (i = 0; i < dataLen; i++, shtPtr++)
436 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
437 mTlens.push_back(shtPtr[0]);
440 if (dataLen & 1) shtPtr++;
444 <nr> amount of structs (int)
453 intPtr = (int *)shtPtr;
455 assert(strncmp(cp, "STRC", 4) == 0);
460 *intPtr = ChunkUtils::swapInt(*intPtr);
465 shtPtr = (short *)intPtr;
466 for (i = 0; i < dataLen; i++)
468 mStructs.push_back(shtPtr);
471 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
472 shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
477 for (int a = 0; a < len; a++, shtPtr += 2)
479 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
480 shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
484 shtPtr += (2 * shtPtr[1]) + 2;
487 // build reverse lookups
488 for (i = 0; i < (int)mStructs.size(); i++)
490 short *strc = mStructs.at(i);
491 if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
493 mPtrLen = mTlens[strc[0]] / 2;
496 mStructReverse.insert(strc[0], i);
497 mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
501 // ----------------------------------------------------- //
502 int bDNA::getArraySize(char *string)
505 int len = strlen(string);
508 for (int i = 0; i < len; i++)
513 next = &string[i + 1];
519 // print (string << ' ' << ret);
523 void bDNA::dumpTypeDefinitions()
527 int numTypes = mTypes.size();
529 for (i = 0; i < numTypes; i++)
533 for (i = 0; i < (int)mStructs.size(); i++)
536 short *oldStruct = mStructs[i];
538 int oldLookup = getReverseType(oldStruct[0]);
541 mCMPFlags[i] = FDF_NONE;
545 short *newStruct = mStructs[oldLookup];
546 char *typeName = mTypes[newStruct[0]];
547 printf("%3d: %s ", i, typeName);
549 //char *name = mNames[oldStruct[1]];
550 int len = oldStruct[1];
551 printf(" (%d fields) ", len);
556 for (j = 0; j < len; ++j, oldStruct += 2)
558 const char *name = m_Names[oldStruct[1]].m_name;
559 printf("%s %s", mTypes[oldStruct[0]], name);
560 int elemNumBytes = 0;
561 int arrayDimensions = getArraySizeNew(oldStruct[1]);
563 if (m_Names[oldStruct[1]].m_isPointer)
565 elemNumBytes = VOID_IS_8 ? 8 : 4;
569 elemNumBytes = getLength(oldStruct[0]);
571 printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
581 totalBytes += elemNumBytes * arrayDimensions;
583 printf("\ntotalBytes=%d\n\n", totalBytes);
587 /* dump out display of types and their sizes */
588 for (i=0; i<bf->types_count; ++i) {
589 /* if (!bf->types[i].is_struct)*/
591 printf("%3d: sizeof(%s%s)=%d",
593 bf->types[i].is_struct ? "struct " : "atomic ",
594 bf->types[i].name, bf->types[i].size);
595 if (bf->types[i].is_struct) {
597 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
598 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
600 bf->types[bf->types[i].fieldtypes[j]].name,
601 bf->names[bf->types[i].fieldnames[j]]);
602 if (j == bf->types[i].fieldtypes_count-1) {