b3DNA.cpp 12 KB

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