Imported Upstream version 2.81
[platform/upstream/libbullet.git] / src / LinearMath / btSerializer.h
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
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
16 #ifndef BT_SERIALIZER_H
17 #define BT_SERIALIZER_H
18
19 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
20 #include "btStackAlloc.h"
21 #include "btHashMap.h"
22
23 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
24 #include <memory.h>
25 #endif
26 #include <string.h>
27
28
29
30 ///only the 32bit versions for now
31 extern char sBulletDNAstr[];
32 extern int sBulletDNAlen;
33 extern char sBulletDNAstr64[];
34 extern int sBulletDNAlen64;
35
36 SIMD_FORCE_INLINE       int btStrLen(const char* str) 
37 {
38     if (!str) 
39                 return(0);
40         int len = 0;
41     
42         while (*str != 0)
43         {
44         str++;
45         len++;
46     }
47
48     return len;
49 }
50
51
52 class btChunk
53 {
54 public:
55         int             m_chunkCode;
56         int             m_length;
57         void    *m_oldPtr;
58         int             m_dna_nr;
59         int             m_number;
60 };
61
62 enum    btSerializationFlags
63 {
64         BT_SERIALIZE_NO_BVH = 1,
65         BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
66         BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
67 };
68
69 class   btSerializer
70 {
71
72 public:
73
74         virtual ~btSerializer() {}
75
76         virtual const unsigned char*            getBufferPointer() const = 0;
77
78         virtual int             getCurrentBufferSize() const = 0;
79
80         virtual btChunk*        allocate(size_t size, int numElements) = 0;
81
82         virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
83
84         virtual  void*  findPointer(void* oldPtr)  = 0;
85
86         virtual void*   getUniquePointer(void*oldPtr) = 0;
87
88         virtual void    startSerialization() = 0;
89         
90         virtual void    finishSerialization() = 0;
91
92         virtual const char*     findNameForPointer(const void* ptr) const = 0;
93
94         virtual void    registerNameForPointer(const void* ptr, const char* name) = 0;
95
96         virtual void    serializeName(const char* ptr) = 0;
97
98         virtual int             getSerializationFlags() const = 0;
99
100         virtual void    setSerializationFlags(int flags) = 0;
101
102
103 };
104
105
106
107 #define BT_HEADER_LENGTH 12
108 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
109 #       define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
110 #else
111 #       define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
112 #endif
113
114 #define BT_SOFTBODY_CODE                BT_MAKE_ID('S','B','D','Y')
115 #define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
116 #define BT_RIGIDBODY_CODE               BT_MAKE_ID('R','B','D','Y')
117 #define BT_CONSTRAINT_CODE              BT_MAKE_ID('C','O','N','S')
118 #define BT_BOXSHAPE_CODE                BT_MAKE_ID('B','O','X','S')
119 #define BT_QUANTIZED_BVH_CODE   BT_MAKE_ID('Q','B','V','H')
120 #define BT_TRIANLGE_INFO_MAP    BT_MAKE_ID('T','M','A','P')
121 #define BT_SHAPE_CODE                   BT_MAKE_ID('S','H','A','P')
122 #define BT_ARRAY_CODE                   BT_MAKE_ID('A','R','A','Y')
123 #define BT_SBMATERIAL_CODE              BT_MAKE_ID('S','B','M','T')
124 #define BT_SBNODE_CODE                  BT_MAKE_ID('S','B','N','D')
125 #define BT_DYNAMICSWORLD_CODE   BT_MAKE_ID('D','W','L','D')
126 #define BT_DNA_CODE                             BT_MAKE_ID('D','N','A','1')
127
128
129 struct  btPointerUid
130 {
131         union
132         {
133                 void*   m_ptr;
134                 int             m_uniqueIds[2];
135         };
136 };
137
138 ///The btDefaultSerializer is the main Bullet serialization class.
139 ///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
140 class btDefaultSerializer       :       public btSerializer
141 {
142
143
144         btAlignedObjectArray<char*>                     mTypes;
145         btAlignedObjectArray<short*>                    mStructs;
146         btAlignedObjectArray<short>                     mTlens;
147         btHashMap<btHashInt, int>                       mStructReverse;
148         btHashMap<btHashString,int>     mTypeLookup;
149
150         
151         btHashMap<btHashPtr,void*>      m_chunkP;
152         
153         btHashMap<btHashPtr,const char*>        m_nameMap;
154
155         btHashMap<btHashPtr,btPointerUid>       m_uniquePointers;
156         int     m_uniqueIdGenerator;
157
158         int                                     m_totalSize;
159         unsigned char*          m_buffer;
160         int                                     m_currentSize;
161         void*                           m_dna;
162         int                                     m_dnaLength;
163
164         int                                     m_serializationFlags;
165
166
167         btAlignedObjectArray<btChunk*>  m_chunkPtrs;
168         
169 protected:
170
171         virtual void*   findPointer(void* oldPtr) 
172         {
173                 void** ptr = m_chunkP.find(oldPtr);
174                 if (ptr && *ptr)
175                         return *ptr;
176                 return 0;
177         }
178
179         
180
181
182
183                 void    writeDNA()
184                 {
185                         btChunk* dnaChunk = allocate(m_dnaLength,1);
186                         memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
187                         finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
188                 }
189
190                 int getReverseType(const char *type) const
191                 {
192
193                         btHashString key(type);
194                         const int* valuePtr = mTypeLookup.find(key);
195                         if (valuePtr)
196                                 return *valuePtr;
197                         
198                         return -1;
199                 }
200
201                 void initDNA(const char* bdnaOrg,int dnalen)
202                 {
203                         ///was already initialized
204                         if (m_dna)
205                                 return;
206
207                         int littleEndian= 1;
208                         littleEndian= ((char*)&littleEndian)[0];
209                         
210
211                         m_dna = btAlignedAlloc(dnalen,16);
212                         memcpy(m_dna,bdnaOrg,dnalen);
213                         m_dnaLength = dnalen;
214
215                         int *intPtr=0;
216                         short *shtPtr=0;
217                         char *cp = 0;int dataLen =0;
218                         intPtr = (int*)m_dna;
219
220                         /*
221                                 SDNA (4 bytes) (magic number)
222                                 NAME (4 bytes)
223                                 <nr> (4 bytes) amount of names (int)
224                                 <string>
225                                 <string>
226                         */
227
228                         if (strncmp((const char*)m_dna, "SDNA", 4)==0)
229                         {
230                                 // skip ++ NAME
231                                 intPtr++; intPtr++;
232                         }
233
234                         // Parse names
235                         if (!littleEndian)
236                                 *intPtr = btSwapEndian(*intPtr);
237                                 
238                         dataLen = *intPtr;
239                         
240                         intPtr++;
241
242                         cp = (char*)intPtr;
243                         int i;
244                         for ( i=0; i<dataLen; i++)
245                         {
246                                 
247                                 while (*cp)cp++;
248                                 cp++;
249                         }
250                         cp = btAlignPointer(cp,4);
251
252                         /*
253                                 TYPE (4 bytes)
254                                 <nr> amount of types (int)
255                                 <string>
256                                 <string>
257                         */
258
259                         intPtr = (int*)cp;
260                         btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++;
261
262                         if (!littleEndian)
263                                 *intPtr =  btSwapEndian(*intPtr);
264                         
265                         dataLen = *intPtr;
266                         intPtr++;
267
268                         
269                         cp = (char*)intPtr;
270                         for (i=0; i<dataLen; i++)
271                         {
272                                 mTypes.push_back(cp);
273                                 while (*cp)cp++;
274                                 cp++;
275                         }
276
277                         cp = btAlignPointer(cp,4);
278
279
280                         /*
281                                 TLEN (4 bytes)
282                                 <len> (short) the lengths of types
283                                 <len>
284                         */
285
286                         // Parse type lens
287                         intPtr = (int*)cp;
288                         btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++;
289
290                         dataLen = (int)mTypes.size();
291
292                         shtPtr = (short*)intPtr;
293                         for (i=0; i<dataLen; i++, shtPtr++)
294                         {
295                                 if (!littleEndian)
296                                         shtPtr[0] = btSwapEndian(shtPtr[0]);
297                                 mTlens.push_back(shtPtr[0]);
298                         }
299
300                         if (dataLen & 1) shtPtr++;
301
302                         /*
303                                 STRC (4 bytes)
304                                 <nr> amount of structs (int)
305                                 <typenr>
306                                 <nr_of_elems>
307                                 <typenr>
308                                 <namenr>
309                                 <typenr>
310                                 <namenr>
311                         */
312
313                         intPtr = (int*)shtPtr;
314                         cp = (char*)intPtr;
315                         btAssert(strncmp(cp, "STRC", 4)==0); intPtr++;
316
317                         if (!littleEndian)
318                                 *intPtr = btSwapEndian(*intPtr);
319                         dataLen = *intPtr ; 
320                         intPtr++;
321
322
323                         shtPtr = (short*)intPtr;
324                         for (i=0; i<dataLen; i++)
325                         {
326                                 mStructs.push_back (shtPtr);
327                                 
328                                 if (!littleEndian)
329                                 {
330                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
331                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
332
333                                         int len = shtPtr[1];
334                                         shtPtr+= 2;
335
336                                         for (int a=0; a<len; a++, shtPtr+=2)
337                                         {
338                                                         shtPtr[0]= btSwapEndian(shtPtr[0]);
339                                                         shtPtr[1]= btSwapEndian(shtPtr[1]);
340                                         }
341
342                                 } else
343                                 {
344                                         shtPtr+= (2*shtPtr[1])+2;
345                                 }
346                         }
347
348                         // build reverse lookups
349                         for (i=0; i<(int)mStructs.size(); i++)
350                         {
351                                 short *strc = mStructs.at(i);
352                                 mStructReverse.insert(strc[0], i);
353                                 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
354                         }
355                 }
356
357 public: 
358         
359
360         
361
362                 btDefaultSerializer(int totalSize=0)
363                         :m_totalSize(totalSize),
364                         m_currentSize(0),
365                         m_dna(0),
366                         m_dnaLength(0),
367                         m_serializationFlags(0)
368                 {
369                         m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
370                         
371                         const bool VOID_IS_8 = ((sizeof(void*)==8));
372
373 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
374                         if (VOID_IS_8)
375                         {
376 #if _WIN64
377                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
378 #else
379                                 btAssert(0);
380 #endif
381                         } else
382                         {
383 #ifndef _WIN64
384                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
385 #else
386                                 btAssert(0);
387 #endif
388                         }
389         
390 #else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
391                         if (VOID_IS_8)
392                         {
393                                 initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
394                         } else
395                         {
396                                 initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
397                         }
398 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
399         
400                 }
401
402                 virtual ~btDefaultSerializer() 
403                 {
404                         if (m_buffer)
405                                 btAlignedFree(m_buffer);
406                         if (m_dna)
407                                 btAlignedFree(m_dna);
408                 }
409
410                 void    writeHeader(unsigned char* buffer) const
411                 {
412                         
413
414 #ifdef  BT_USE_DOUBLE_PRECISION
415                         memcpy(buffer, "BULLETd", 7);
416 #else
417                         memcpy(buffer, "BULLETf", 7);
418 #endif //BT_USE_DOUBLE_PRECISION
419         
420                         int littleEndian= 1;
421                         littleEndian= ((char*)&littleEndian)[0];
422
423                         if (sizeof(void*)==8)
424                         {
425                                 buffer[7] = '-';
426                         } else
427                         {
428                                 buffer[7] = '_';
429                         }
430
431                         if (littleEndian)
432                         {
433                                 buffer[8]='v';                          
434                         } else
435                         {
436                                 buffer[8]='V';
437                         }
438
439
440                         buffer[9] = '2';
441                         buffer[10] = '8';
442                         buffer[11] = '1';
443
444                 }
445
446                 virtual void    startSerialization()
447                 {
448                         m_uniqueIdGenerator= 1;
449                         if (m_totalSize)
450                         {
451                                 unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
452                                 writeHeader(buffer);
453                         }
454                         
455                 }
456
457                 virtual void    finishSerialization()
458                 {
459                         writeDNA();
460
461                         //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
462                         int mysize = 0;
463                         if (!m_totalSize)
464                         {
465                                 if (m_buffer)
466                                         btAlignedFree(m_buffer);
467
468                                 m_currentSize += BT_HEADER_LENGTH;
469                                 m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
470
471                                 unsigned char* currentPtr = m_buffer;
472                                 writeHeader(m_buffer);
473                                 currentPtr += BT_HEADER_LENGTH;
474                                 mysize+=BT_HEADER_LENGTH;
475                                 for (int i=0;i< m_chunkPtrs.size();i++)
476                                 {
477                                         int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
478                                         memcpy(currentPtr,m_chunkPtrs[i], curLength);
479                                         btAlignedFree(m_chunkPtrs[i]);
480                                         currentPtr+=curLength;
481                                         mysize+=curLength;
482                                 }
483                         }
484
485                         mTypes.clear();
486                         mStructs.clear();
487                         mTlens.clear();
488                         mStructReverse.clear();
489                         mTypeLookup.clear();
490                         m_chunkP.clear();
491                         m_nameMap.clear();
492                         m_uniquePointers.clear();
493                         m_chunkPtrs.clear();
494                 }
495
496                 virtual void*   getUniquePointer(void*oldPtr)
497                 {
498                         if (!oldPtr)
499                                 return 0;
500
501                         btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
502                         if (uptr)
503                         {
504                                 return uptr->m_ptr;
505                         }
506                         m_uniqueIdGenerator++;
507                         
508                         btPointerUid uid;
509                         uid.m_uniqueIds[0] = m_uniqueIdGenerator;
510                         uid.m_uniqueIds[1] = m_uniqueIdGenerator;
511                         m_uniquePointers.insert(oldPtr,uid);
512                         return uid.m_ptr;
513
514                 }
515
516                 virtual const unsigned char*            getBufferPointer() const
517                 {
518                         return m_buffer;
519                 }
520
521                 virtual int                                     getCurrentBufferSize() const
522                 {
523                         return  m_currentSize;
524                 }
525
526                 virtual void    finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
527                 {
528                         if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
529                         {
530                                 btAssert(!findPointer(oldPtr));
531                         }
532
533                         chunk->m_dna_nr = getReverseType(structType);
534                         
535                         chunk->m_chunkCode = chunkCode;
536                         
537                         void* uniquePtr = getUniquePointer(oldPtr);
538                         
539                         m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
540                         chunk->m_oldPtr = uniquePtr;//oldPtr;
541                         
542                 }
543
544                 
545                 virtual unsigned char* internalAlloc(size_t size)
546                 {
547                         unsigned char* ptr = 0;
548
549                         if (m_totalSize)
550                         {
551                                 ptr = m_buffer+m_currentSize;
552                                 m_currentSize += int(size);
553                                 btAssert(m_currentSize<m_totalSize);
554                         } else
555                         {
556                                 ptr = (unsigned char*)btAlignedAlloc(size,16);
557                                 m_currentSize += int(size);
558                         }
559                         return ptr;
560                 }
561
562                 
563
564                 virtual btChunk*        allocate(size_t size, int numElements)
565                 {
566
567                         unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
568
569                         unsigned char* data = ptr + sizeof(btChunk);
570                         
571                         btChunk* chunk = (btChunk*)ptr;
572                         chunk->m_chunkCode = 0;
573                         chunk->m_oldPtr = data;
574                         chunk->m_length = int(size)*numElements;
575                         chunk->m_number = numElements;
576                         
577                         m_chunkPtrs.push_back(chunk);
578                         
579
580                         return chunk;
581                 }
582
583                 virtual const char*     findNameForPointer(const void* ptr) const
584                 {
585                         const char*const * namePtr = m_nameMap.find(ptr);
586                         if (namePtr && *namePtr)
587                                 return *namePtr;
588                         return 0;
589
590                 }
591
592                 virtual void    registerNameForPointer(const void* ptr, const char* name)
593                 {
594                         m_nameMap.insert(ptr,name);
595                 }
596
597                 virtual void    serializeName(const char* name)
598                 {
599                         if (name)
600                         {
601                                 //don't serialize name twice
602                                 if (findPointer((void*)name))
603                                         return;
604
605                                 int len = btStrLen(name);
606                                 if (len)
607                                 {
608
609                                         int newLen = len+1;
610                                         int padding = ((newLen+3)&~3)-newLen;
611                                         newLen += padding;
612
613                                         //serialize name string now
614                                         btChunk* chunk = allocate(sizeof(char),newLen);
615                                         char* destinationName = (char*)chunk->m_oldPtr;
616                                         for (int i=0;i<len;i++)
617                                         {
618                                                 destinationName[i] = name[i];
619                                         }
620                                         destinationName[len] = 0;
621                                         finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
622                                 }
623                         }
624                 }
625
626                 virtual int             getSerializationFlags() const
627                 {
628                         return m_serializationFlags;
629                 }
630
631                 virtual void    setSerializationFlags(int flags)
632                 {
633                         m_serializationFlags = flags;
634                 }
635
636 };
637
638
639 #endif //BT_SERIALIZER_H
640