123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- /*
- bParse
- Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include <assert.h>
- #include "b3DNA.h"
- #include "b3Chunk.h"
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- //this define will force traversal of structures, to check backward (and forward) compatibility
- //#define TEST_BACKWARD_FORWARD_COMPATIBILITY
- using namespace bParse;
- // ----------------------------------------------------- //
- bDNA::bDNA()
- : mPtrLen(0)
- {
- // --
- }
- // ----------------------------------------------------- //
- bDNA::~bDNA()
- {
- // --
- }
- // ----------------------------------------------------- //
- bool bDNA::lessThan(bDNA *file)
- {
- return (m_Names.size() < file->m_Names.size());
- }
- // ----------------------------------------------------- //
- char *bDNA::getName(int ind)
- {
- assert(ind <= (int)m_Names.size());
- return m_Names[ind].m_name;
- }
- // ----------------------------------------------------- //
- char *bDNA::getType(int ind)
- {
- assert(ind <= (int)mTypes.size());
- return mTypes[ind];
- }
- // ----------------------------------------------------- //
- short *bDNA::getStruct(int ind)
- {
- assert(ind <= (int)mStructs.size());
- return mStructs[ind];
- }
- // ----------------------------------------------------- //
- short bDNA::getLength(int ind)
- {
- assert(ind <= (int)mTlens.size());
- return mTlens[ind];
- }
- // ----------------------------------------------------- //
- int bDNA::getReverseType(short type)
- {
- int *intPtr = mStructReverse.find(type);
- if (intPtr)
- return *intPtr;
- return -1;
- }
- // ----------------------------------------------------- //
- int bDNA::getReverseType(const char *type)
- {
- b3HashString key(type);
- int *valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
- return -1;
- }
- // ----------------------------------------------------- //
- int bDNA::getNumStructs()
- {
- return (int)mStructs.size();
- }
- // ----------------------------------------------------- //
- bool bDNA::flagNotEqual(int dna_nr)
- {
- assert(dna_nr <= (int)mCMPFlags.size());
- return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
- }
- // ----------------------------------------------------- //
- bool bDNA::flagEqual(int dna_nr)
- {
- assert(dna_nr <= (int)mCMPFlags.size());
- int flag = mCMPFlags[dna_nr];
- return flag == FDF_STRUCT_EQU;
- }
- // ----------------------------------------------------- //
- bool bDNA::flagNone(int dna_nr)
- {
- assert(dna_nr <= (int)mCMPFlags.size());
- return mCMPFlags[dna_nr] == FDF_NONE;
- }
- // ----------------------------------------------------- //
- int bDNA::getPointerSize()
- {
- return mPtrLen;
- }
- // ----------------------------------------------------- //
- void bDNA::initRecurseCmpFlags(int iter)
- {
- // iter is FDF_STRUCT_NEQU
- short *oldStrc = mStructs[iter];
- short type = oldStrc[0];
- for (int i = 0; i < (int)mStructs.size(); i++)
- {
- if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
- {
- short *curStruct = mStructs[i];
- int eleLen = curStruct[1];
- curStruct += 2;
- for (int j = 0; j < eleLen; j++, curStruct += 2)
- {
- if (curStruct[0] == type)
- {
- //char *name = m_Names[curStruct[1]].m_name;
- //if (name[0] != '*')
- if (m_Names[curStruct[1]].m_isPointer)
- {
- mCMPFlags[i] = FDF_STRUCT_NEQU;
- initRecurseCmpFlags(i);
- }
- }
- }
- }
- }
- }
- // ----------------------------------------------------- //
- void bDNA::initCmpFlags(bDNA *memDNA)
- {
- // compare the file to memory
- // this ptr should be the file data
- assert(!(m_Names.size() == 0)); // && "SDNA empty!");
- mCMPFlags.resize(mStructs.size(), FDF_NONE);
- int i;
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short *oldStruct = mStructs[i];
- int oldLookup = getReverseType(oldStruct[0]);
- if (oldLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
- //char* typeName = mTypes[oldStruct[0]];
- //#define SLOW_FORWARD_COMPATIBLE 1
- #ifdef SLOW_FORWARD_COMPATIBLE
- char *typeName = mTypes[oldLookup];
- int newLookup = memDNA->getReverseType(typeName);
- if (newLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
- short *curStruct = memDNA->mStructs[newLookup];
- #else
- // memory for file
- if (oldLookup < memDNA->mStructs.size())
- {
- short *curStruct = memDNA->mStructs[oldLookup];
- #endif
- // rebuild...
- mCMPFlags[i] = FDF_STRUCT_NEQU;
- #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
- if (curStruct[1] == oldStruct[1])
- {
- // type len same ...
- if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
- {
- bool isSame = true;
- int elementLength = oldStruct[1];
- curStruct += 2;
- oldStruct += 2;
- for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
- {
- // type the same
- //const char* typeFileDNA = mTypes[oldStruct[0]];
- //const char* typeMemDNA = mTypes[curStruct[0]];
- if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
- {
- isSame = false;
- break;
- }
- // name the same
- if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
- {
- isSame = false;
- break;
- }
- }
- // flag valid ==
- if (isSame)
- mCMPFlags[i] = FDF_STRUCT_EQU;
- }
- }
- #endif
- }
- }
- // recurse in
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- if (mCMPFlags[i] == FDF_STRUCT_NEQU)
- initRecurseCmpFlags(i);
- }
- }
- static int name_is_array(char *name, int *dim1, int *dim2)
- {
- int len = strlen(name);
- /*fprintf(stderr,"[%s]",name);*/
- /*if (len >= 1) {
- if (name[len-1] != ']')
- return 1;
- }
- return 0;*/
- char *bp;
- int num;
- if (dim1)
- {
- *dim1 = 1;
- }
- if (dim2)
- {
- *dim2 = 1;
- }
- bp = strchr(name, '[');
- if (!bp)
- {
- return 0;
- }
- num = 0;
- while (++bp < name + len - 1)
- {
- const char c = *bp;
- if (c == ']')
- {
- break;
- }
- if (c <= '9' && c >= '0')
- {
- num *= 10;
- num += (c - '0');
- }
- else
- {
- printf("array parse error.\n");
- return 0;
- }
- }
- if (dim2)
- {
- *dim2 = num;
- }
- /* find second dim, if any. */
- bp = strchr(bp, '[');
- if (!bp)
- {
- return 1; /* at least we got the first dim. */
- }
- num = 0;
- while (++bp < name + len - 1)
- {
- const char c = *bp;
- if (c == ']')
- {
- break;
- }
- if (c <= '9' && c >= '0')
- {
- num *= 10;
- num += (c - '0');
- }
- else
- {
- printf("array2 parse error.\n");
- return 1;
- }
- }
- if (dim1)
- {
- if (dim2)
- {
- *dim1 = *dim2;
- *dim2 = num;
- }
- else
- {
- *dim1 = num;
- }
- }
- return 1;
- }
- // ----------------------------------------------------- //
- void bDNA::init(char *data, int len, bool swap)
- {
- int *intPtr = 0;
- short *shtPtr = 0;
- char *cp = 0;
- int dataLen = 0;
- //long nr=0;
- intPtr = (int *)data;
- /*
- SDNA (4 bytes) (magic number)
- NAME (4 bytes)
- <nr> (4 bytes) amount of names (int)
- <string>
- <string>
- */
- if (strncmp(data, "SDNA", 4) == 0)
- {
- // skip ++ NAME
- intPtr++;
- intPtr++;
- }
- // Parse names
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
- cp = (char *)intPtr;
- int i;
- for (i = 0; i < dataLen; i++)
- {
- bNameInfo info;
- info.m_name = cp;
- info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
- name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
- m_Names.push_back(info);
- while (*cp) cp++;
- cp++;
- }
- cp = b3AlignPointer(cp, 4);
- /*
- TYPE (4 bytes)
- <nr> amount of types (int)
- <string>
- <string>
- */
- intPtr = (int *)cp;
- assert(strncmp(cp, "TYPE", 4) == 0);
- intPtr++;
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
- cp = (char *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp) cp++;
- cp++;
- }
- cp = b3AlignPointer(cp, 4);
- /*
- TLEN (4 bytes)
- <len> (short) the lengths of types
- <len>
- */
- // Parse type lens
- intPtr = (int *)cp;
- assert(strncmp(cp, "TLEN", 4) == 0);
- intPtr++;
- dataLen = (int)mTypes.size();
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++, shtPtr++)
- {
- if (swap)
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
- if (dataLen & 1) shtPtr++;
- /*
- STRC (4 bytes)
- <nr> amount of structs (int)
- <typenr>
- <nr_of_elems>
- <typenr>
- <namenr>
- <typenr>
- <namenr>
- */
- intPtr = (int *)shtPtr;
- cp = (char *)intPtr;
- assert(strncmp(cp, "STRC", 4) == 0);
- intPtr++;
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mStructs.push_back(shtPtr);
- if (swap)
- {
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
- int len = shtPtr[1];
- shtPtr += 2;
- for (int a = 0; a < len; a++, shtPtr += 2)
- {
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
- }
- }
- else
- shtPtr += (2 * shtPtr[1]) + 2;
- }
- // build reverse lookups
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short *strc = mStructs.at(i);
- if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
- {
- mPtrLen = mTlens[strc[0]] / 2;
- }
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
- }
- }
- // ----------------------------------------------------- //
- int bDNA::getArraySize(char *string)
- {
- int ret = 1;
- int len = strlen(string);
- char *next = 0;
- for (int i = 0; i < len; i++)
- {
- char c = string[i];
- if (c == '[')
- next = &string[i + 1];
- else if (c == ']')
- if (next)
- ret *= atoi(next);
- }
- // print (string << ' ' << ret);
- return ret;
- }
- void bDNA::dumpTypeDefinitions()
- {
- int i;
- int numTypes = mTypes.size();
- for (i = 0; i < numTypes; i++)
- {
- }
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- int totalBytes = 0;
- short *oldStruct = mStructs[i];
- int oldLookup = getReverseType(oldStruct[0]);
- if (oldLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
- short *newStruct = mStructs[oldLookup];
- char *typeName = mTypes[newStruct[0]];
- printf("%3d: %s ", i, typeName);
- //char *name = mNames[oldStruct[1]];
- int len = oldStruct[1];
- printf(" (%d fields) ", len);
- oldStruct += 2;
- printf("{");
- int j;
- for (j = 0; j < len; ++j, oldStruct += 2)
- {
- const char *name = m_Names[oldStruct[1]].m_name;
- printf("%s %s", mTypes[oldStruct[0]], name);
- int elemNumBytes = 0;
- int arrayDimensions = getArraySizeNew(oldStruct[1]);
- if (m_Names[oldStruct[1]].m_isPointer)
- {
- elemNumBytes = VOID_IS_8 ? 8 : 4;
- }
- else
- {
- elemNumBytes = getLength(oldStruct[0]);
- }
- printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
- if (j == len - 1)
- {
- printf(";}");
- }
- else
- {
- printf("; ");
- }
- totalBytes += elemNumBytes * arrayDimensions;
- }
- printf("\ntotalBytes=%d\n\n", totalBytes);
- }
- #if 0
- /* dump out display of types and their sizes */
- for (i=0; i<bf->types_count; ++i) {
- /* if (!bf->types[i].is_struct)*/
- {
- printf("%3d: sizeof(%s%s)=%d",
- i,
- bf->types[i].is_struct ? "struct " : "atomic ",
- bf->types[i].name, bf->types[i].size);
- if (bf->types[i].is_struct) {
- int j;
- printf(", %d fields: { ", bf->types[i].fieldtypes_count);
- for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
- printf("%s %s",
- bf->types[bf->types[i].fieldtypes[j]].name,
- bf->names[bf->types[i].fieldnames[j]]);
- if (j == bf->types[i].fieldtypes_count-1) {
- printf(";}");
- } else {
- printf("; ");
- }
- }
- }
- printf("\n\n");
- }
- }
- #endif
- }
- //eof
|