Bullet Collision Detection & Physics Library
bDNA.cpp
Go to the documentation of this file.
1 /*
2 bParse
3 Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
4 
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:
10 
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.
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 using namespace bParse;
27 
28 // ----------------------------------------------------- //
30  : mPtrLen(0)
31 {
32  // --
33 }
34 
35 // ----------------------------------------------------- //
37 {
38  // --
39 }
40 
41 // ----------------------------------------------------- //
42 bool bDNA::lessThan(bDNA *file)
43 {
44  return (m_Names.size() < file->m_Names.size());
45 }
46 
47 // ----------------------------------------------------- //
48 char *bDNA::getName(int ind)
49 {
50  assert(ind <= (int)m_Names.size());
51  return m_Names[ind].m_name;
52 }
53 
54 // ----------------------------------------------------- //
55 char *bDNA::getType(int ind)
56 {
57  assert(ind <= (int)mTypes.size());
58  return mTypes[ind];
59 }
60 
61 // ----------------------------------------------------- //
62 short *bDNA::getStruct(int ind)
63 {
64  assert(ind <= (int)mStructs.size());
65  return mStructs[ind];
66 }
67 
68 // ----------------------------------------------------- //
69 short bDNA::getLength(int ind)
70 {
71  assert(ind <= (int)mTlens.size());
72  return mTlens[ind];
73 }
74 
75 // ----------------------------------------------------- //
76 int bDNA::getReverseType(short type)
77 {
78  int *intPtr = mStructReverse.find(type);
79  if (intPtr)
80  return *intPtr;
81 
82  return -1;
83 }
84 
85 // ----------------------------------------------------- //
86 int 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 // ----------------------------------------------------- //
103 bool bDNA::flagNotEqual(int dna_nr)
104 {
105  assert(dna_nr <= (int)mCMPFlags.size());
106  return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
107 }
108 
109 // ----------------------------------------------------- //
110 bool 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 // ----------------------------------------------------- //
118 bool 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
248 for (i = 0; i < (int)mStructs.size(); i++)
249 {
250  if (mCMPFlags[i] == FDF_STRUCT_NEQU)
252 }
253 }
254 
255 static 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 // ----------------------------------------------------- //
345 void 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);
498  mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
499  }
500 }
501 
502 // ----------------------------------------------------- //
503 int 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
bParse::bDNA::getType
char * getType(int ind)
Definition: bDNA.cpp:55
bParse::bDNA::getName
char * getName(int ind)
Definition: bDNA.cpp:48
bParse::bDNA::lessThan
bool lessThan(bDNA *other)
Definition: bDNA.cpp:42
bParse::bDNA::getArraySizeNew
int getArraySizeNew(short name)
Definition: bDNA.h:40
bParse::bDNA::getLength
short getLength(int ind)
Definition: bDNA.cpp:69
bParse::bDNA::initRecurseCmpFlags
void initRecurseCmpFlags(int i)
Definition: bDNA.cpp:131
bParse::bDNA::flagNone
bool flagNone(int dna_nr)
Definition: bDNA.cpp:118
bParse::bDNA::initCmpFlags
void initCmpFlags(bDNA *memDNA)
Definition: bDNA.cpp:164
bParse::bDNA::getNumStructs
int getNumStructs()
Definition: bDNA.cpp:97
bParse::bDNA::FDF_NONE
Definition: bDNA.h:81
bChunk.h
bParse::bNameInfo::m_dim1
int m_dim1
Definition: bDNA.h:28
bParse::bDNA::mTlens
btAlignedObjectArray< short > mTlens
Definition: bDNA.h:93
bParse::bDNA::getReverseType
int getReverseType(short type)
Definition: bDNA.cpp:76
bParse::ChunkUtils::swapInt
static int swapInt(int inte)
Definition: bChunk.cpp:35
bParse::bDNA::dumpTypeDefinitions
void dumpTypeDefinitions()
Definition: bDNA.cpp:524
bParse::bDNA::mPtrLen
int mPtrLen
Definition: bDNA.h:97
bParse::bDNA::FDF_STRUCT_EQU
Definition: bDNA.h:83
bParse::bNameInfo::m_name
char * m_name
Definition: bDNA.h:25
bParse::bDNA
Definition: bDNA.h:31
bParse::bDNA::mStructReverse
btHashMap< btHashInt, int > mStructReverse
Definition: bDNA.h:94
btAlignPointer
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:814
bParse::bDNA::m_Names
btAlignedObjectArray< bNameInfo > m_Names
Definition: bDNA.h:90
btHashString
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:23
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:203
bParse::bNameInfo::m_isPointer
bool m_isPointer
Definition: bDNA.h:26
bParse::bDNA::mTypeLookup
btHashMap< btHashString, int > mTypeLookup
Definition: bDNA.h:95
bParse::VOID_IS_8
const bool VOID_IS_8
Definition: bChunk.h:81
bParse::bDNA::getPointerSize
int getPointerSize()
Definition: bDNA.cpp:125
bParse::bDNA::flagEqual
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:110
bParse::bNameInfo::m_dim0
int m_dim0
Definition: bDNA.h:27
bDNA.h
bParse::bNameInfo
Definition: bDNA.h:23
btHashMap::find
const Value * find(const Key &key) const
Definition: btHashMap.h:424
bParse::bDNA::~bDNA
~bDNA()
Definition: bDNA.cpp:36
bParse::bDNA::mTypes
btAlignedObjectArray< char * > mTypes
Definition: bDNA.h:91
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:264
bParse::bDNA::getArraySize
int getArraySize(char *str)
Definition: bDNA.cpp:503
bParse::bDNA::flagNotEqual
bool flagNotEqual(int dna_nr)
Definition: bDNA.cpp:103
bParse::bDNA::init
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:345
bParse::bDNA::getStruct
short * getStruct(int ind)
Definition: bDNA.cpp:62
bParse
Definition: btBulletWorldImporter.h:23
bParse::bDNA::FDF_STRUCT_NEQU
Definition: bDNA.h:82
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:257
bParse::bDNA::bDNA
bDNA()
Definition: bDNA.cpp:29
bParse::ChunkUtils::swapShort
static short swapShort(short sht)
Definition: bChunk.cpp:28
btAlignedObjectArray::at
const T & at(int n) const
Definition: btAlignedObjectArray.h:147
name_is_array
static int name_is_array(char *name, int *dim1, int *dim2)
Definition: bDNA.cpp:255
bParse::bDNA::mCMPFlags
btAlignedObjectArray< int > mCMPFlags
Definition: bDNA.h:88
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:142
bParse::bDNA::mStructs
btAlignedObjectArray< short * > mStructs
Definition: bDNA.h:92