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 enum    btSerializationFlags
00063 {
00064         BT_SERIALIZE_NO_BVH = 1,
00065         BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
00066         BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
00067 };
00068 
00069 class   btSerializer
00070 {
00071 
00072 public:
00073 
00074         virtual ~btSerializer() {}
00075 
00076         virtual const unsigned char*            getBufferPointer() const = 0;
00077 
00078         virtual int             getCurrentBufferSize() const = 0;
00079 
00080         virtual btChunk*        allocate(size_t size, int numElements) = 0;
00081 
00082         virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
00083 
00084         virtual  void*  findPointer(void* oldPtr)  = 0;
00085 
00086         virtual void*   getUniquePointer(void*oldPtr) = 0;
00087 
00088         virtual void    startSerialization() = 0;
00089         
00090         virtual void    finishSerialization() = 0;
00091 
00092         virtual const char*     findNameForPointer(const void* ptr) const = 0;
00093 
00094         virtual void    registerNameForPointer(const void* ptr, const char* name) = 0;
00095 
00096         virtual void    serializeName(const char* ptr) = 0;
00097 
00098         virtual int             getSerializationFlags() const = 0;
00099 
00100         virtual void    setSerializationFlags(int flags) = 0;
00101 
00102 
00103 };
00104 
00105 
00106 
00107 #define BT_HEADER_LENGTH 12
00108 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
00109 #       define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
00110 #else
00111 #       define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
00112 #endif
00113 
00114 #define BT_SOFTBODY_CODE                MAKE_ID('S','B','D','Y')
00115 #define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
00116 #define BT_RIGIDBODY_CODE               MAKE_ID('R','B','D','Y')
00117 #define BT_CONSTRAINT_CODE              MAKE_ID('C','O','N','S')
00118 #define BT_BOXSHAPE_CODE                MAKE_ID('B','O','X','S')
00119 #define BT_QUANTIZED_BVH_CODE   MAKE_ID('Q','B','V','H')
00120 #define BT_TRIANLGE_INFO_MAP    MAKE_ID('T','M','A','P')
00121 #define BT_SHAPE_CODE                   MAKE_ID('S','H','A','P')
00122 #define BT_ARRAY_CODE                   MAKE_ID('A','R','A','Y')
00123 #define BT_SBMATERIAL_CODE              MAKE_ID('S','B','M','T')
00124 #define BT_SBNODE_CODE                  MAKE_ID('S','B','N','D')
00125 #define BT_DNA_CODE                             MAKE_ID('D','N','A','1')
00126 
00127 
00128 struct  btPointerUid
00129 {
00130         union
00131         {
00132                 void*   m_ptr;
00133                 int             m_uniqueIds[2];
00134         };
00135 };
00136 
00139 class btDefaultSerializer       :       public btSerializer
00140 {
00141 
00142 
00143         btAlignedObjectArray<char*>                     mTypes;
00144         btAlignedObjectArray<short*>                    mStructs;
00145         btAlignedObjectArray<short>                     mTlens;
00146         btHashMap<btHashInt, int>                       mStructReverse;
00147         btHashMap<btHashString,int>     mTypeLookup;
00148 
00149         
00150         btHashMap<btHashPtr,void*>      m_chunkP;
00151         
00152         btHashMap<btHashPtr,const char*>        m_nameMap;
00153 
00154         btHashMap<btHashPtr,btPointerUid>       m_uniquePointers;
00155         int     m_uniqueIdGenerator;
00156 
00157         int                                     m_totalSize;
00158         unsigned char*          m_buffer;
00159         int                                     m_currentSize;
00160         void*                           m_dna;
00161         int                                     m_dnaLength;
00162 
00163         int                                     m_serializationFlags;
00164 
00165 
00166         btAlignedObjectArray<btChunk*>  m_chunkPtrs;
00167         
00168 protected:
00169 
00170         virtual void*   findPointer(void* oldPtr) 
00171         {
00172                 void** ptr = m_chunkP.find(oldPtr);
00173                 if (ptr && *ptr)
00174                         return *ptr;
00175                 return 0;
00176         }
00177 
00178         
00179 
00180 
00181 
00182                 void    writeDNA()
00183                 {
00184                         btChunk* dnaChunk = allocate(m_dnaLength,1);
00185                         memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
00186                         finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
00187                 }
00188 
00189                 int getReverseType(const char *type) const
00190                 {
00191 
00192                         btHashString key(type);
00193                         const int* valuePtr = mTypeLookup.find(key);
00194                         if (valuePtr)
00195                                 return *valuePtr;
00196                         
00197                         return -1;
00198                 }
00199 
00200                 void initDNA(const char* bdnaOrg,int dnalen)
00201                 {
00203                         if (m_dna)
00204                                 return;
00205 
00206                         int littleEndian= 1;
00207                         littleEndian= ((char*)&littleEndian)[0];
00208                         
00209 
00210                         m_dna = btAlignedAlloc(dnalen,16);
00211                         memcpy(m_dna,bdnaOrg,dnalen);
00212                         m_dnaLength = dnalen;
00213 
00214                         int *intPtr=0;
00215                         short *shtPtr=0;
00216                         char *cp = 0;int dataLen =0;long nr=0;
00217                         intPtr = (int*)m_dna;
00218 
00219                         /*
00220                                 SDNA (4 bytes) (magic number)
00221                                 NAME (4 bytes)
00222                                 <nr> (4 bytes) amount of names (int)
00223                                 <string>
00224                                 <string>
00225                         */
00226 
00227                         if (strncmp((const char*)m_dna, "SDNA", 4)==0)
00228                         {
00229                                 // skip ++ NAME
00230                                 intPtr++; intPtr++;
00231                         }
00232 
00233                         // Parse names
00234                         if (!littleEndian)
00235                                 *intPtr = btSwapEndian(*intPtr);
00236                                 
00237                         dataLen = *intPtr;
00238                         
00239                         intPtr++;
00240 
00241                         cp = (char*)intPtr;
00242                         int i;
00243                         for ( i=0; i<dataLen; i++)
00244                         {
00245                                 
00246                                 while (*cp)cp++;
00247                                 cp++;
00248                         }
00249                         {
00250                                 nr= (long)cp;
00251                         //      long mask=3;
00252                                 nr= ((nr+3)&~3)-nr;
00253                                 while (nr--)
00254                                 {
00255                                         cp++;
00256                                 }
00257                         }
00258 
00259                         /*
00260                                 TYPE (4 bytes)
00261                                 <nr> amount of types (int)
00262                                 <string>
00263                                 <string>
00264                         */
00265 
00266                         intPtr = (int*)cp;
00267                         assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
00268 
00269                         if (!littleEndian)
00270                                 *intPtr =  btSwapEndian(*intPtr);
00271                         
00272                         dataLen = *intPtr;
00273                         intPtr++;
00274 
00275                         
00276                         cp = (char*)intPtr;
00277                         for (i=0; i<dataLen; i++)
00278                         {
00279                                 mTypes.push_back(cp);
00280                                 while (*cp)cp++;
00281                                 cp++;
00282                         }
00283 
00284                 {
00285                                 nr= (long)cp;
00286                         //      long mask=3;
00287                                 nr= ((nr+3)&~3)-nr;
00288                                 while (nr--)
00289                                 {
00290                                         cp++;
00291                                 }
00292                         }
00293 
00294 
00295                         /*
00296                                 TLEN (4 bytes)
00297                                 <len> (short) the lengths of types
00298                                 <len>
00299                         */
00300 
00301                         // Parse type lens
00302                         intPtr = (int*)cp;
00303                         assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
00304 
00305                         dataLen = (int)mTypes.size();
00306 
00307                         shtPtr = (short*)intPtr;
00308                         for (i=0; i<dataLen; i++, shtPtr++)
00309                         {
00310                                 if (!littleEndian)
00311                                         shtPtr[0] = btSwapEndian(shtPtr[0]);
00312                                 mTlens.push_back(shtPtr[0]);
00313                         }
00314 
00315                         if (dataLen & 1) shtPtr++;
00316 
00317                         /*
00318                                 STRC (4 bytes)
00319                                 <nr> amount of structs (int)
00320                                 <typenr>
00321                                 <nr_of_elems>
00322                                 <typenr>
00323                                 <namenr>
00324                                 <typenr>
00325                                 <namenr>
00326                         */
00327 
00328                         intPtr = (int*)shtPtr;
00329                         cp = (char*)intPtr;
00330                         assert(strncmp(cp, "STRC", 4)==0); intPtr++;
00331 
00332                         if (!littleEndian)
00333                                 *intPtr = btSwapEndian(*intPtr);
00334                         dataLen = *intPtr ; 
00335                         intPtr++;
00336 
00337 
00338                         shtPtr = (short*)intPtr;
00339                         for (i=0; i<dataLen; i++)
00340                         {
00341                                 mStructs.push_back (shtPtr);
00342                                 
00343                                 if (!littleEndian)
00344                                 {
00345                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
00346                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
00347 
00348                                         int len = shtPtr[1];
00349                                         shtPtr+= 2;
00350 
00351                                         for (int a=0; a<len; a++, shtPtr+=2)
00352                                         {
00353                                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
00354                                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
00355                                         }
00356 
00357                                 } else
00358                                 {
00359                                         shtPtr+= (2*shtPtr[1])+2;
00360                                 }
00361                         }
00362 
00363                         // build reverse lookups
00364                         for (i=0; i<(int)mStructs.size(); i++)
00365                         {
00366                                 short *strc = mStructs.at(i);
00367                                 mStructReverse.insert(strc[0], i);
00368                                 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
00369                         }
00370                 }
00371 
00372 public: 
00373         
00374 
00375         
00376 
00377                 btDefaultSerializer(int totalSize=0)
00378                         :m_totalSize(totalSize),
00379                         m_currentSize(0),
00380                         m_dna(0),
00381                         m_dnaLength(0),
00382                         m_serializationFlags(0)
00383                 {
00384                         m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
00385                         
00386                         const bool VOID_IS_8 = ((sizeof(void*)==8));
00387 
00388 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00389                         if (VOID_IS_8)
00390                         {
00391 #if _WIN64
00392                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00393 #else
00394                                 btAssert(0);
00395 #endif
00396                         } else
00397                         {
00398 #ifndef _WIN64
00399                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00400 #else
00401                                 btAssert(0);
00402 #endif
00403                         }
00404         
00405 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00406                         if (VOID_IS_8)
00407                         {
00408                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
00409                         } else
00410                         {
00411                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
00412                         }
00413 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
00414         
00415                 }
00416 
00417                 virtual ~btDefaultSerializer() 
00418                 {
00419                         if (m_buffer)
00420                                 btAlignedFree(m_buffer);
00421                         if (m_dna)
00422                                 btAlignedFree(m_dna);
00423                 }
00424 
00425                 void    writeHeader(unsigned char* buffer) const
00426                 {
00427                         
00428 
00429 #ifdef  BT_USE_DOUBLE_PRECISION
00430                         memcpy(buffer, "BULLETd", 7);
00431 #else
00432                         memcpy(buffer, "BULLETf", 7);
00433 #endif //BT_USE_DOUBLE_PRECISION
00434         
00435                         int littleEndian= 1;
00436                         littleEndian= ((char*)&littleEndian)[0];
00437 
00438                         if (sizeof(void*)==8)
00439                         {
00440                                 buffer[7] = '-';
00441                         } else
00442                         {
00443                                 buffer[7] = '_';
00444                         }
00445 
00446                         if (littleEndian)
00447                         {
00448                                 buffer[8]='v';                          
00449                         } else
00450                         {
00451                                 buffer[8]='V';
00452                         }
00453 
00454 
00455                         buffer[9] = '2';
00456                         buffer[10] = '7';
00457                         buffer[11] = '8';
00458 
00459                 }
00460 
00461                 virtual void    startSerialization()
00462                 {
00463                         m_uniqueIdGenerator= 1;
00464                         if (m_totalSize)
00465                         {
00466                                 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
00467                                 writeHeader(buffer);
00468                         }
00469                         
00470                 }
00471 
00472                 virtual void    finishSerialization()
00473                 {
00474                         writeDNA();
00475 
00476                         //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
00477                         int mysize = 0;
00478                         if (!m_totalSize)
00479                         {
00480                                 if (m_buffer)
00481                                         btAlignedFree(m_buffer);
00482 
00483                                 m_currentSize += BT_HEADER_LENGTH;
00484                                 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
00485 
00486                                 unsigned char* currentPtr = m_buffer;
00487                                 writeHeader(m_buffer);
00488                                 currentPtr += BT_HEADER_LENGTH;
00489                                 mysize+=BT_HEADER_LENGTH;
00490                                 for (int i=0;i< m_chunkPtrs.size();i++)
00491                                 {
00492                                         int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
00493                                         memcpy(currentPtr,m_chunkPtrs[i], curLength);
00494                                         btAlignedFree(m_chunkPtrs[i]);
00495                                         currentPtr+=curLength;
00496                                         mysize+=curLength;
00497                                 }
00498                         }
00499 
00500                         mTypes.clear();
00501                         mStructs.clear();
00502                         mTlens.clear();
00503                         mStructReverse.clear();
00504                         mTypeLookup.clear();
00505                         m_chunkP.clear();
00506                         m_nameMap.clear();
00507                         m_uniquePointers.clear();
00508                         m_chunkPtrs.clear();
00509                 }
00510 
00511                 virtual void*   getUniquePointer(void*oldPtr)
00512                 {
00513                         if (!oldPtr)
00514                                 return 0;
00515 
00516                         btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
00517                         if (uptr)
00518                         {
00519                                 return uptr->m_ptr;
00520                         }
00521                         m_uniqueIdGenerator++;
00522                         
00523                         btPointerUid uid;
00524                         uid.m_uniqueIds[0] = m_uniqueIdGenerator;
00525                         uid.m_uniqueIds[1] = m_uniqueIdGenerator;
00526                         m_uniquePointers.insert(oldPtr,uid);
00527                         return uid.m_ptr;
00528 
00529                 }
00530 
00531                 virtual const unsigned char*            getBufferPointer() const
00532                 {
00533                         return m_buffer;
00534                 }
00535 
00536                 virtual int                                     getCurrentBufferSize() const
00537                 {
00538                         return  m_currentSize;
00539                 }
00540 
00541                 virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
00542                 {
00543                         if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
00544                         {
00545                                 btAssert(!findPointer(oldPtr));
00546                         }
00547 
00548                         chunk->m_dna_nr = getReverseType(structType);
00549                         
00550                         chunk->m_chunkCode = chunkCode;
00551                         
00552                         void* uniquePtr = getUniquePointer(oldPtr);
00553                         
00554                         m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
00555                         chunk->m_oldPtr = uniquePtr;//oldPtr;
00556                         
00557                 }
00558 
00559                 
00560                 virtual unsigned char* internalAlloc(size_t size)
00561                 {
00562                         unsigned char* ptr = 0;
00563 
00564                         if (m_totalSize)
00565                         {
00566                                 ptr = m_buffer+m_currentSize;
00567                                 m_currentSize += int(size);
00568                                 btAssert(m_currentSize<m_totalSize);
00569                         } else
00570                         {
00571                                 ptr = (unsigned char*)btAlignedAlloc(size,16);
00572                                 m_currentSize += int(size);
00573                         }
00574                         return ptr;
00575                 }
00576 
00577                 
00578 
00579                 virtual btChunk*        allocate(size_t size, int numElements)
00580                 {
00581 
00582                         unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
00583 
00584                         unsigned char* data = ptr + sizeof(btChunk);
00585                         
00586                         btChunk* chunk = (btChunk*)ptr;
00587                         chunk->m_chunkCode = 0;
00588                         chunk->m_oldPtr = data;
00589                         chunk->m_length = int(size)*numElements;
00590                         chunk->m_number = numElements;
00591                         
00592                         m_chunkPtrs.push_back(chunk);
00593                         
00594 
00595                         return chunk;
00596                 }
00597 
00598                 virtual const char*     findNameForPointer(const void* ptr) const
00599                 {
00600                         const char*const * namePtr = m_nameMap.find(ptr);
00601                         if (namePtr && *namePtr)
00602                                 return *namePtr;
00603                         return 0;
00604 
00605                 }
00606 
00607                 virtual void    registerNameForPointer(const void* ptr, const char* name)
00608                 {
00609                         m_nameMap.insert(ptr,name);
00610                 }
00611 
00612                 virtual void    serializeName(const char* name)
00613                 {
00614                         if (name)
00615                         {
00616                                 //don't serialize name twice
00617                                 if (findPointer((void*)name))
00618                                         return;
00619 
00620                                 int len = btStrLen(name);
00621                                 if (len)
00622                                 {
00623 
00624                                         int newLen = len+1;
00625                                         int padding = ((newLen+3)&~3)-newLen;
00626                                         newLen += padding;
00627 
00628                                         //serialize name string now
00629                                         btChunk* chunk = allocate(sizeof(char),newLen);
00630                                         char* destinationName = (char*)chunk->m_oldPtr;
00631                                         for (int i=0;i<len;i++)
00632                                         {
00633                                                 destinationName[i] = name[i];
00634                                         }
00635                                         destinationName[len] = 0;
00636                                         finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
00637                                 }
00638                         }
00639                 }
00640 
00641                 virtual int             getSerializationFlags() const
00642                 {
00643                         return m_serializationFlags;
00644                 }
00645 
00646                 virtual void    setSerializationFlags(int flags)
00647                 {
00648                         m_serializationFlags = flags;
00649                 }
00650 
00651 };
00652 
00653 
00654 #endif //BT_SERIALIZER_H
00655 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


bullet
Author(s): Erwin Coumans, ROS package maintained by Tully Foote
autogenerated on Wed Oct 31 2012 07:54:31