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