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 
27 using namespace bParse;
28 
29 
30 // ----------------------------------------------------- //
32  : mPtrLen(0)
33 {
34  // --
35 }
36 
37 // ----------------------------------------------------- //
39 {
40  // --
41 }
42 
43 // ----------------------------------------------------- //
44 bool bDNA::lessThan(bDNA *file)
45 {
46  return ( m_Names.size() < file->m_Names.size());
47 }
48 
49 // ----------------------------------------------------- //
50 char *bDNA::getName(int ind)
51 {
52  assert(ind <= (int)m_Names.size());
53  return m_Names[ind].m_name;
54 }
55 
56 
57 // ----------------------------------------------------- //
58 char *bDNA::getType(int ind)
59 {
60  assert(ind<= (int)mTypes.size());
61  return mTypes[ind];
62 }
63 
64 
65 // ----------------------------------------------------- //
66 short *bDNA::getStruct(int ind)
67 {
68  assert(ind <= (int)mStructs.size());
69  return mStructs[ind];
70 }
71 
72 
73 // ----------------------------------------------------- //
74 short bDNA::getLength(int ind)
75 {
76  assert(ind <= (int)mTlens.size());
77  return mTlens[ind];
78 }
79 
80 
81 // ----------------------------------------------------- //
82 int 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 // ----------------------------------------------------- //
93 int 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 // ----------------------------------------------------- //
111 bool bDNA::flagNotEqual(int dna_nr)
112 {
113  assert(dna_nr <= (int)mCMPFlags.size());
114  return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
115 }
116 
117 // ----------------------------------------------------- //
118 bool 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 // ----------------------------------------------------- //
126 bool 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 
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 
278 static 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 // ----------------------------------------------------- //
349 void 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 // ----------------------------------------------------- //
508 int 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 
void push_back(const T &_Val)
btAlignedObjectArray< int > mCMPFlags
Definition: bDNA.h:92
int getArraySizeNew(short name)
Definition: bDNA.h:41
int mPtrLen
Definition: bDNA.h:101
btAlignedObjectArray< short * > mStructs
Definition: bDNA.h:96
bool lessThan(bDNA *other)
Definition: bDNA.cpp:44
const T & at(int n) const
int getNumStructs()
Definition: bDNA.cpp:105
char * getName(int ind)
Definition: bDNA.cpp:50
void dumpTypeDefinitions()
Definition: bDNA.cpp:531
bool m_isPointer
Definition: bDNA.h:27
void initCmpFlags(bDNA *memDNA)
Definition: bDNA.cpp:172
btAlignedObjectArray< short > mTlens
Definition: bDNA.h:97
btAlignedObjectArray< bNameInfo > m_Names
Definition: bDNA.h:94
static int swapInt(int inte)
Definition: bChunk.cpp:37
int size() const
return the number of elements in the array
const bool VOID_IS_8
Definition: bChunk.h:89
btHashMap< btHashInt, int > mStructReverse
Definition: bDNA.h:98
int getPointerSize()
Definition: bDNA.cpp:133
static int name_is_array(char *name, int *dim1, int *dim2)
Definition: bDNA.cpp:278
char * m_name
Definition: bDNA.h:26
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:262
int getArraySize(char *str)
Definition: bDNA.cpp:508
const Value * find(const Key &key) const
Definition: btHashMap.h:422
bool flagNotEqual(int dna_nr)
Definition: bDNA.cpp:111
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:24
void resize(int newsize, const T &fillData=T())
short * getStruct(int ind)
Definition: bDNA.cpp:66
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:349
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
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
void initRecurseCmpFlags(int i)
Definition: bDNA.cpp:139
btAlignedObjectArray< char * > mTypes
Definition: bDNA.h:95
btHashMap< btHashString, int > mTypeLookup
Definition: bDNA.h:99
int getReverseType(short type)
Definition: bDNA.cpp:82
short getLength(int ind)
Definition: bDNA.cpp:74
bool flagNone(int dna_nr)
Definition: bDNA.cpp:126
char * getType(int ind)
Definition: bDNA.cpp:58