btSerializer.h

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #ifndef BT_SERIALIZER_H
00017 #define BT_SERIALIZER_H
00018 
00019 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
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                                 SDNA (4 bytes) (magic number)
00185                                 NAME (4 bytes)
00186                                 <nr> (4 bytes) amount of names (int)
00187                                 <string>
00188                                 <string>
00189                         */
00190 
00191                         if (strncmp((const char*)m_dna, "SDNA", 4)==0)
00192                         {
00193                                 // skip ++ NAME
00194                                 intPtr++; intPtr++;
00195                         }
00196 
00197                         // Parse names
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                         //      long mask=3;
00216                                 nr= ((nr+3)&~3)-nr;
00217                                 while (nr--)
00218                                 {
00219                                         cp++;
00220                                 }
00221                         }
00222 
00223                         /*
00224                                 TYPE (4 bytes)
00225                                 <nr> amount of types (int)
00226                                 <string>
00227                                 <string>
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                         //      long mask=3;
00251                                 nr= ((nr+3)&~3)-nr;
00252                                 while (nr--)
00253                                 {
00254                                         cp++;
00255                                 }
00256                         }
00257 
00258 
00259                         /*
00260                                 TLEN (4 bytes)
00261                                 <len> (short) the lengths of types
00262                                 <len>
00263                         */
00264 
00265                         // Parse type lens
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                                 STRC (4 bytes)
00283                                 <nr> amount of structs (int)
00284                                 <typenr>
00285                                 <nr_of_elems>
00286                                 <typenr>
00287                                 <namenr>
00288                                 <typenr>
00289                                 <namenr>
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                         // build reverse lookups
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                                         //serialize name string now
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 

Generated on Mon Feb 15 22:17:06 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1