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 && "SDNA empty!");
181 
182 
183 
184  int i;
185  for ( i=0; i<(int)mStructs.size(); i++)
186  {
187  short *oldStruct = mStructs[i];
188 
189  int oldLookup = getReverseType(oldStruct[0]);
190  if (oldLookup == -1)
191  {
192  mCMPFlags[i] = FDF_NONE;
193  continue;
194  }
195  //char* typeName = mTypes[oldStruct[0]];
196 
197 //#define SLOW_FORWARD_COMPATIBLE 1
198 #ifdef SLOW_FORWARD_COMPATIBLE
199  char* typeName = mTypes[oldLookup];
200  int newLookup = memDNA->getReverseType(typeName);
201  if (newLookup == -1)
202  {
203  mCMPFlags[i] = FDF_NONE;
204  continue;
205  }
206  short *curStruct = memDNA->mStructs[newLookup];
207 #else
208  // memory for file
209 
210  if (oldLookup < memDNA->mStructs.size())
211  {
212  short *curStruct = memDNA->mStructs[oldLookup];
213 #endif
214 
215 
216 
217  // rebuild...
219 
220 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
221 
222  if (curStruct[1] == oldStruct[1])
223  {
224  // type len same ...
225  if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
226  {
227  bool isSame = true;
228  int elementLength = oldStruct[1];
229 
230 
231  curStruct+=2;
232  oldStruct+=2;
233 
234 
235  for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
236  {
237  // type the same
238  //const char* typeFileDNA = mTypes[oldStruct[0]];
239  //const char* typeMemDNA = mTypes[curStruct[0]];
240  if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
241  {
242  isSame=false;
243  break;
244  }
245 
246  // name the same
247  if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
248  {
249  isSame=false;
250  break;
251  }
252  }
253  // flag valid ==
254  if (isSame)
256  }
257  }
258 #endif
259  }
260  }
261 
262 
263 
264 
265 
266  // recurse in
267  for ( i=0; i<(int)mStructs.size(); i++)
268  {
269  if (mCMPFlags[i] == FDF_STRUCT_NEQU)
271  }
272 }
273 
274 
275 
276 
277 static int name_is_array(char* name, int* dim1, int* dim2) {
278  int len = strlen(name);
279  /*fprintf(stderr,"[%s]",name);*/
280  /*if (len >= 1) {
281  if (name[len-1] != ']')
282  return 1;
283  }
284  return 0;*/
285  char *bp;
286  int num;
287  if (dim1) {
288  *dim1 = 1;
289  }
290  if (dim2) {
291  *dim2 = 1;
292  }
293  bp = strchr(name, '[');
294  if (!bp) {
295  return 0;
296  }
297  num = 0;
298  while (++bp < name+len-1) {
299  const char c = *bp;
300  if (c == ']') {
301  break;
302  }
303  if (c <= '9' && c >= '0') {
304  num *= 10;
305  num += (c - '0');
306  } else {
307  printf("array parse error.\n");
308  return 0;
309  }
310  }
311  if (dim2) {
312  *dim2 = num;
313  }
314 
315  /* find second dim, if any. */
316  bp = strchr(bp, '[');
317  if (!bp) {
318  return 1; /* at least we got the first dim. */
319  }
320  num = 0;
321  while (++bp < name+len-1) {
322  const char c = *bp;
323  if (c == ']') {
324  break;
325  }
326  if (c <= '9' && c >= '0') {
327  num *= 10;
328  num += (c - '0');
329  } else {
330  printf("array2 parse error.\n");
331  return 1;
332  }
333  }
334  if (dim1) {
335  if (dim2) {
336  *dim1 = *dim2;
337  *dim2 = num;
338  } else {
339  *dim1 = num;
340  }
341  }
342 
343  return 1;
344 }
345 
346 
347 // ----------------------------------------------------- //
348 void bDNA::init(char *data, int len, bool swap)
349 {
350  int *intPtr=0;short *shtPtr=0;
351  char *cp = 0;int dataLen =0;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++; intPtr++;
366  }
367 
368 
369 
370  // Parse names
371  if (swap)
372  {
373  *intPtr = ChunkUtils::swapInt(*intPtr);
374  }
375  dataLen = *intPtr;
376  intPtr++;
377 
378  cp = (char*)intPtr;
379  int i;
380  for ( i=0; i<dataLen; i++)
381  {
382  bNameInfo info;
383  info.m_name = cp;
384  info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
385  name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
386  m_Names.push_back(info);
387  while (*cp)cp++;
388  cp++;
389  }
390 
391 
392  {
393  nr= (long)cp;
394  //long mask=3;
395  nr= ((nr+3)&~3)-nr;
396  while (nr--)
397  {
398  cp++;
399  }
400  }
401 
402 
403  /*
404  TYPE (4 bytes)
405  <nr> amount of types (int)
406  <string>
407  <string>
408  */
409 
410  intPtr = (int*)cp;
411  assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
412 
413  if (swap)
414  {
415  *intPtr = ChunkUtils::swapInt(*intPtr);
416  }
417  dataLen = *intPtr;
418  intPtr++;
419 
420  cp = (char*)intPtr;
421  for ( i=0; i<dataLen; i++)
422  {
423  mTypes.push_back(cp);
424  while (*cp)cp++;
425  cp++;
426  }
427 
428 {
429  nr= (long)cp;
430  // long mask=3;
431  nr= ((nr+3)&~3)-nr;
432  while (nr--)
433  {
434  cp++;
435  }
436  }
437 
438 
439  /*
440  TLEN (4 bytes)
441  <len> (short) the lengths of types
442  <len>
443  */
444 
445  // Parse type lens
446  intPtr = (int*)cp;
447  assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
448 
449  dataLen = (int)mTypes.size();
450 
451  shtPtr = (short*)intPtr;
452  for ( i=0; i<dataLen; i++, shtPtr++)
453  {
454  if (swap)
455  shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
456  mTlens.push_back(shtPtr[0]);
457  }
458 
459  if (dataLen & 1) shtPtr++;
460 
461  /*
462  STRC (4 bytes)
463  <nr> amount of structs (int)
464  <typenr>
465  <nr_of_elems>
466  <typenr>
467  <namenr>
468  <typenr>
469  <namenr>
470  */
471 
472  intPtr = (int*)shtPtr;
473  cp = (char*)intPtr;
474  assert(strncmp(cp, "STRC", 4)==0); intPtr++;
475 
476  if (swap)
477  {
478  *intPtr = ChunkUtils::swapInt(*intPtr);
479  }
480  dataLen = *intPtr;
481  intPtr++;
482 
483 
484  shtPtr = (short*)intPtr;
485  for ( i=0; i<dataLen; i++)
486  {
487  mStructs.push_back (shtPtr);
488  if (swap)
489  {
490  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
491  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
492 
493  int len = shtPtr[1];
494  shtPtr+= 2;
495 
496  for (int a=0; a<len; a++, shtPtr+=2)
497  {
498  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
499  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
500  }
501  }
502  else
503  shtPtr+= (2*shtPtr[1])+2;
504  }
505 
506 
507  // build reverse lookups
508  for ( i=0; i<(int)mStructs.size(); i++)
509  {
510  short *strc = mStructs.at(i);
511  if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
512  {
513  mPtrLen = mTlens[strc[0]]/2;
514  }
515 
516  mStructReverse.insert(strc[0], i);
517  mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
518  }
519 }
520 
521 
522 // ----------------------------------------------------- //
523 int bDNA::getArraySize(char* string)
524 {
525  int ret = 1;
526  int len = strlen(string);
527 
528 
529  char* next = 0;
530  for (int i=0; i<len; i++)
531  {
532  char c = string[i];
533 
534  if (c == '[')
535  next = &string[i+1];
536  else if (c==']')
537  if (next)
538  ret *= atoi(next);
539  }
540 
541 // print (string << ' ' << ret);
542  return ret;
543 }
544 
545 
547 {
548  int i;
549 
550  int numTypes = mTypes.size();
551 
552  for (i=0;i<numTypes;i++)
553  {
554 
555  }
556 
557  for ( i=0; i<(int)mStructs.size(); i++)
558  {
559  int totalBytes=0;
560  short *oldStruct = mStructs[i];
561 
562  int oldLookup = getReverseType(oldStruct[0]);
563  if (oldLookup == -1)
564  {
565  mCMPFlags[i] = FDF_NONE;
566  continue;
567  }
568 
569  short* newStruct = mStructs[oldLookup];
570  char* typeName = mTypes[newStruct[0]];
571  printf("%3d: %s ",i,typeName);
572 
573  //char *name = mNames[oldStruct[1]];
574  int len = oldStruct[1];
575  printf(" (%d fields) ",len);
576  oldStruct+=2;
577 
578  printf("{");
579  int j;
580  for (j=0; j<len; ++j,oldStruct+=2) {
581  const char* name = m_Names[oldStruct[1]].m_name;
582  printf("%s %s", mTypes[oldStruct[0]],name);
583  int elemNumBytes= 0;
584  int arrayDimensions = getArraySizeNew(oldStruct[1]);
585 
586  if (m_Names[oldStruct[1]].m_isPointer)
587  {
588  elemNumBytes = VOID_IS_8 ? 8 : 4;
589  } else
590  {
591  elemNumBytes = getLength(oldStruct[0]);
592  }
593  printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
594 
595  if (j == len-1) {
596  printf(";}");
597  } else {
598  printf("; ");
599  }
600  totalBytes+=elemNumBytes*arrayDimensions;
601  }
602  printf("\ntotalBytes=%d\n\n",totalBytes);
603 
604  }
605 
606 
607 
608 #if 0
609  /* dump out display of types and their sizes */
610  for (i=0; i<bf->types_count; ++i) {
611  /* if (!bf->types[i].is_struct)*/
612  {
613  printf("%3d: sizeof(%s%s)=%d",
614  i,
615  bf->types[i].is_struct ? "struct " : "atomic ",
616  bf->types[i].name, bf->types[i].size);
617  if (bf->types[i].is_struct) {
618  int j;
619  printf(", %d fields: { ", bf->types[i].fieldtypes_count);
620  for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
621  printf("%s %s",
622  bf->types[bf->types[i].fieldtypes[j]].name,
623  bf->names[bf->types[i].fieldnames[j]]);
624  if (j == bf->types[i].fieldtypes_count-1) {
625  printf(";}");
626  } else {
627  printf("; ");
628  }
629  }
630  }
631  printf("\n\n");
632 
633  }
634  }
635 #endif
636 
637 }
638 
639 
640 
641 
642 //eof
643 
644 
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:546
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:277
char * m_name
Definition: bDNA.h:26
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:269
int getArraySize(char *str)
Definition: bDNA.cpp:523
const Value * find(const Key &key) const
Definition: btHashMap.h:402
bool flagNotEqual(int dna_nr)
Definition: bDNA.cpp:111
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:23
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:348
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
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