EDIT 2: Update complete, have fun
![Smile :)](./images/smilies/icon_smile.gif)
EDIT 3: Cache system finished but as it seems it's 8x slower than this but if some one want's to play with it here is code http://www.megaupload.com/?d=KPGVDF4V
I have update code with D_Ini_CommentChar
Hi this is slightly modified version from my game that is currently being developed. This is for anyone that wants to parse ini files from archive.
It's simple and efficient. Of course if anyone have suggestion to make this class better I will gladly hear it.
IrrIni.h
Code: Select all
/*
Note 1: config file can be in this format:
[Section]
key value
There is not need for '=' or any other sign since end of key is
checked for non alphabet and non numeric character.
Note 2: char '[' and ']' should not be used anywhere except for defining
section names in config file.
Note 3: getKeyValue will read whole key row until reach end of row or until finds D_Ini_CommentChar
*/
#pragma once
#include <irrlicht.h>
#pragma comment(lib, "Irrlicht.lib")
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// default value for getKeyValue that will be returned
#define D_Ini_DefaultValue L""
// default value for getKeyValueBool that will be returned
#define D_Ini_BoolDefaultValue false
// default value for getKeyValueInt that will be returned
#define D_Ini_IntDefaultValue 0
// char that will be used for commenting in config file
#define D_Ini_CommentChar '#'
class CIrrIni
{
public:
CIrrIni(void);
~CIrrIni(void);
void setIniFileName(IReadFile* file);
int getKeyValueInt(stringw strKey, stringw strSection);
void getKeyValue(const stringw strKey, stringw strSection, stringw& result);
bool getKeyValueBool(stringw strKey, stringw strSection);
private:
bool isCharAlpha(wchar_t wchar);
bool isCharAlphaNumeric(wchar_t wchar);
IReadFile* iniFile;
int bufferSize;
stringw buff;
struct SSectionsInfo
{
int numOfSections;
map<stringw, int> sectionsInfo; // param 1 section name, param 2 section start
};
SSectionsInfo sectionsInfo;
};
Code: Select all
#include "IrrIni.h"
CIrrIni::CIrrIni(void)
{
}
CIrrIni::~CIrrIni(void)
{
}
void CIrrIni::setIniFileName(IReadFile* file)
{
int start = 0;
int end = 0;
iniFile = file;
bufferSize = iniFile->getSize();
char* wbuff = new char[bufferSize];
iniFile->read(wbuff, bufferSize);
buff = L"";
buff.append(stringw(wbuff), stringw(wbuff).size());
delete [] wbuff;
sectionsInfo.numOfSections = 0;
sectionsInfo.sectionsInfo.clear();
start = buff.findFirst('[');
while(start != -1) // if we have found sections
{
end = buff.findNext(']', start);
if(end != -1)
{
sectionsInfo.sectionsInfo[buff.subString(start + 1, end - start - 1)] = end + 1;
++sectionsInfo.numOfSections;
start = buff.findNext('[', end);
}
}
}
int CIrrIni::getKeyValueInt(stringw strKey, stringw strSection)
{
stringw currentKey;
stringw result = stringw(D_Ini_IntDefaultValue);
int index = 0;
int buffPos = 0;
map<stringw, int>::Node* i = sectionsInfo.sectionsInfo.getRoot();
while (index != sectionsInfo.sectionsInfo.size())
{
buffPos = i->getValue();
int endOfSection;
if(sectionsInfo.sectionsInfo.size() > 1)
{
endOfSection = buffPos;
}
else
{
endOfSection = bufferSize;
}
if(i->getKey() == strSection) // if we found section
{
while(buffPos < endOfSection)
{
while(!isCharAlpha(buff[buffPos]))
{
if(buffPos >= endOfSection)
{
return D_Ini_IntDefaultValue;
}
++buffPos;
}
while(isCharAlpha(buff[buffPos]) || isCharAlphaNumeric(buff[buffPos]))
{
currentKey += buff[buffPos];
++buffPos;
}
if(currentKey == strKey) // if we found key
{
while(!isCharAlphaNumeric(buff[buffPos]))
{
++buffPos;
}
while(isCharAlphaNumeric(buff[buffPos]))
{
result += buff[buffPos];
++buffPos;
}
return _wtoi(result.c_str());
}
else
{
currentKey = "";
}
}
}
++index;
++i;
}
return _wtoi(result.c_str());
}
void CIrrIni::getKeyValue(const stringw strKey, stringw strSection, stringw& result)
{
stringw currentKey;
result = D_Ini_DefaultValue;
int index = 0;
int buffPos = 0;
map<stringw, int>::Node* i = sectionsInfo.sectionsInfo.getRoot();
while (index != sectionsInfo.sectionsInfo.size())
{
buffPos = i->getValue();
int endOfSection;
if(sectionsInfo.sectionsInfo.size() > 1)
{
endOfSection = buffPos;
}
else
{
endOfSection = bufferSize;
}
if(i->getKey() == strSection) // if we found section
{
while(buffPos < endOfSection)
{
while(!isCharAlpha(buff[buffPos]))
{
if(buffPos >= endOfSection)
{
return;
}
++buffPos;
}
while(isCharAlpha(buff[buffPos]))
{
currentKey += buff[buffPos];
++buffPos;
}
if(currentKey == strKey) // if we found key
{
while(!isCharAlpha(buff[buffPos]))
{
++buffPos;
}
while(buff[buffPos] != 10 && buff[buffPos] != 13 && buff[buffPos] != D_Ini_CommentChar && buff[buffPos] != 65533)
{
result += buff[buffPos];
++buffPos;
}
return;
}
else
{
currentKey = "";
}
}
}
++index;
++i;
}
}
bool CIrrIni::getKeyValueBool(stringw strKey, stringw strSection)
{
stringw currentKey;
stringw result = stringw(D_Ini_BoolDefaultValue);
int index = 0;
int buffPos = 0;
map<stringw, int>::Node* i = sectionsInfo.sectionsInfo.getRoot();
while (index != sectionsInfo.sectionsInfo.size())
{
buffPos = i->getValue();
int endOfSection;
if(sectionsInfo.sectionsInfo.size() > 1)
{
endOfSection = buffPos;
}
else
{
endOfSection = bufferSize;
}
if(i->getKey() == strSection) // if we found section
{
while(buffPos < endOfSection)
{
while(!isCharAlpha(buff[buffPos]))
{
if(buffPos >= endOfSection)
{
return D_Ini_BoolDefaultValue;
}
++buffPos;
}
while(isCharAlpha(buff[buffPos]))
{
currentKey += buff[buffPos];
++buffPos;
}
if(currentKey == strKey) // if we found key
{
while(!isCharAlphaNumeric(buff[buffPos]))
{
++buffPos;
}
while(isCharAlphaNumeric(buff[buffPos]))
{
result += buff[buffPos];
++buffPos;
}
return _wtoi(result.c_str());
}
else
{
currentKey = "";
}
}
}
++index;
++i;
}
if(result.equals_ignore_case(stringw(L"true")))
{
return true;
}
else if(result.equals_ignore_case(stringw(L"false")))
{
return false;
}
return _wtoi(result.c_str());
}
bool CIrrIni::isCharAlpha(wchar_t wchar)
{
return ((wchar >= 65 && wchar <= 90) || (wchar >= 97 && wchar <= 122));
}
bool CIrrIni::isCharAlphaNumeric(wchar_t wchar)
{
return (wchar >= 48 && wchar <= 57);
}
Code: Select all
#include "IrrIni.h"
int _tmain(int argc, _TCHAR* argv[])
{
stringw archivePath = L"My\path\to\the\archive";
stringw configFileExtension = L".ini";
IrrlichtDevice *device = createDevice(video::EDT_NULL);
if (!device)
{
return 1;
}
CIrrIni IrrIni;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
if(device->getFileSystem()->addFileArchive(archivePath) == false)
{
return 1;
}
IFileArchive* cardArchive = device->getFileSystem()->getFileArchive(0);
const IFileList* files = cardArchive->getFileList();
for(u32 i = 0; i < files->getFileCount(); ++i)
{
path file = files->getFileName(i);
file.make_lower();
// we here check if we got file with extension that we want
if(file.subString(file.size() - configFileExtension.size(), configFileExtension.size()) == configFileExtension)
{
IReadFile* iniFile = cardArchive->createAndOpenFile(i);
IrrIni.setIniFileName(iniFile);
stringw iniStringResult;
IrrIni.getKeyValue(L"Key1", L"Section", iniStringResult);
int iValue = IrrIni.getKeyValueInt(L"Key2", L"Section");
bool bValue = IrrIni.getKeyValueBool(L"Key3", L"Section");
iniFile->drop();
}
}
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
device->drop();
return 0;
}