Bullet Collision Detection & Physics Library
bDNA.cpp
Go to the documentation of this file.
1/*
2bParse
3Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15#include <assert.h>
16
17#include "bDNA.h"
18#include "bChunk.h"
19#include <string.h>
20#include <stdlib.h>
21#include <stdio.h>
22
23//this define will force traversal of structures, to check backward (and forward) compatibility
24//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
25
26
27using namespace bParse;
28
29
30// ----------------------------------------------------- //
31bDNA::bDNA()
32 : mPtrLen(0)
33{
34 // --
35}
36
37// ----------------------------------------------------- //
39{
40 // --
41}
42
43// ----------------------------------------------------- //
45{
46 return ( m_Names.size() < file->m_Names.size());
47}
48
49// ----------------------------------------------------- //
50char *bDNA::getName(int ind)
51{
52 assert(ind <= (int)m_Names.size());
53 return m_Names[ind].m_name;
54}
55
56
57// ----------------------------------------------------- //
58char *bDNA::getType(int ind)
59{
60 assert(ind<= (int)mTypes.size());
61 return mTypes[ind];
62}
63
64
65// ----------------------------------------------------- //
66short *bDNA::getStruct(int ind)
67{
68 assert(ind <= (int)mStructs.size());
69 return mStructs[ind];
70}
71
72
73// ----------------------------------------------------- //
74short bDNA::getLength(int ind)
75{
76 assert(ind <= (int)mTlens.size());
77 return mTlens[ind];
78}
79
80
81// ----------------------------------------------------- //
82int bDNA::getReverseType(short type)
83{
84
85 int* intPtr = mStructReverse.find(type);
86 if (intPtr)
87 return *intPtr;
88
89 return -1;
90}
91
92// ----------------------------------------------------- //
93int bDNA::getReverseType(const char *type)
94{
95
96 btHashString key(type);
97 int* valuePtr = mTypeLookup.find(key);
98 if (valuePtr)
99 return *valuePtr;
100
101 return -1;
102}
103
104// ----------------------------------------------------- //
106{
107 return (int)mStructs.size();
108}
109
110// ----------------------------------------------------- //
111bool bDNA::flagNotEqual(int dna_nr)
112{
113 assert(dna_nr <= (int)mCMPFlags.size());
114 return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
115}
116
117// ----------------------------------------------------- //
118bool bDNA::flagEqual(int dna_nr)
119{
120 assert(dna_nr <= (int)mCMPFlags.size());
121 int flag = mCMPFlags[dna_nr];
122 return flag == FDF_STRUCT_EQU;
123}
124
125// ----------------------------------------------------- //
126bool bDNA::flagNone(int dna_nr)
127{
128 assert(dna_nr <= (int)mCMPFlags.size());
129 return mCMPFlags[dna_nr] == FDF_NONE;
130}
131
132// ----------------------------------------------------- //
134{
135 return mPtrLen;
136}
137
138// ----------------------------------------------------- //
140{
141 // iter is FDF_STRUCT_NEQU
142
143 short *oldStrc = mStructs[iter];
144 short type = oldStrc[0];
145
146 for (int i=0; i<(int)mStructs.size(); i++)
147 {
148 if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
149 {
150 short *curStruct = mStructs[i];
151 int eleLen = curStruct[1];
152 curStruct+=2;
153
154 for (int j=0; j<eleLen; j++, curStruct+=2)
155 {
156 if (curStruct[0] == type)
157 {
158 //char *name = m_Names[curStruct[1]].m_name;
159 //if (name[0] != '*')
160 if (m_Names[curStruct[1]].m_isPointer)
161 {
164 }
165 }
166 }
167 }
168 }
169}
170
171// ----------------------------------------------------- //
173{
174
175 // compare the file to memory
176 // this ptr should be the file data
177
178
179 assert(!(m_Names.size() == 0));//DNA empty!
180
181 mCMPFlags.resize(mStructs.size(), FDF_NONE);
182
183
184
185 int i;
186 for ( i=0; i<(int)mStructs.size(); i++)
187 {
188 short *oldStruct = mStructs[i];
189
190 int oldLookup = getReverseType(oldStruct[0]);
191 if (oldLookup == -1)
192 {
193 mCMPFlags[i] = FDF_NONE;
194 continue;
195 }
196 //char* typeName = mTypes[oldStruct[0]];
197
198//#define SLOW_FORWARD_COMPATIBLE 1
199#ifdef SLOW_FORWARD_COMPATIBLE
200 char* typeName = mTypes[oldLookup];
201 int newLookup = memDNA->getReverseType(typeName);
202 if (newLookup == -1)
203 {
204 mCMPFlags[i] = FDF_NONE;
205 continue;
206 }
207 short *curStruct = memDNA->mStructs[newLookup];
208#else
209 // memory for file
210
211 if (oldLookup < memDNA->mStructs.size())
212 {
213 short *curStruct = memDNA->mStructs[oldLookup];
214#endif
215
216
217
218 // rebuild...
220
221#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
222
223 if (curStruct[1] == oldStruct[1])
224 {
225 // type len same ...
226 if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
227 {
228 bool isSame = true;
229 int elementLength = oldStruct[1];
230
231
232 curStruct+=2;
233 oldStruct+=2;
234
235
236 for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
237 {
238 // type the same
239 //const char* typeFileDNA = mTypes[oldStruct[0]];
240 //const char* typeMemDNA = mTypes[curStruct[0]];
241 if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
242 {
243 isSame=false;
244 break;
245 }
246
247 // name the same
248 if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
249 {
250 isSame=false;
251 break;
252 }
253 }
254 // flag valid ==
255 if (isSame)
257 }
258 }
259#endif
260 }
261 }
262
263
264
265
266
267 // recurse in
268 for ( i=0; i<(int)mStructs.size(); i++)
269 {
270 if (mCMPFlags[i] == FDF_STRUCT_NEQU)
272 }
273}
274
275
276
277
278static int name_is_array(char* name, int* dim1, int* dim2) {
279 int len = strlen(name);
280 /*fprintf(stderr,"[%s]",name);*/
281 /*if (len >= 1) {
282 if (name[len-1] != ']')
283 return 1;
284 }
285 return 0;*/
286 char *bp;
287 int num;
288 if (dim1) {
289 *dim1 = 1;
290 }
291 if (dim2) {
292 *dim2 = 1;
293 }
294 bp = strchr(name, '[');
295 if (!bp) {
296 return 0;
297 }
298 num = 0;
299 while (++bp < name+len-1) {
300 const char c = *bp;
301 if (c == ']') {
302 break;
303 }
304 if (c <= '9' && c >= '0') {
305 num *= 10;
306 num += (c - '0');
307 } else {
308 printf("array parse error.\n");
309 return 0;
310 }
311 }
312 if (dim2) {
313 *dim2 = num;
314 }
315
316 /* find second dim, if any. */
317 bp = strchr(bp, '[');
318 if (!bp) {
319 return 1; /* at least we got the first dim. */
320 }
321 num = 0;
322 while (++bp < name+len-1) {
323 const char c = *bp;
324 if (c == ']') {
325 break;
326 }
327 if (c <= '9' && c >= '0') {
328 num *= 10;
329 num += (c - '0');
330 } else {
331 printf("array2 parse error.\n");
332 return 1;
333 }
334 }
335 if (dim1) {
336 if (dim2) {
337 *dim1 = *dim2;
338 *dim2 = num;
339 } else {
340 *dim1 = num;
341 }
342 }
343
344 return 1;
345}
346
347
348// ----------------------------------------------------- //
349void bDNA::init(char *data, int len, bool swap)
350{
351 int *intPtr=0;short *shtPtr=0;
352 char *cp = 0;int dataLen =0;
353 //long nr=0;
354 intPtr = (int*)data;
355
356 /*
357 SDNA (4 bytes) (magic number)
358 NAME (4 bytes)
359 <nr> (4 bytes) amount of names (int)
360 <string>
361 <string>
362 */
363
364 if (strncmp(data, "SDNA", 4)==0)
365 {
366 // skip ++ NAME
367 intPtr++; intPtr++;
368 }
369
370
371
372 // Parse names
373 if (swap)
374 {
375 *intPtr = ChunkUtils::swapInt(*intPtr);
376 }
377 dataLen = *intPtr;
378 intPtr++;
379
380 cp = (char*)intPtr;
381 int i;
382 for ( i=0; i<dataLen; i++)
383 {
384 bNameInfo info;
385 info.m_name = cp;
386 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
387 name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
388 m_Names.push_back(info);
389 while (*cp)cp++;
390 cp++;
391 }
392
393
394
395 cp = btAlignPointer(cp,4);
396
397 /*
398 TYPE (4 bytes)
399 <nr> amount of types (int)
400 <string>
401 <string>
402 */
403
404 intPtr = (int*)cp;
405 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
406
407 if (swap)
408 {
409 *intPtr = ChunkUtils::swapInt(*intPtr);
410 }
411 dataLen = *intPtr;
412 intPtr++;
413
414 cp = (char*)intPtr;
415 for ( i=0; i<dataLen; i++)
416 {
417 mTypes.push_back(cp);
418 while (*cp)cp++;
419 cp++;
420 }
421
422 cp = btAlignPointer(cp,4);
423
424 /*
425 TLEN (4 bytes)
426 <len> (short) the lengths of types
427 <len>
428 */
429
430 // Parse type lens
431 intPtr = (int*)cp;
432 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
433
434 dataLen = (int)mTypes.size();
435
436 shtPtr = (short*)intPtr;
437 for ( i=0; i<dataLen; i++, shtPtr++)
438 {
439 if (swap)
440 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
441 mTlens.push_back(shtPtr[0]);
442 }
443
444 if (dataLen & 1) shtPtr++;
445
446 /*
447 STRC (4 bytes)
448 <nr> amount of structs (int)
449 <typenr>
450 <nr_of_elems>
451 <typenr>
452 <namenr>
453 <typenr>
454 <namenr>
455 */
456
457 intPtr = (int*)shtPtr;
458 cp = (char*)intPtr;
459 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
460
461 if (swap)
462 {
463 *intPtr = ChunkUtils::swapInt(*intPtr);
464 }
465 dataLen = *intPtr;
466 intPtr++;
467
468
469 shtPtr = (short*)intPtr;
470 for ( i=0; i<dataLen; i++)
471 {
472 mStructs.push_back (shtPtr);
473 if (swap)
474 {
475 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
476 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
477
478 int len = shtPtr[1];
479 shtPtr+= 2;
480
481 for (int a=0; a<len; a++, shtPtr+=2)
482 {
483 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
484 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
485 }
486 }
487 else
488 shtPtr+= (2*shtPtr[1])+2;
489 }
490
491
492 // build reverse lookups
493 for ( i=0; i<(int)mStructs.size(); i++)
494 {
495 short *strc = mStructs.at(i);
496 if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
497 {
498 mPtrLen = mTlens[strc[0]]/2;
499 }
500
501 mStructReverse.insert(strc[0], i);
502 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
503 }
504}
505
506
507// ----------------------------------------------------- //
508int bDNA::getArraySize(char* string)
509{
510 int ret = 1;
511 int len = strlen(string);
512
513
514 char* next = 0;
515 for (int i=0; i<len; i++)
516 {
517 char c = string[i];
518
519 if (c == '[')
520 next = &string[i+1];
521 else if (c==']')
522 if (next)
523 ret *= atoi(next);
524 }
525
526// print (string << ' ' << ret);
527 return ret;
528}
529
530
532{
533 int i;
534
535 int numTypes = mTypes.size();
536
537 for (i=0;i<numTypes;i++)
538 {
539
540 }
541
542 for ( i=0; i<(int)mStructs.size(); i++)
543 {
544 int totalBytes=0;
545 short *oldStruct = mStructs[i];
546
547 int oldLookup = getReverseType(oldStruct[0]);
548 if (oldLookup == -1)
549 {
550 mCMPFlags[i] = FDF_NONE;
551 continue;
552 }
553
554 short* newStruct = mStructs[oldLookup];
555 char* typeName = mTypes[newStruct[0]];
556 printf("%3d: %s ",i,typeName);
557
558 //char *name = mNames[oldStruct[1]];
559 int len = oldStruct[1];
560 printf(" (%d fields) ",len);
561 oldStruct+=2;
562
563 printf("{");
564 int j;
565 for (j=0; j<len; ++j,oldStruct+=2) {
566 const char* name = m_Names[oldStruct[1]].m_name;
567 printf("%s %s", mTypes[oldStruct[0]],name);
568 int elemNumBytes= 0;
569 int arrayDimensions = getArraySizeNew(oldStruct[1]);
570
571 if (m_Names[oldStruct[1]].m_isPointer)
572 {
573 elemNumBytes = VOID_IS_8 ? 8 : 4;
574 } else
575 {
576 elemNumBytes = getLength(oldStruct[0]);
577 }
578 printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
579
580 if (j == len-1) {
581 printf(";}");
582 } else {
583 printf("; ");
584 }
585 totalBytes+=elemNumBytes*arrayDimensions;
586 }
587 printf("\ntotalBytes=%d\n\n",totalBytes);
588
589 }
590
591
592
593#if 0
594 /* dump out display of types and their sizes */
595 for (i=0; i<bf->types_count; ++i) {
596 /* if (!bf->types[i].is_struct)*/
597 {
598 printf("%3d: sizeof(%s%s)=%d",
599 i,
600 bf->types[i].is_struct ? "struct " : "atomic ",
601 bf->types[i].name, bf->types[i].size);
602 if (bf->types[i].is_struct) {
603 int j;
604 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
605 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
606 printf("%s %s",
607 bf->types[bf->types[i].fieldtypes[j]].name,
608 bf->names[bf->types[i].fieldnames[j]]);
609 if (j == bf->types[i].fieldtypes_count-1) {
610 printf(";}");
611 } else {
612 printf("; ");
613 }
614 }
615 }
616 printf("\n\n");
617
618 }
619 }
620#endif
621
622}
623
624
625
626
627//eof
628
629
static int name_is_array(char *name, int *dim1, int *dim2)
Definition: bDNA.cpp:278
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:792
static short swapShort(short sht)
Definition: bChunk.cpp:30
static int swapInt(int inte)
Definition: bChunk.cpp:37
int getArraySizeNew(short name)
Definition: bDNA.h:41
btAlignedObjectArray< int > mCMPFlags
Definition: bDNA.h:92
int getPointerSize()
Definition: bDNA.cpp:133
bool flagNone(int dna_nr)
Definition: bDNA.cpp:126
short getLength(int ind)
Definition: bDNA.cpp:74
int mPtrLen
Definition: bDNA.h:101
btAlignedObjectArray< short * > mStructs
Definition: bDNA.h:96
void initCmpFlags(bDNA *memDNA)
Definition: bDNA.cpp:172
@ FDF_STRUCT_EQU
Definition: bDNA.h:87
@ FDF_NONE
Definition: bDNA.h:85
@ FDF_STRUCT_NEQU
Definition: bDNA.h:86
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:349
void initRecurseCmpFlags(int i)
Definition: bDNA.cpp:139
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
int getNumStructs()
Definition: bDNA.cpp:105
btHashMap< btHashInt, int > mStructReverse
Definition: bDNA.h:98
bool flagNotEqual(int dna_nr)
Definition: bDNA.cpp:111
btAlignedObjectArray< bNameInfo > m_Names
Definition: bDNA.h:94
char * getName(int ind)
Definition: bDNA.cpp:50
void dumpTypeDefinitions()
Definition: bDNA.cpp:531
bool lessThan(bDNA *other)
Definition: bDNA.cpp:44
int getReverseType(short type)
Definition: bDNA.cpp:82
btAlignedObjectArray< short > mTlens
Definition: bDNA.h:97
short * getStruct(int ind)
Definition: bDNA.cpp:66
btAlignedObjectArray< char * > mTypes
Definition: bDNA.h:95
int getArraySize(char *str)
Definition: bDNA.cpp:508
btHashMap< btHashString, int > mTypeLookup
Definition: bDNA.h:99
char * getType(int ind)
Definition: bDNA.cpp:58
Definition: bChunk.h:29
const bool VOID_IS_8
Definition: bChunk.h:89
char * m_name
Definition: bDNA.h:26
bool m_isPointer
Definition: bDNA.h:27
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:24