I do already have a config file manager integrated into my projects (IrrOdeCar demo, Stunt Marble Racers), but it has some backdraws:
- uses plain IrrXML
- doesn't keep configuration information that is currently not used (e.g. all the rest when the initial graphics mode dialog pops up in Stunt Marble Racers)
Because of this I have decided to make a new configuration manager. This time I have used the (de)serialization methods that Irrlicht provides. Enough talking, here's the code:
IConfiguration.h
Code: Select all
#ifndef _I_CONFIGURATION
#define _I_CONFIGURATION
/**
* @class IConfiguration
* Implement this interface to have configurations saved and loaded
* @author Christian Keimel / bulletbyte.de
*/
class IConfiguration {
public:
virtual ~IConfiguration() { }
virtual void writeConfiguration(irr::io::IAttributes *pOut)=0; /**<! implement this method to write configuration */
virtual void readConfiguration(irr::io::IAttributes *pIn)=0; /**<! implement this method to read configuration */
/**
* This method returns the name of the configuration settings. Must be unique within a project (config file)
* @return name of the configuration part
*/
virtual irr::core::stringc getConfigName()=0;
};
#endif
Code: Select all
#ifndef _C_CONFIGURATION_MANAGER
#define _C_CONFIGURATION_MANAGER
#include <irrlicht.h>
class IConfiguration;
/**
* @class CConfigurationManager
* This is the managing class that takes care of loading and
* saving. Register your implementation instances of
* "IConfiguration" with the "addConfiguration" method
* @author Christian Keimel / bulletbyte.de
*/
class CConfigurationManager {
protected:
/**
* @class CAttributeWrap
* This class is just used to bind together the attributes
* and the configuration instance
* @author Christian Keimel / bulletbyte.de
*/
class CAttributeWrap {
public:
CAttributeWrap() {
m_pAttr=NULL;
m_pConf=NULL;
}
irr::core::stringc m_sName; /**<! the name */
irr::io::IAttributes *m_pAttr; /**<! the attributes */
IConfiguration *m_pConf; /**<! the configuration */
};
irr::IrrlichtDevice *m_pDevice;
irr::core::list<IConfiguration *> m_lConfigurations;
irr::core::list<CAttributeWrap *> m_lParts;
irr::core::stringc m_sFileName;
public:
/**
* Constructor
* @param sFileName the name of the configuration file
*/
CConfigurationManager(irr::core::stringc sFileName, irr::IrrlichtDevice *pDevice);
/**
* Destructor. Does save the settings to the
* specified file
*/
~CConfigurationManager();
/**
* load the settings from the specified file
* @return "true" if loading succeeded, "false" otherwise
*/
bool load();
/**
* save the settings to the specified file
* @return "true" if saving succeeded, "false" otherwise
*/
bool save();
/**
* Add a configuration to the list. Configurations can't be added more
* the once
* @param p configuration to add
*/
void addConfiguration(IConfiguration *p);
/**
* Remove a configuration from the list
* @param p configuration to remove
* @return "true" if the configuration was removed, "false" otherwise
*/
bool removeConfiguration(IConfiguration *p);
};
#endif
Code: Select all
#include <CConfigurationManager.h>
#include <IConfiguration.h>
/**
* Constructor
* @param sFileName the name of the configuration file
*/
CConfigurationManager::CConfigurationManager(irr::core::stringc sFileName, irr::IrrlichtDevice *pDevice) {
m_sFileName=sFileName;
m_pDevice=pDevice;
}
/**
* Destructor. Does save the settings to the
* specified file
*/
CConfigurationManager::~CConfigurationManager() {
save();
//clear the list of parts
while (m_lParts.getSize()>0) {
irr::core::list<CAttributeWrap *>::Iterator it=m_lParts.begin();
CAttributeWrap *p=*it;
m_lParts.erase(it);
delete p;
}
}
/**
* load the settings from the specified file
* @return "true" if loading succeeded, "false" otherwise
*/
bool CConfigurationManager::load() {
bool bRet=false;
irr::io::IReadFile *pRead=m_pDevice->getFileSystem()->createAndOpenFile(m_sFileName);
if (pRead) {
irr::io::IXMLReader *pReader=m_pDevice->getFileSystem()->createXMLReader(m_sFileName);
if (pReader) {
irr::core::stringc sNodeName;
while (pReader->read()) {
if (pReader->getNodeType()==irr::io::EXN_ELEMENT) {
if (irr::core::stringc("attributes")==pReader->getNodeName()) {
irr::io::IAttributes *pAttr=m_pDevice->getFileSystem()->createEmptyAttributes(m_pDevice->getVideoDriver());
bool bFound=false;
pAttr->read(pReader,true);
irr::core::list<CAttributeWrap *>::Iterator it;
for (it=m_lParts.begin(); it!=m_lParts.end(); it++) {
CAttributeWrap *w=*it;
if (w->m_sName==sNodeName) {
w->m_pAttr=pAttr;
w->m_pConf->readConfiguration(pAttr);
bFound=true;
}
}
if (!bFound) {
CAttributeWrap *w=new CAttributeWrap();
w->m_sName=sNodeName;
w->m_pAttr=pAttr;
m_lParts.push_back(w);
}
}
else sNodeName=pReader->getNodeName();
}
}
bRet=true;
}
else printf("Unable to create xml writer for file \"%s\"\n",m_sFileName.c_str());
}
else printf("Unable to open file \"%s\" for loading parameters\n",m_sFileName.c_str());
return bRet;
}
/**
* save the settings to the specified file
* @return "true" if saving succeeded, "false" otherwise
*/
bool CConfigurationManager::save() {
bool bRet=false;
irr::io::IWriteFile *pFile=m_pDevice->getFileSystem()->createAndWriteFile(m_sFileName);
if (pFile) {
irr::io::IXMLWriter *pWriter=m_pDevice->getFileSystem()->createXMLWriter(m_sFileName);
if (pWriter) {
pWriter->writeXMLHeader();
pWriter->writeElement(L"configuration");
pWriter->writeLineBreak();
irr::core::list<CAttributeWrap *>::Iterator it;
for (it=m_lParts.begin(); it!=m_lParts.end(); it++) {
CAttributeWrap *w=*it;
if (w->m_pAttr==NULL) w->m_pAttr=m_pDevice->getFileSystem()->createEmptyAttributes(m_pDevice->getVideoDriver());
if (w->m_pConf!=NULL) {
w->m_pAttr->clear();
w->m_pConf->writeConfiguration(w->m_pAttr);
}
pWriter->writeElement(irr::core::stringw(w->m_sName.c_str()).c_str());
pWriter->writeLineBreak();
w->m_pAttr->write(pWriter);
pWriter->writeClosingTag(irr::core::stringw(w->m_sName.c_str()).c_str());
pWriter->writeLineBreak();
}
pWriter->writeClosingTag(L"parameters");
pWriter->drop();
bRet=true;
}
else printf("Unable to create xml writer for file \"%s\"\n",m_sFileName.c_str());
pFile->drop();
}
else printf("Unable to open file \"%s\" for saving configuration",m_sFileName.c_str());
return bRet;
}
/**
* Add a configuration to the list. Configurations can't be added more
* the once
* @param p configuration to add
*/
void CConfigurationManager::addConfiguration(IConfiguration *p) {
//we only want one instance in the list one time. Exit method if it's already registered
irr::core::list<IConfiguration *>::Iterator it;
for (it=m_lConfigurations.begin(); it!=m_lConfigurations.end(); it++) if (*it==p) return;
CAttributeWrap *w=new CAttributeWrap();
w->m_sName=p->getConfigName();
w->m_pConf=p;
m_lParts.push_back(w);
m_lConfigurations.push_back(p);
}
/**
* Remove a configuration from the list
* @param p configuration to remove
* @return "true" if the configuration was removed, "false" otherwise
*/
bool CConfigurationManager::removeConfiguration(IConfiguration *p) {
irr::core::list<IConfiguration *>::Iterator it;
for (it=m_lConfigurations.begin(); it!=m_lConfigurations.end(); it++)
if (*it==p) {
m_lConfigurations.erase(it);
return true;;
}
return false;
}
Code: Select all
#include <stdio.h>
#include <irrlicht.h>
#include <CConfigurationManager.h>
#include <IConfiguration.h>
using namespace std;
class CTest1 : public IConfiguration {
public:
virtual void writeConfiguration(irr::io::IAttributes *pOut) {
pOut->addInt("value1",1);
pOut->addInt("value2",2);
pOut->addInt("value3",3);
pOut->addString("name","Test1");
}
virtual void readConfiguration(irr::io::IAttributes *pIn) {
printf("value: %i\n",pIn->getAttributeAsInt("value1"));
printf("value: %i\n",pIn->getAttributeAsInt("value2"));
printf("value: %i\n",pIn->getAttributeAsInt("value3"));
printf("name: %s\n",pIn->getAttributeAsString("name").c_str());
}
virtual irr::core::stringc getConfigName() {
return irr::core::stringc("TestConfig1");
}
};
class CTest2 : public IConfiguration {
public:
virtual void writeConfiguration(irr::io::IAttributes *pOut) {
pOut->addFloat("firstValue",5.23);
pOut->addString("myName","ConfigurationTest2");
}
virtual void readConfiguration(irr::io::IAttributes *pIn) {
printf("firstValue: %.2f\n",pIn->getAttributeAsFloat("firstValue"));
printf("myName: %s\n",pIn->getAttributeAsString("myName").c_str());
}
virtual irr::core::stringc getConfigName() {
return irr::core::stringc("TestConfig2");
}
};
class CTest3 : public IConfiguration {
public:
virtual void writeConfiguration(irr::io::IAttributes *pOut) {
pOut->addInt("AnInteger",23);
pOut->addString("AnotherName","ConfigurationTest3");
}
virtual void readConfiguration(irr::io::IAttributes *pIn) {
printf("AnInteger: %i\n",pIn->getAttributeAsInt("AnInteger"));
printf("AnotherName: %s\n",pIn->getAttributeAsString("AnotherName").c_str());
}
virtual irr::core::stringc getConfigName() {
return irr::core::stringc("TestConfig3");
}
};
int main() {
irr::IrrlichtDevice *pDevice=irr::createDevice(irr::video::EDT_NULL);
CConfigurationManager *p=new CConfigurationManager("test1.xml",pDevice);
CTest1 t1;
p->addConfiguration(&t1);
p->load();
p->save();
delete p;
CTest2 t2;
CTest3 t3;
printf("\t\t**** new configuration\n");
p=new CConfigurationManager("test1.xml",pDevice);
p->addConfiguration(&t2);
p->addConfiguration(&t3);
p->load();
p->save();
delete p;
return 0;
}
