[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / bullet3 / src / Bullet3Serialize / Bullet2FileLoader / b3DNA.cpp
1 /*
2 bParse
3 Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
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 #include <assert.h>
16
17 #include "b3DNA.h"
18 #include "b3Chunk.h"
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 //this define will force traversal of structures, to check backward (and forward) compatibility
24 //#define TEST_BACKWARD_FORWARD_COMPATIBILITY
25
26 using namespace bParse;
27
28 // ----------------------------------------------------- //
29 bDNA::bDNA()
30         : mPtrLen(0)
31 {
32         // --
33 }
34
35 // ----------------------------------------------------- //
36 bDNA::~bDNA()
37 {
38         // --
39 }
40
41 // ----------------------------------------------------- //
42 bool bDNA::lessThan(bDNA *file)
43 {
44         return (m_Names.size() < file->m_Names.size());
45 }
46
47 // ----------------------------------------------------- //
48 char *bDNA::getName(int ind)
49 {
50         assert(ind <= (int)m_Names.size());
51         return m_Names[ind].m_name;
52 }
53
54 // ----------------------------------------------------- //
55 char *bDNA::getType(int ind)
56 {
57         assert(ind <= (int)mTypes.size());
58         return mTypes[ind];
59 }
60
61 // ----------------------------------------------------- //
62 short *bDNA::getStruct(int ind)
63 {
64         assert(ind <= (int)mStructs.size());
65         return mStructs[ind];
66 }
67
68 // ----------------------------------------------------- //
69 short bDNA::getLength(int ind)
70 {
71         assert(ind <= (int)mTlens.size());
72         return mTlens[ind];
73 }
74
75 // ----------------------------------------------------- //
76 int bDNA::getReverseType(short type)
77 {
78         int *intPtr = mStructReverse.find(type);
79         if (intPtr)
80                 return *intPtr;
81
82         return -1;
83 }
84
85 // ----------------------------------------------------- //
86 int bDNA::getReverseType(const char *type)
87 {
88         b3HashString key(type);
89         int *valuePtr = mTypeLookup.find(key);
90         if (valuePtr)
91                 return *valuePtr;
92
93         return -1;
94 }
95
96 // ----------------------------------------------------- //
97 int bDNA::getNumStructs()
98 {
99         return (int)mStructs.size();
100 }
101
102 // ----------------------------------------------------- //
103 bool bDNA::flagNotEqual(int dna_nr)
104 {
105         assert(dna_nr <= (int)mCMPFlags.size());
106         return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
107 }
108
109 // ----------------------------------------------------- //
110 bool bDNA::flagEqual(int dna_nr)
111 {
112         assert(dna_nr <= (int)mCMPFlags.size());
113         int flag = mCMPFlags[dna_nr];
114         return flag == FDF_STRUCT_EQU;
115 }
116
117 // ----------------------------------------------------- //
118 bool bDNA::flagNone(int dna_nr)
119 {
120         assert(dna_nr <= (int)mCMPFlags.size());
121         return mCMPFlags[dna_nr] == FDF_NONE;
122 }
123
124 // ----------------------------------------------------- //
125 int bDNA::getPointerSize()
126 {
127         return mPtrLen;
128 }
129
130 // ----------------------------------------------------- //
131 void bDNA::initRecurseCmpFlags(int iter)
132 {
133         // iter is FDF_STRUCT_NEQU
134
135         short *oldStrc = mStructs[iter];
136         short type = oldStrc[0];
137
138         for (int i = 0; i < (int)mStructs.size(); i++)
139         {
140                 if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
141                 {
142                         short *curStruct = mStructs[i];
143                         int eleLen = curStruct[1];
144                         curStruct += 2;
145
146                         for (int j = 0; j < eleLen; j++, curStruct += 2)
147                         {
148                                 if (curStruct[0] == type)
149                                 {
150                                         //char *name = m_Names[curStruct[1]].m_name;
151                                         //if (name[0] != '*')
152                                         if (m_Names[curStruct[1]].m_isPointer)
153                                         {
154                                                 mCMPFlags[i] = FDF_STRUCT_NEQU;
155                                                 initRecurseCmpFlags(i);
156                                         }
157                                 }
158                         }
159                 }
160         }
161 }
162
163 // ----------------------------------------------------- //
164 void bDNA::initCmpFlags(bDNA *memDNA)
165 {
166         // compare the file to memory
167         // this ptr should be the file data
168
169         assert(!(m_Names.size() == 0));  // && "SDNA empty!");
170         mCMPFlags.resize(mStructs.size(), FDF_NONE);
171
172         int i;
173         for (i = 0; i < (int)mStructs.size(); i++)
174         {
175                 short *oldStruct = mStructs[i];
176
177                 int oldLookup = getReverseType(oldStruct[0]);
178                 if (oldLookup == -1)
179                 {
180                         mCMPFlags[i] = FDF_NONE;
181                         continue;
182                 }
183                 //char* typeName = mTypes[oldStruct[0]];
184
185 //#define SLOW_FORWARD_COMPATIBLE 1
186 #ifdef SLOW_FORWARD_COMPATIBLE
187                 char *typeName = mTypes[oldLookup];
188                 int newLookup = memDNA->getReverseType(typeName);
189                 if (newLookup == -1)
190                 {
191                         mCMPFlags[i] = FDF_NONE;
192                         continue;
193                 }
194                 short *curStruct = memDNA->mStructs[newLookup];
195 #else
196                 // memory for file
197
198                 if (oldLookup < memDNA->mStructs.size())
199                 {
200                         short *curStruct = memDNA->mStructs[oldLookup];
201 #endif
202
203                 // rebuild...
204                 mCMPFlags[i] = FDF_STRUCT_NEQU;
205
206 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
207
208                 if (curStruct[1] == oldStruct[1])
209                 {
210                         // type len same ...
211                         if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
212                         {
213                                 bool isSame = true;
214                                 int elementLength = oldStruct[1];
215
216                                 curStruct += 2;
217                                 oldStruct += 2;
218
219                                 for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
220                                 {
221                                         // type the same
222                                         //const char* typeFileDNA = mTypes[oldStruct[0]];
223                                         //const char* typeMemDNA = mTypes[curStruct[0]];
224                                         if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
225                                         {
226                                                 isSame = false;
227                                                 break;
228                                         }
229
230                                         // name the same
231                                         if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
232                                         {
233                                                 isSame = false;
234                                                 break;
235                                         }
236                                 }
237                                 // flag valid ==
238                                 if (isSame)
239                                         mCMPFlags[i] = FDF_STRUCT_EQU;
240                         }
241                 }
242 #endif
243         }
244 }
245
246 // recurse in
247 for (i = 0; i < (int)mStructs.size(); i++)
248 {
249         if (mCMPFlags[i] == FDF_STRUCT_NEQU)
250                 initRecurseCmpFlags(i);
251 }
252 }
253
254 static int name_is_array(char *name, int *dim1, int *dim2)
255 {
256         int len = strlen(name);
257         /*fprintf(stderr,"[%s]",name);*/
258         /*if (len >= 1) {
259         if (name[len-1] != ']')
260         return 1;
261         }
262         return 0;*/
263         char *bp;
264         int num;
265         if (dim1)
266         {
267                 *dim1 = 1;
268         }
269         if (dim2)
270         {
271                 *dim2 = 1;
272         }
273         bp = strchr(name, '[');
274         if (!bp)
275         {
276                 return 0;
277         }
278         num = 0;
279         while (++bp < name + len - 1)
280         {
281                 const char c = *bp;
282                 if (c == ']')
283                 {
284                         break;
285                 }
286                 if (c <= '9' && c >= '0')
287                 {
288                         num *= 10;
289                         num += (c - '0');
290                 }
291                 else
292                 {
293                         printf("array parse error.\n");
294                         return 0;
295                 }
296         }
297         if (dim2)
298         {
299                 *dim2 = num;
300         }
301
302         /* find second dim, if any. */
303         bp = strchr(bp, '[');
304         if (!bp)
305         {
306                 return 1; /* at least we got the first dim. */
307         }
308         num = 0;
309         while (++bp < name + len - 1)
310         {
311                 const char c = *bp;
312                 if (c == ']')
313                 {
314                         break;
315                 }
316                 if (c <= '9' && c >= '0')
317                 {
318                         num *= 10;
319                         num += (c - '0');
320                 }
321                 else
322                 {
323                         printf("array2 parse error.\n");
324                         return 1;
325                 }
326         }
327         if (dim1)
328         {
329                 if (dim2)
330                 {
331                         *dim1 = *dim2;
332                         *dim2 = num;
333                 }
334                 else
335                 {
336                         *dim1 = num;
337                 }
338         }
339
340         return 1;
341 }
342
343 // ----------------------------------------------------- //
344 void bDNA::init(char *data, int len, bool swap)
345 {
346         int *intPtr = 0;
347         short *shtPtr = 0;
348         char *cp = 0;
349         int dataLen = 0;
350         //long nr=0;
351         intPtr = (int *)data;
352
353         /*
354                 SDNA (4 bytes) (magic number)
355                 NAME (4 bytes)
356                 <nr> (4 bytes) amount of names (int)
357                 <string>
358                 <string>
359         */
360
361         if (strncmp(data, "SDNA", 4) == 0)
362         {
363                 // skip ++ NAME
364                 intPtr++;
365                 intPtr++;
366         }
367
368         // Parse names
369         if (swap)
370         {
371                 *intPtr = ChunkUtils::swapInt(*intPtr);
372         }
373         dataLen = *intPtr;
374         intPtr++;
375
376         cp = (char *)intPtr;
377         int i;
378         for (i = 0; i < dataLen; i++)
379         {
380                 bNameInfo info;
381                 info.m_name = cp;
382                 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
383                 name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
384                 m_Names.push_back(info);
385                 while (*cp) cp++;
386                 cp++;
387         }
388
389         cp = b3AlignPointer(cp, 4);
390
391         /*
392                 TYPE (4 bytes)
393                 <nr> amount of types (int)
394                 <string>
395                 <string>
396         */
397
398         intPtr = (int *)cp;
399         assert(strncmp(cp, "TYPE", 4) == 0);
400         intPtr++;
401
402         if (swap)
403         {
404                 *intPtr = ChunkUtils::swapInt(*intPtr);
405         }
406         dataLen = *intPtr;
407         intPtr++;
408
409         cp = (char *)intPtr;
410         for (i = 0; i < dataLen; i++)
411         {
412                 mTypes.push_back(cp);
413                 while (*cp) cp++;
414                 cp++;
415         }
416
417         cp = b3AlignPointer(cp, 4);
418
419         /*
420                 TLEN (4 bytes)
421                 <len> (short) the lengths of types
422                 <len>
423         */
424
425         // Parse type lens
426         intPtr = (int *)cp;
427         assert(strncmp(cp, "TLEN", 4) == 0);
428         intPtr++;
429
430         dataLen = (int)mTypes.size();
431
432         shtPtr = (short *)intPtr;
433         for (i = 0; i < dataLen; i++, shtPtr++)
434         {
435                 if (swap)
436                         shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
437                 mTlens.push_back(shtPtr[0]);
438         }
439
440         if (dataLen & 1) shtPtr++;
441
442         /*
443                 STRC (4 bytes)
444                 <nr> amount of structs (int)
445                 <typenr>
446                 <nr_of_elems>
447                 <typenr>
448                 <namenr>
449                 <typenr>
450                 <namenr>
451         */
452
453         intPtr = (int *)shtPtr;
454         cp = (char *)intPtr;
455         assert(strncmp(cp, "STRC", 4) == 0);
456         intPtr++;
457
458         if (swap)
459         {
460                 *intPtr = ChunkUtils::swapInt(*intPtr);
461         }
462         dataLen = *intPtr;
463         intPtr++;
464
465         shtPtr = (short *)intPtr;
466         for (i = 0; i < dataLen; i++)
467         {
468                 mStructs.push_back(shtPtr);
469                 if (swap)
470                 {
471                         shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
472                         shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
473
474                         int len = shtPtr[1];
475                         shtPtr += 2;
476
477                         for (int a = 0; a < len; a++, shtPtr += 2)
478                         {
479                                 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
480                                 shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
481                         }
482                 }
483                 else
484                         shtPtr += (2 * shtPtr[1]) + 2;
485         }
486
487         // build reverse lookups
488         for (i = 0; i < (int)mStructs.size(); i++)
489         {
490                 short *strc = mStructs.at(i);
491                 if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
492                 {
493                         mPtrLen = mTlens[strc[0]] / 2;
494                 }
495
496                 mStructReverse.insert(strc[0], i);
497                 mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
498         }
499 }
500
501 // ----------------------------------------------------- //
502 int bDNA::getArraySize(char *string)
503 {
504         int ret = 1;
505         int len = strlen(string);
506
507         char *next = 0;
508         for (int i = 0; i < len; i++)
509         {
510                 char c = string[i];
511
512                 if (c == '[')
513                         next = &string[i + 1];
514                 else if (c == ']')
515                         if (next)
516                                 ret *= atoi(next);
517         }
518
519         //      print (string << ' ' << ret);
520         return ret;
521 }
522
523 void bDNA::dumpTypeDefinitions()
524 {
525         int i;
526
527         int numTypes = mTypes.size();
528
529         for (i = 0; i < numTypes; i++)
530         {
531         }
532
533         for (i = 0; i < (int)mStructs.size(); i++)
534         {
535                 int totalBytes = 0;
536                 short *oldStruct = mStructs[i];
537
538                 int oldLookup = getReverseType(oldStruct[0]);
539                 if (oldLookup == -1)
540                 {
541                         mCMPFlags[i] = FDF_NONE;
542                         continue;
543                 }
544
545                 short *newStruct = mStructs[oldLookup];
546                 char *typeName = mTypes[newStruct[0]];
547                 printf("%3d: %s ", i, typeName);
548
549                 //char *name = mNames[oldStruct[1]];
550                 int len = oldStruct[1];
551                 printf(" (%d fields) ", len);
552                 oldStruct += 2;
553
554                 printf("{");
555                 int j;
556                 for (j = 0; j < len; ++j, oldStruct += 2)
557                 {
558                         const char *name = m_Names[oldStruct[1]].m_name;
559                         printf("%s %s", mTypes[oldStruct[0]], name);
560                         int elemNumBytes = 0;
561                         int arrayDimensions = getArraySizeNew(oldStruct[1]);
562
563                         if (m_Names[oldStruct[1]].m_isPointer)
564                         {
565                                 elemNumBytes = VOID_IS_8 ? 8 : 4;
566                         }
567                         else
568                         {
569                                 elemNumBytes = getLength(oldStruct[0]);
570                         }
571                         printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
572
573                         if (j == len - 1)
574                         {
575                                 printf(";}");
576                         }
577                         else
578                         {
579                                 printf("; ");
580                         }
581                         totalBytes += elemNumBytes * arrayDimensions;
582                 }
583                 printf("\ntotalBytes=%d\n\n", totalBytes);
584         }
585
586 #if 0
587         /* dump out display of types and their sizes */
588         for (i=0; i<bf->types_count; ++i) {
589                 /* if (!bf->types[i].is_struct)*/
590                 {
591                         printf("%3d: sizeof(%s%s)=%d",
592                                 i,
593                                 bf->types[i].is_struct ? "struct " : "atomic ",
594                                 bf->types[i].name, bf->types[i].size);
595                         if (bf->types[i].is_struct) {
596                                 int j;
597                                 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
598                                 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
599                                         printf("%s %s",
600                                                 bf->types[bf->types[i].fieldtypes[j]].name,
601                                                 bf->names[bf->types[i].fieldnames[j]]);
602                                         if (j == bf->types[i].fieldtypes_count-1) {
603                                                 printf(";}");
604                                         } else {
605                                                 printf("; ");
606                                         }
607                                 }
608                         }
609                         printf("\n\n");
610
611                 }
612         }
613 #endif
614 }
615
616 //eof