123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "console/consoleObject.h"
- #include "string/stringTable.h"
- #include "algorithm/crc.h"
- #include "console/console.h"
- #include "console/consoleInternal.h"
- #include "console/ConsoleTypeValidators.h"
- #include "math/mMath.h"
- AbstractClassRep * AbstractClassRep::classLinkList = NULL;
- static AbstractClassRep::FieldList sg_tempFieldList;
- U32 AbstractClassRep::NetClassCount [NetClassGroupsCount][NetClassTypesCount] = {{0, },};
- U32 AbstractClassRep::NetClassBitSize[NetClassGroupsCount][NetClassTypesCount] = {{0, },};
- AbstractClassRep ** AbstractClassRep::classTable[NetClassGroupsCount][NetClassTypesCount];
- U32 AbstractClassRep::classCRC[NetClassGroupsCount] = {INITIAL_CRC_VALUE, };
- bool AbstractClassRep::initialized = false;
- //--------------------------------------
- const AbstractClassRep::Field *AbstractClassRep::findField(StringTableEntry name) const
- {
- for(U32 i = 0; i < (U32)mFieldList.size(); i++)
- if(mFieldList[i].pFieldname == name)
- return &mFieldList[i];
- return NULL;
- }
- //-----------------------------------------------------------------------------
- AbstractClassRep* AbstractClassRep::findFieldRoot( StringTableEntry fieldName )
- {
- // Find the field.
- const Field* pField = findField( fieldName );
- // Finish if not found.
- if ( pField == NULL )
- return NULL;
- // We're the root if we have no parent.
- if ( getParentClass() == NULL )
- return this;
- // Find the field root via the parent.
- AbstractClassRep* pFieldRoot = getParentClass()->findFieldRoot( fieldName );
- // We're the root if the parent does not have it else return the field root.
- return pFieldRoot == NULL ? this : pFieldRoot;
- }
- //-----------------------------------------------------------------------------
- AbstractClassRep* AbstractClassRep::findContainerChildRoot( AbstractClassRep* pChild )
- {
- // Fetch container child.
- AbstractClassRep* pContainerChildClass = getContainerChildClass( true );
- // Finish if not found.
- if ( pContainerChildClass == NULL )
- return NULL;
- // We're the root for the child if we have no parent.
- if ( getParentClass() == NULL )
- return this;
- // Find child in parent.
- AbstractClassRep* pParentContainerChildClass = getParentClass()->findContainerChildRoot( pChild );
- // We;re the root if the parent does not contain the child else return the container root.
- return pParentContainerChildClass == NULL ? this : pParentContainerChildClass;
- }
- //-----------------------------------------------------------------------------
- AbstractClassRep* AbstractClassRep::findClassRep(const char* in_pClassName)
- {
- AssertFatal(initialized,
- "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize().");
- for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
- if (dStricmp(walk->getClassName(), in_pClassName) == 0)
- return walk;
- return NULL;
- }
- //--------------------------------------
- void AbstractClassRep::registerClassRep(AbstractClassRep* in_pRep)
- {
- AssertFatal(in_pRep != NULL, "AbstractClassRep::registerClassRep was passed a NULL pointer!");
- #ifdef TORQUE_DEBUG // assert if this class is already registered.
- for(AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
- {
- AssertFatal(dStricmp(in_pRep->mClassName, walk->mClassName) != 0,
- "Duplicate class name registered in AbstractClassRep::registerClassRep()");
- }
- #endif
- in_pRep->nextClass = classLinkList;
- classLinkList = in_pRep;
- }
- //--------------------------------------
- ConsoleObject* AbstractClassRep::create(const char* in_pClassName)
- {
- AssertFatal(initialized,
- "AbstractClassRep::create() - Tried to create an object before AbstractClassRep::initialize().");
- const AbstractClassRep *rep = AbstractClassRep::findClassRep(in_pClassName);
- if(rep)
- return rep->create();
- AssertWarn(0, avar("Couldn't find class rep for dynamic class: %s", in_pClassName));
- return NULL;
- }
- //--------------------------------------
- ConsoleObject* AbstractClassRep::create(const U32 groupId, const U32 typeId, const U32 in_classId)
- {
- AssertFatal(initialized,
- "AbstractClassRep::create() - Tried to create an object before AbstractClassRep::initialize().");
- AssertFatal(in_classId < NetClassCount[groupId][typeId],
- "AbstractClassRep::create() - Class id out of range.");
- AssertFatal(classTable[groupId][typeId][in_classId] != NULL,
- "AbstractClassRep::create() - No class with requested ID type.");
- // Look up the specified class and create it.
- if(classTable[groupId][typeId][in_classId])
- return classTable[groupId][typeId][in_classId]->create();
- return NULL;
- }
- //--------------------------------------
- S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr)
- {
- const AbstractClassRep *a = *((const AbstractClassRep **) aptr);
- const AbstractClassRep *b = *((const AbstractClassRep **) bptr);
- if(a->mClassType != b->mClassType)
- return a->mClassType - b->mClassType;
- return dStricmp(a->getClassName(), b->getClassName());
- }
- void AbstractClassRep::initialize()
- {
- AssertFatal(!initialized, "Duplicate call to AbstractClassRep::initialize()!");
- Vector<AbstractClassRep *> dynamicTable(__FILE__, __LINE__);
- AbstractClassRep *walk;
- // Initialize namespace references...
- for (walk = classLinkList; walk; walk = walk->nextClass)
- {
- walk->mNamespace = Con::lookupNamespace(StringTable->insert(walk->getClassName()));
- walk->mNamespace->mClassRep = walk;
- }
- // Initialize field lists... (and perform other console registration).
- for (walk = classLinkList; walk; walk = walk->nextClass)
- {
- // sg_tempFieldList is used as a staging area for field lists
- // (see addField, addGroup, etc.)
- sg_tempFieldList.setSize(0);
- walk->init();
- // So if we have things in it, copy it over...
- if (sg_tempFieldList.size() != 0)
- {
- if( !walk->mFieldList.size())
- walk->mFieldList = sg_tempFieldList;
- else
- destroyFieldValidators( sg_tempFieldList );
- }
- // And of course delete it every round.
- sg_tempFieldList.clear();
- }
- // Calculate counts and bit sizes for the various NetClasses.
- for (U32 group = 0; group < NetClassGroupsCount; group++)
- {
- U32 groupMask = 1 << group;
- // Specifically, for each NetClass of each NetGroup...
- for(U32 type = 0; type < NetClassTypesCount; type++)
- {
- // Go through all the classes and find matches...
- for (walk = classLinkList; walk; walk = walk->nextClass)
- {
- if(walk->mClassType == type && walk->mClassGroupMask & groupMask)
- dynamicTable.push_back(walk);
- }
- // Set the count for this NetGroup and NetClass
- NetClassCount[group][type] = dynamicTable.size();
- if(!NetClassCount[group][type])
- continue; // If no classes matched, skip to next.
- // Sort by type and then by name.
- dQsort((void *)dynamicTable.address(), dynamicTable.size(), sizeof(AbstractClassRep *), ACRCompare);
- // Allocate storage in the classTable
- classTable[group][type] = new AbstractClassRep*[NetClassCount[group][type]];
- // Fill this in and assign class ids for this group.
- for(U32 i = 0; i < NetClassCount[group][type];i++)
- {
- classTable[group][type][i] = dynamicTable[i];
- dynamicTable[i]->mClassId[group] = i;
- }
- // And calculate the size of bitfields for this group and type.
- NetClassBitSize[group][type] =
- getBinLog2(getNextPow2(NetClassCount[group][type] + 1));
- dynamicTable.clear();
- }
- }
- // Ok, we're golden!
- initialized = true;
- }
- void AbstractClassRep::destroyFieldValidators( AbstractClassRep::FieldList &mFieldList )
- {
- for(S32 i = mFieldList.size()-1; i>=0; i-- )
- {
- ConsoleTypeValidator **p = &mFieldList[i].validator;
- if( *p )
- {
- delete *p;
- *p = NULL;
- }
- }
- }
- //------------------------------------------------------------------------------
- //-------------------------------------- ConsoleObject
- char replacebuf[1024];
- char* suppressSpaces(const char* in_pname)
- {
- U32 i = 0;
- char chr;
- do
- {
- chr = in_pname[i];
- replacebuf[i++] = (chr != 32) ? chr : '_';
- } while(chr);
- return replacebuf;
- }
- void ConsoleObject::addGroup(const char* in_pGroupname, const char* in_pGroupDocs)
- {
- // Remove spaces.
- char* pFieldNameBuf = suppressSpaces(in_pGroupname);
- // Append group type to fieldname.
- dStrcat(pFieldNameBuf, "_begingroup");
- // Create Field.
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(pFieldNameBuf);
- f.pGroupname = StringTable->insert(in_pGroupname);
- if(in_pGroupDocs)
- f.pFieldDocs = StringTable->insert(in_pGroupDocs);
- else
- f.pFieldDocs = NULL;
- f.type = AbstractClassRep::StartGroupFieldType;
- f.elementCount = 0;
- f.groupExpand = false;
- f.validator = NULL;
- f.setDataFn = &defaultProtectedSetFn;
- f.getDataFn = &defaultProtectedGetFn;
- f.writeDataFn = &defaultProtectedWriteFn;
- // Add to field list.
- sg_tempFieldList.push_back(f);
- }
- void ConsoleObject::endGroup(const char* in_pGroupname)
- {
- // Remove spaces.
- char* pFieldNameBuf = suppressSpaces(in_pGroupname);
- // Append group type to fieldname.
- dStrcat(pFieldNameBuf, "_endgroup");
- // Create Field.
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(pFieldNameBuf);
- f.pGroupname = StringTable->insert(in_pGroupname);
- f.pFieldDocs = NULL;
- f.type = AbstractClassRep::EndGroupFieldType;
- f.groupExpand = false;
- f.validator = NULL;
- f.setDataFn = &defaultProtectedSetFn;
- f.getDataFn = &defaultProtectedGetFn;
- f.writeDataFn = &defaultProtectedWriteFn;
- f.elementCount = 0;
- // Add to field list.
- sg_tempFieldList.push_back(f);
- }
- void ConsoleObject::addField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- const char* in_pFieldDocs)
- {
- addField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- &defaultProtectedWriteFn,
- 1,
- NULL,
- in_pFieldDocs);
- }
- void ConsoleObject::addField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::WriteDataNotify in_writeDataFn,
- const char* in_pFieldDocs)
- {
- addField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- in_writeDataFn,
- 1,
- NULL,
- in_pFieldDocs);
- }
- void ConsoleObject::addField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- const U32 in_elementCount,
- EnumTable *in_table,
- const char* in_pFieldDocs)
- {
- addField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- &defaultProtectedWriteFn,
- in_elementCount,
- in_table,
- in_pFieldDocs);
- }
- void ConsoleObject::addField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::WriteDataNotify in_writeDataFn,
- const U32 in_elementCount,
- EnumTable *in_table,
- const char* in_pFieldDocs)
- {
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(in_pFieldname);
- f.pGroupname = NULL;
- if(in_pFieldDocs)
- f.pFieldDocs = StringTable->insert(in_pFieldDocs);
- else
- f.pFieldDocs = NULL;
- f.type = in_fieldType;
- f.offset = in_fieldOffset;
- f.elementCount = in_elementCount;
- f.table = in_table;
- f.validator = NULL;
- f.setDataFn = &defaultProtectedSetFn;
- f.getDataFn = &defaultProtectedGetFn;
- f.writeDataFn = in_writeDataFn;
- sg_tempFieldList.push_back(f);
- }
- void ConsoleObject::addProtectedField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::SetDataNotify in_setDataFn,
- AbstractClassRep::GetDataNotify in_getDataFn,
- const char* in_pFieldDocs)
- {
- addProtectedField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- in_setDataFn,
- in_getDataFn,
- &defaultProtectedWriteFn,
- 1,
- NULL,
- in_pFieldDocs);
- }
- void ConsoleObject::addProtectedField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::SetDataNotify in_setDataFn,
- AbstractClassRep::GetDataNotify in_getDataFn,
- AbstractClassRep::WriteDataNotify in_writeDataFn,
- const char* in_pFieldDocs)
- {
- addProtectedField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- in_setDataFn,
- in_getDataFn,
- in_writeDataFn,
- 1,
- NULL,
- in_pFieldDocs);
- }
- void ConsoleObject::addProtectedField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::SetDataNotify in_setDataFn,
- AbstractClassRep::GetDataNotify in_getDataFn,
- const U32 in_elementCount,
- EnumTable *in_table,
- const char* in_pFieldDocs)
- {
- addProtectedField(
- in_pFieldname,
- in_fieldType,
- in_fieldOffset,
- in_setDataFn,
- in_getDataFn,
- &defaultProtectedWriteFn,
- in_elementCount,
- in_table,
- in_pFieldDocs);
- }
- void ConsoleObject::addProtectedField(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- AbstractClassRep::SetDataNotify in_setDataFn,
- AbstractClassRep::GetDataNotify in_getDataFn,
- AbstractClassRep::WriteDataNotify in_writeDataFn,
- const U32 in_elementCount,
- EnumTable *in_table,
- const char* in_pFieldDocs)
- {
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(in_pFieldname);
- f.pGroupname = NULL;
- if(in_pFieldDocs)
- f.pFieldDocs = StringTable->insert(in_pFieldDocs);
- else
- f.pFieldDocs = NULL;
- f.type = in_fieldType;
- f.offset = in_fieldOffset;
- f.elementCount = in_elementCount;
- f.table = in_table;
- f.validator = NULL;
- f.setDataFn = in_setDataFn;
- f.getDataFn = in_getDataFn;
- f.writeDataFn = in_writeDataFn;
- sg_tempFieldList.push_back(f);
- }
- void ConsoleObject::addFieldV(const char* in_pFieldname,
- const U32 in_fieldType,
- const dsize_t in_fieldOffset,
- ConsoleTypeValidator *v,
- const char* in_pFieldDocs)
- {
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(in_pFieldname);
- f.pGroupname = NULL;
- if(in_pFieldDocs)
- f.pFieldDocs = StringTable->insert(in_pFieldDocs);
- else
- f.pFieldDocs = NULL;
- f.type = in_fieldType;
- f.offset = in_fieldOffset;
- f.elementCount = 1;
- f.table = NULL;
- f.setDataFn = &defaultProtectedSetFn;
- f.getDataFn = &defaultProtectedGetFn;
- f.writeDataFn = &defaultProtectedWriteFn;
- f.validator = v;
- v->fieldIndex = sg_tempFieldList.size();
- sg_tempFieldList.push_back(f);
- }
- void ConsoleObject::addDepricatedField(const char *fieldName)
- {
- AbstractClassRep::Field f;
- f.pFieldname = StringTable->insert(fieldName);
- f.pGroupname = NULL;
- f.pFieldDocs = NULL;
- f.type = AbstractClassRep::DepricatedFieldType;
- f.offset = 0;
- f.elementCount = 0;
- f.table = NULL;
- f.validator = NULL;
- f.setDataFn = &defaultProtectedSetFn;
- f.getDataFn = &defaultProtectedGetFn;
- f.writeDataFn = &defaultProtectedWriteFn;
- sg_tempFieldList.push_back(f);
- }
- bool ConsoleObject::removeField(const char* in_pFieldname)
- {
- for (U32 i = 0; i < (U32)sg_tempFieldList.size(); i++) {
- if (dStricmp(in_pFieldname, sg_tempFieldList[i].pFieldname) == 0) {
- sg_tempFieldList.erase(i);
- return true;
- }
- }
- return false;
- }
- //--------------------------------------
- void ConsoleObject::initPersistFields()
- {
- }
- //--------------------------------------
- void ConsoleObject::consoleInit()
- {
- }
- ConsoleObject::~ConsoleObject()
- {
- }
- //--------------------------------------
- AbstractClassRep* ConsoleObject::getClassRep() const
- {
- return NULL;
- }
|