00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BT_SERIALIZER_H
00017 #define BT_SERIALIZER_H
00018
00019 #include "btScalar.h"
00020 #include "btStackAlloc.h"
00021 #include "btHashMap.h"
00022
00023 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
00024 #include <memory.h>
00025 #endif
00026 #include <string.h>
00027
00028
00029
00031 extern unsigned char sBulletDNAstr[];
00032 extern int sBulletDNAlen;
00033 extern unsigned char sBulletDNAstr64[];
00034 extern int sBulletDNAlen64;
00035
00036 SIMD_FORCE_INLINE int btStrLen(const char* str)
00037 {
00038 if (!str)
00039 return(0);
00040 int len = 0;
00041
00042 while (*str != 0)
00043 {
00044 str++;
00045 len++;
00046 }
00047
00048 return len;
00049 }
00050
00051
00052 class btChunk
00053 {
00054 public:
00055 int m_chunkCode;
00056 int m_length;
00057 void *m_oldPtr;
00058 int m_dna_nr;
00059 int m_number;
00060 };
00061
00062 class btSerializer
00063 {
00064
00065 public:
00066
00067 virtual ~btSerializer() {}
00068
00069 virtual const unsigned char* getBufferPointer() const = 0;
00070
00071 virtual int getCurrentBufferSize() const = 0;
00072
00073 virtual btChunk* allocate(size_t size, int numElements) = 0;
00074
00075 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
00076
00077 virtual void* findPointer(void* oldPtr) = 0;
00078
00079 virtual void startSerialization() = 0;
00080
00081 virtual void finishSerialization() = 0;
00082
00083 virtual const char* findNameForPointer(const void* ptr) const = 0;
00084
00085 virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
00086
00087 virtual void serializeName(const char* ptr) = 0;
00088
00089 };
00090
00091
00092
00093 #define BT_HEADER_LENGTH 12
00094 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
00095 # define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
00096 #else
00097 # define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
00098 #endif
00099
00100 #define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
00101 #define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y')
00102 #define BT_CONSTRAINT_CODE MAKE_ID('C','O','N','S')
00103 #define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S')
00104 #define BT_SHAPE_CODE MAKE_ID('S','H','A','P')
00105 #define BT_ARRAY_CODE MAKE_ID('A','R','A','Y')
00106
00107
00108
00109 class btDefaultSerializer : public btSerializer
00110 {
00111
00112
00113 btAlignedObjectArray<char*> mTypes;
00114 btAlignedObjectArray<short*> mStructs;
00115 btAlignedObjectArray<short> mTlens;
00116 btHashMap<btHashInt, int> mStructReverse;
00117 btHashMap<btHashString,int> mTypeLookup;
00118
00119
00120 btHashMap<btHashPtr,void*> m_chunkP;
00121
00122 btHashMap<btHashPtr,const char*> m_nameMap;
00123
00124
00125 int m_totalSize;
00126 unsigned char* m_buffer;
00127 int m_currentSize;
00128 void* m_dna;
00129 int m_dnaLength;
00130
00131
00132 btAlignedObjectArray<btChunk*> m_chunkPtrs;
00133
00134 protected:
00135
00136 virtual void* findPointer(void* oldPtr)
00137 {
00138 void** ptr = m_chunkP.find(oldPtr);
00139 if (ptr && *ptr)
00140 return *ptr;
00141 return 0;
00142 }
00143
00144
00145
00146 void writeDNA()
00147 {
00148 unsigned char* dnaTarget = m_buffer+m_currentSize;
00149 memcpy(dnaTarget,m_dna,m_dnaLength);
00150 m_currentSize += m_dnaLength;
00151 }
00152
00153 int getReverseType(const char *type) const
00154 {
00155
00156 btHashString key(type);
00157 const int* valuePtr = mTypeLookup.find(key);
00158 if (valuePtr)
00159 return *valuePtr;
00160
00161 return -1;
00162 }
00163
00164 void initDNA(const char* bdnaOrg,int dnalen)
00165 {
00167 if (m_dna)
00168 return;
00169
00170 int littleEndian= 1;
00171 littleEndian= ((char*)&littleEndian)[0];
00172
00173
00174 m_dna = btAlignedAlloc(dnalen,16);
00175 memcpy(m_dna,bdnaOrg,dnalen);
00176 m_dnaLength = dnalen;
00177
00178 int *intPtr=0;
00179 short *shtPtr=0;
00180 char *cp = 0;int dataLen =0;long nr=0;
00181 intPtr = (int*)m_dna;
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if (strncmp((const char*)m_dna, "SDNA", 4)==0)
00192 {
00193
00194 intPtr++; intPtr++;
00195 }
00196
00197
00198 if (!littleEndian)
00199 *intPtr = btSwapEndian(*intPtr);
00200
00201 dataLen = *intPtr;
00202
00203 intPtr++;
00204
00205 cp = (char*)intPtr;
00206 int i;
00207 for ( i=0; i<dataLen; i++)
00208 {
00209
00210 while (*cp)cp++;
00211 cp++;
00212 }
00213 {
00214 nr= (long)cp;
00215
00216 nr= ((nr+3)&~3)-nr;
00217 while (nr--)
00218 {
00219 cp++;
00220 }
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 intPtr = (int*)cp;
00231 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
00232
00233 if (!littleEndian)
00234 *intPtr = btSwapEndian(*intPtr);
00235
00236 dataLen = *intPtr;
00237 intPtr++;
00238
00239
00240 cp = (char*)intPtr;
00241 for (i=0; i<dataLen; i++)
00242 {
00243 mTypes.push_back(cp);
00244 while (*cp)cp++;
00245 cp++;
00246 }
00247
00248 {
00249 nr= (long)cp;
00250
00251 nr= ((nr+3)&~3)-nr;
00252 while (nr--)
00253 {
00254 cp++;
00255 }
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 intPtr = (int*)cp;
00267 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
00268
00269 dataLen = (int)mTypes.size();
00270
00271 shtPtr = (short*)intPtr;
00272 for (i=0; i<dataLen; i++, shtPtr++)
00273 {
00274 if (!littleEndian)
00275 shtPtr[0] = btSwapEndian(shtPtr[0]);
00276 mTlens.push_back(shtPtr[0]);
00277 }
00278
00279 if (dataLen & 1) shtPtr++;
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 intPtr = (int*)shtPtr;
00293 cp = (char*)intPtr;
00294 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
00295
00296 if (!littleEndian)
00297 *intPtr = btSwapEndian(*intPtr);
00298 dataLen = *intPtr ;
00299 intPtr++;
00300
00301
00302 shtPtr = (short*)intPtr;
00303 for (i=0; i<dataLen; i++)
00304 {
00305 mStructs.push_back (shtPtr);
00306
00307 if (!littleEndian)
00308 {
00309 shtPtr[0]= btSwapEndian(shtPtr[0]);
00310 shtPtr[1]= btSwapEndian(shtPtr[1]);
00311
00312 int len = shtPtr[1];
00313 shtPtr+= 2;
00314
00315 for (int a=0; a<len; a++, shtPtr+=2)
00316 {
00317 shtPtr[0]= btSwapEndian(shtPtr[0]);
00318 shtPtr[1]= btSwapEndian(shtPtr[1]);
00319 }
00320
00321 } else
00322 {
00323 shtPtr+= (2*shtPtr[1])+2;
00324 }
00325 }
00326
00327
00328 for (i=0; i<(int)mStructs.size(); i++)
00329 {
00330 short *strc = mStructs.at(i);
00331 mStructReverse.insert(strc[0], i);
00332 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
00333 }
00334 }
00335
00336 public:
00337
00338
00339
00340
00341 btDefaultSerializer(int totalSize)
00342 :m_totalSize(totalSize),
00343 m_currentSize(0),
00344 m_dna(0),
00345 m_dnaLength(0)
00346 {
00347 m_buffer = (unsigned char*)btAlignedAlloc(totalSize, 16);
00348
00349 const bool VOID_IS_8 = ((sizeof(void*)==8));
00350
00351 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00352 if (VOID_IS_8)
00353 {
00354 #if _WIN64
00355 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00356 #else
00357 btAssert(0);
00358 #endif
00359 } else
00360 {
00361 #ifndef _WIN64
00362 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00363 #else
00364 btAssert(0);
00365 #endif
00366 }
00367
00368 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00369 if (VOID_IS_8)
00370 {
00371 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00372 } else
00373 {
00374 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00375 }
00376 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00377
00378 }
00379
00380 virtual ~btDefaultSerializer()
00381 {
00382 if (m_buffer)
00383 btAlignedFree(m_buffer);
00384 if (m_dna)
00385 btAlignedFree(m_dna);
00386 }
00387
00388 virtual void startSerialization()
00389 {
00390 m_currentSize = BT_HEADER_LENGTH;
00391
00392 #ifdef BT_USE_DOUBLE_PRECISION
00393 memcpy(m_buffer, "BULLETd", 7);
00394 #else
00395 memcpy(m_buffer, "BULLETf", 7);
00396 #endif //BT_USE_DOUBLE_PRECISION
00397
00398 int littleEndian= 1;
00399 littleEndian= ((char*)&littleEndian)[0];
00400
00401 if (sizeof(void*)==8)
00402 {
00403 m_buffer[7] = '-';
00404 } else
00405 {
00406 m_buffer[7] = '_';
00407 }
00408
00409 if (littleEndian)
00410 {
00411 m_buffer[8]='v';
00412 } else
00413 {
00414 m_buffer[8]='V';
00415 }
00416
00417
00418 m_buffer[9] = '2';
00419 m_buffer[10] = '7';
00420 m_buffer[11] = '6';
00421
00422
00423 }
00424
00425 virtual void finishSerialization()
00426 {
00427 writeDNA();
00428 }
00429
00430
00431 virtual const unsigned char* getBufferPointer() const
00432 {
00433 return m_buffer;
00434 }
00435
00436 virtual int getCurrentBufferSize() const
00437 {
00438 return m_currentSize;
00439 }
00440
00441 virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
00442 {
00443 btAssert(!findPointer(oldPtr));
00444
00445 chunk->m_dna_nr = getReverseType(structType);
00446
00447 chunk->m_chunkCode = chunkCode;
00448 m_chunkP.insert(oldPtr,chunk->m_oldPtr);
00449 chunk->m_oldPtr = oldPtr;
00450
00451 }
00452
00453
00454
00455
00456
00457 virtual btChunk* allocate(size_t size, int numElements)
00458 {
00459
00460 unsigned char* ptr = m_buffer+m_currentSize;
00461 m_currentSize += int(size)*numElements+sizeof(btChunk);
00462 btAssert(m_currentSize<m_totalSize);
00463
00464 unsigned char* data = ptr + sizeof(btChunk);
00465
00466 btChunk* chunk = (btChunk*)ptr;
00467 chunk->m_chunkCode = 0;
00468 chunk->m_oldPtr = data;
00469 chunk->m_length = int(size)*numElements;
00470 chunk->m_number = numElements;
00471
00472 m_chunkPtrs.push_back(chunk);
00473
00474
00475 return chunk;
00476 }
00477
00478 virtual const char* findNameForPointer(const void* ptr) const
00479 {
00480 const char*const * namePtr = m_nameMap.find(ptr);
00481 if (namePtr && *namePtr)
00482 return *namePtr;
00483 return 0;
00484
00485 }
00486
00487 virtual void registerNameForPointer(const void* ptr, const char* name)
00488 {
00489 m_nameMap.insert(ptr,name);
00490 }
00491
00492 virtual void serializeName(const char* name)
00493 {
00494 if (name)
00495 {
00496 int len = btStrLen(name);
00497 if (len)
00498 {
00499
00500 int newLen = len+1;
00501 int padding = ((newLen+3)&~3)-newLen;
00502 newLen += padding;
00503
00504
00505 btChunk* chunk = allocate(sizeof(char),newLen);
00506 char* destinationName = (char*)chunk->m_oldPtr;
00507 for (int i=0;i<len;i++)
00508 {
00509 destinationName[i] = name[i];
00510 }
00511 destinationName[len] = 0;
00512 finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
00513 }
00514 }
00515 }
00516 };
00517
00518
00519 #endif //BT_SERIALIZER_H
00520