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