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;long nr=0;
353  intPtr = (int*)data;
354 
355  /*
356  SDNA (4 bytes) (magic number)
357  NAME (4 bytes)
358  <nr> (4 bytes) amount of names (int)
359  <string>
360  <string>
361  */
362 
363  if (strncmp(data, "SDNA", 4)==0)
364  {
365  // skip ++ NAME
366  intPtr++; intPtr++;
367  }
368 
369 
370 
371  // Parse names
372  if (swap)
373  {
374  *intPtr = ChunkUtils::swapInt(*intPtr);
375  }
376  dataLen = *intPtr;
377  intPtr++;
378 
379  cp = (char*)intPtr;
380  int i;
381  for ( i=0; i<dataLen; i++)
382  {
383  bNameInfo info;
384  info.m_name = cp;
385  info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
386  name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
387  m_Names.push_back(info);
388  while (*cp)cp++;
389  cp++;
390  }
391 
392 
393  {
394  nr= (long)cp;
395  //long mask=3;
396  nr= ((nr+3)&~3)-nr;
397  while (nr--)
398  {
399  cp++;
400  }
401  }
402 
403 
404  /*
405  TYPE (4 bytes)
406  <nr> amount of types (int)
407  <string>
408  <string>
409  */
410 
411  intPtr = (int*)cp;
412  assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
413 
414  if (swap)
415  {
416  *intPtr = ChunkUtils::swapInt(*intPtr);
417  }
418  dataLen = *intPtr;
419  intPtr++;
420 
421  cp = (char*)intPtr;
422  for ( i=0; i<dataLen; i++)
423  {
424  mTypes.push_back(cp);
425  while (*cp)cp++;
426  cp++;
427  }
428 
429 {
430  nr= (long)cp;
431  // long mask=3;
432  nr= ((nr+3)&~3)-nr;
433  while (nr--)
434  {
435  cp++;
436  }
437  }
438 
439 
440  /*
441  TLEN (4 bytes)
442  <len> (short) the lengths of types
443  <len>
444  */
445 
446  // Parse type lens
447  intPtr = (int*)cp;
448  assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
449 
450  dataLen = (int)mTypes.size();
451 
452  shtPtr = (short*)intPtr;
453  for ( i=0; i<dataLen; i++, shtPtr++)
454  {
455  if (swap)
456  shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
457  mTlens.push_back(shtPtr[0]);
458  }
459 
460  if (dataLen & 1) shtPtr++;
461 
462  /*
463  STRC (4 bytes)
464  <nr> amount of structs (int)
465  <typenr>
466  <nr_of_elems>
467  <typenr>
468  <namenr>
469  <typenr>
470  <namenr>
471  */
472 
473  intPtr = (int*)shtPtr;
474  cp = (char*)intPtr;
475  assert(strncmp(cp, "STRC", 4)==0); intPtr++;
476 
477  if (swap)
478  {
479  *intPtr = ChunkUtils::swapInt(*intPtr);
480  }
481  dataLen = *intPtr;
482  intPtr++;
483 
484 
485  shtPtr = (short*)intPtr;
486  for ( i=0; i<dataLen; i++)
487  {
488  mStructs.push_back (shtPtr);
489  if (swap)
490  {
491  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
492  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
493 
494  int len = shtPtr[1];
495  shtPtr+= 2;
496 
497  for (int a=0; a<len; a++, shtPtr+=2)
498  {
499  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
500  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
501  }
502  }
503  else
504  shtPtr+= (2*shtPtr[1])+2;
505  }
506 
507 
508  // build reverse lookups
509  for ( i=0; i<(int)mStructs.size(); i++)
510  {
511  short *strc = mStructs.at(i);
512  if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
513  {
514  mPtrLen = mTlens[strc[0]]/2;
515  }
516 
517  mStructReverse.insert(strc[0], i);
518  mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
519  }
520 }
521 
522 
523 // ----------------------------------------------------- //
524 int bDNA::getArraySize(char* string)
525 {
526  int ret = 1;
527  int len = strlen(string);
528 
529 
530  char* next = 0;
531  for (int i=0; i<len; i++)
532  {
533  char c = string[i];
534 
535  if (c == '[')
536  next = &string[i+1];
537  else if (c==']')
538  if (next)
539  ret *= atoi(next);
540  }
541 
542 // print (string << ' ' << ret);
543  return ret;
544 }
545 
546 
548 {
549  int i;
550 
551  int numTypes = mTypes.size();
552 
553  for (i=0;i<numTypes;i++)
554  {
555 
556  }
557 
558  for ( i=0; i<(int)mStructs.size(); i++)
559  {
560  int totalBytes=0;
561  short *oldStruct = mStructs[i];
562 
563  int oldLookup = getReverseType(oldStruct[0]);
564  if (oldLookup == -1)
565  {
566  mCMPFlags[i] = FDF_NONE;
567  continue;
568  }
569 
570  short* newStruct = mStructs[oldLookup];
571  char* typeName = mTypes[newStruct[0]];
572  printf("%3d: %s ",i,typeName);
573 
574  //char *name = mNames[oldStruct[1]];
575  int len = oldStruct[1];
576  printf(" (%d fields) ",len);
577  oldStruct+=2;
578 
579  printf("{");
580  int j;
581  for (j=0; j<len; ++j,oldStruct+=2) {
582  const char* name = m_Names[oldStruct[1]].m_name;
583  printf("%s %s", mTypes[oldStruct[0]],name);
584  int elemNumBytes= 0;
585  int arrayDimensions = getArraySizeNew(oldStruct[1]);
586 
587  if (m_Names[oldStruct[1]].m_isPointer)
588  {
589  elemNumBytes = VOID_IS_8 ? 8 : 4;
590  } else
591  {
592  elemNumBytes = getLength(oldStruct[0]);
593  }
594  printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
595 
596  if (j == len-1) {
597  printf(";}");
598  } else {
599  printf("; ");
600  }
601  totalBytes+=elemNumBytes*arrayDimensions;
602  }
603  printf("\ntotalBytes=%d\n\n",totalBytes);
604 
605  }
606 
607 
608 
609 #if 0
610  /* dump out display of types and their sizes */
611  for (i=0; i<bf->types_count; ++i) {
612  /* if (!bf->types[i].is_struct)*/
613  {
614  printf("%3d: sizeof(%s%s)=%d",
615  i,
616  bf->types[i].is_struct ? "struct " : "atomic ",
617  bf->types[i].name, bf->types[i].size);
618  if (bf->types[i].is_struct) {
619  int j;
620  printf(", %d fields: { ", bf->types[i].fieldtypes_count);
621  for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
622  printf("%s %s",
623  bf->types[bf->types[i].fieldtypes[j]].name,
624  bf->names[bf->types[i].fieldnames[j]]);
625  if (j == bf->types[i].fieldtypes_count-1) {
626  printf(";}");
627  } else {
628  printf("; ");
629  }
630  }
631  }
632  printf("\n\n");
633 
634  }
635  }
636 #endif
637 
638 }
639 
640 
641 
642 
643 //eof
644 
645 
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:547
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:269
int getArraySize(char *str)
Definition: bDNA.cpp:524
const Value * find(const Key &key) const
Definition: btHashMap.h:406
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:349
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