Wednesday, September 21, 2011

Read and parse ini file in C++


[1] A couple of tools to read and parse ini file.
[2]Stackoverflow Q&A for programmers.
[3] WiKi page on introduction of 'ini' file.
[4] SimpleIni library that support Window,WinCE, Linux


ini file is commonly used for configuration storage. So it can replace binary data you stored in EEPROM for configuration purpose once you system is supporting file system.



RUNNING SIMPLEINI ON LINUX TARGET BOARD
------------------------------------------

[q.yang@localhost Sample_023_SimpleIni_FileReader]$ cat Makefile
PROGRAM=testsi
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
INCL = -I $(LTIB_LINUX_KERNEL_PATH)/include

CC=g++
CFLAGS=-Wall
CPPFLAGS=-Wall

OBJS=testsi.o test1.o snippets.o ConvertUTF.o

help:
@echo This makefile is just for the test program \(use \"make clean all test\"\)
@echo Just include the SimpleIni.h header file to use it.

all: $(PROGRAM)

$(PROGRAM): $(OBJS)
$(CC) -o $(PROGRAM) $(OBJS)

./%.o:./%.cpp
$(CC) -c $(CFLAGS) $< -o $@ $(INCL)

clean:
rm -f core *.o $(PROGRAM)

data:
sed 's/\r\n$$/\n/g' < test1-expected.ini > unix.out
mv unix.out test1-expected.ini

test: testsi
./testsi -u -m -l test1-input.ini > test1-blah.ini
diff test1-output.ini test1-expected.ini

install:
@echo No install required. Just include the SimpleIni.h header file to use it.

testsi.o test1.o snippets.o : SimpleIni.h


SAMPLE CODE TO USE SIMPLEINI
-----------------------------------
Load *.ini file pointed by 'pszFile'


const TCHAR * pszFile;
bool bIsUtf8, bUseMultiKey, bUseMultiLine;

TestGateWayCfg(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine);

static bool TestGateWayCfg(const TCHAR *a_pszFile,bool a_bIsUtf8,bool a_bUseMultiKey,bool a_bUseMultiLine)
{
//----CSimpleIni GateWayCfgIni(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine)-------------------
//---------------GateWayCfgIni.LoadFile(a_pszFile)-------------------------------------------
// load the file
CSimpleIni GateWayCfgIni(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
_tprintf(_T("Loading file: %s\n"), a_pszFile);
SI_Error rc = GateWayCfgIni.LoadFile(a_pszFile);
if (rc < 0) {
printf("Failed to open file.\n");
return false;
}

//Read and print out values read from all keys
//All keys,values,comments will be buffered in instanse of 'GateWayCfgIni'.
_tprintf(_T("\n\n\n\n-----------scan and display all key and values-----------------\n"));
QuentinScanIniFile(GateWayCfgIni);
}



'GateWayCfgIni' stores a clone copy of all comments,sections,keys and values of *.ini file.

Analyze and display sections, keys, values in *.ini file.


static void QuentinScanIniFile(CSimpleIni &ini)
{
const TCHAR *pszSection = 0;
const TCHAR *pItem = 0;
const TCHAR *pszVal = 0;

//------GetValue-======-------------------------------------------
// get the value of the key "LogLevel" in section "ManufactureCfg"
bool bHasMulti;
pszVal = ini.GetValue(_T("ManufactureCfg"), _T("LogLevel"), 0, &bHasMulti);
_tprintf(_T("\n-- Value of ManufactureCfg::LogLevel is '%s' (hasMulti = %d)\n"),
pszVal ? pszVal : _T("(null)"), bHasMulti);

//------GetSectionSize-----------------------------------------------
// get the size of the section [ManufactureCfg]
_tprintf(_T("\n-- Number of keys in section [ManufactureCfg] = %d\n"),
ini.GetSectionSize(_T("ManufactureCfg")));

//------GetAllKeys------------------------------------------------
// get the list of all key names for the section "ManufactureCfg"
_tprintf(_T("\n-- Dumping keys of section: [ManufactureCfg]\n"));
CSimpleIni::TNamesDepend keys;

ini.GetAllKeys(_T("ManufactureCfg"), keys);
// dump all of the key names
CSimpleIni::TNamesDepend::const_iterator iKey = keys.begin();
for ( ; iKey != keys.end(); ++iKey ) {
pItem = iKey->pItem;
_tprintf(_T("Key: %s\n"), pItem);
}

//------GetAllSections------------------------
// iterate through every section in the file
_tprintf(_T("\n-- Dumping all sections\n"));
CSimpleIni::TNamesDepend sections;

ini.GetAllSections(sections);
CSimpleIni::TNamesDepend::const_iterator iSection = sections.begin();
for ( ; iSection != sections.end(); ++iSection ) {
pszSection = iSection->pItem;

// print the section name
printf("\n");
if (*pszSection) {
_tprintf(_T("[%s]\n"), pszSection);
}

// if there are keys and values...
const CSimpleIni::TKeyVal * pSectionData = ini.GetSection(pszSection);
if (pSectionData) {
//-------------------------------------------------------
// iterate over all keys and dump the key name and value
CSimpleIni::TKeyVal::const_iterator iKeyVal = pSectionData->begin();
for ( ;iKeyVal != pSectionData->end(); ++iKeyVal) {
pItem = iKeyVal->first.pItem;
pszVal = iKeyVal->second;
_tprintf(_T("%s=%s\n"), pItem, pszVal);
}
}
}
}

No comments: