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