// IniFile.h
#ifndef INIFILE_H
#define INIFILE_H
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#ifndef OWP_DONT_DEF_FALSE
#ifndef FALSE
#define FALSE 0
#endif
#endif
#ifndef OWP_DONT_DEF_TRUE
#ifndef TRUE
#define TRUE 1
#endif
#endif
#ifndef OWP_DONT_DEF_BOOL
#ifndef BOOL
#define BOOL unsigned int
#endif
#endif
#ifndef OWP_DONT_DEF_CCHR
#ifndef CCHR
#define CCHR const char
#endif
#endif
#ifndef OWP_DONT_DEF_UCHR
#ifndef UCHR
#define UCHR unsigned char
#endif
#endif
#ifndef OWP_DONT_DEF_UCCHR
#ifndef UCCHR
#define UCCHR const unsigned char
#endif
#endif
#ifndef OWP_DONT_DEF_UINT
#ifndef UINT
#define UINT unsigned int
#endif
#endif
#ifndef OWP_DONT_DEF_WORD
#ifndef WORD
#define WORD unsigned short
#endif
#endif
#ifdef LINUX /* Remove CR, on unix systems. */
#define INI_REMOVE_CR
#define DONT_HAVE_STRUPR
#endif
#define tpNULL 0
#define tpSECTION 1
#define tpKEYVALUE 2
#define tpCOMMENT 3
struct ENTRY
{
char Type;
char *pText;
struct ENTRY *pPrev;
struct ENTRY *pNext;
};
typedef struct
{
struct ENTRY *pSec;
struct ENTRY *pKey;
char KeyText [128];
char ValText [128];
char Comment [255];
} EFIND;
/* Macros */
#define ArePtrValid(Sec,Key,Val) ((Sec!=NULL)&&(Key!=NULL)&&(Val!=NULL))
class CIniFile
{
public:
CIniFile (void)
{
m_pEntry = NULL;
m_pCurEntry = NULL;
m_result [0] = 0;
m_pIniFile = NULL;
}
~CIniFile (void)
{
FreeAllMem ();
}
BOOL OpenIniFile (CCHR *pFileName)
{
char Str [255];
char *pStr;
struct ENTRY *pEntry;
FreeAllMem ();
if (pFileName == NULL) { return FALSE; }
if ((m_pIniFile = fopen (pFileName, "r")) == NULL) { return FALSE; }
while (fgets (Str, 255, m_pIniFile) != NULL) {
pStr = strchr (Str, '\n');
if (pStr != NULL) { *pStr = 0; }
pEntry = MakeNewEntry ();
if (pEntry == NULL) { return FALSE; }
#ifdef INI_REMOVE_CR
Len = strlen(Str);
if ( Len > 0 ) {
if ( Str[Len-1] == '\r' ) {
Str[Len-1] = '\0';
}
}
#endif
pEntry->pText = (char *)malloc (strlen (Str)+1);
if (pEntry->pText == NULL) {
FreeAllMem ();
return FALSE;
}
strcpy (pEntry->pText, Str);
pStr = strchr (Str,';');
if (pStr != NULL) { *pStr = 0; } /* Cut all comments */
if ( (strstr (Str, "[") > 0) && (strstr (Str, "]") > 0) ) /* Is Section */ {
pEntry->Type = tpSECTION;
} else {
if (strstr (Str, "=") > 0) {
pEntry->Type = tpKEYVALUE;
} else {
pEntry->Type = tpCOMMENT;
}
}
m_pCurEntry = pEntry;
}
fclose (m_pIniFile);
m_pIniFile = NULL;
return TRUE;
}
void CloseIniFile ()
{
FreeAllMem ();
if (m_pIniFile != NULL) {
fclose (m_pIniFile);
m_pIniFile = NULL;
}
}
bool WriteIniFile (CCHR *pFileName)
{
struct ENTRY *pEntry = m_pEntry;
if (m_pIniFile != NULL) {
fclose (m_pIniFile);
}
if ((m_pIniFile = fopen (pFileName, "wb")) == NULL) {
FreeAllMem ();
return FALSE;
}
while (pEntry != NULL) {
if (pEntry->Type != tpNULL) {
#ifdef INI_REMOVE_CR
fprintf (m_pIniFile, "%s\n", pEntry->pText);
#else
fprintf (m_pIniFile, "%s\r\n", pEntry->pText);
#endif
}
pEntry = pEntry->pNext;
}
fclose (m_pIniFile);
m_pIniFile = NULL;
return TRUE;
}
bool DeleteKey (CCHR *pSection, CCHR *pKey)
{
EFIND List;
struct ENTRY *pPrev;
struct ENTRY *pNext;
if (FindKey (pSection, pKey, &List) == TRUE) {
pPrev = List.pKey->pPrev;
pNext = List.pKey->pNext;
if (pPrev) {
pPrev->pNext=pNext;
}
if (pNext) {
pNext->pPrev=pPrev;
}
FreeMem (List.pKey->pText);
FreeMem (List.pKey);
return TRUE;
}
return FALSE;
}
BOOL ReadBool (CCHR *pSection, CCHR *pKey, BOOL Default)
{
char Val [2] = {"0"};
if (Default != 0) { Val [0] = '1'; }
return (atoi (ReadString (pSection, pKey, Val))?1:0); /* Only allow 0 or 1 */
}
int ReadInt (CCHR *pSection, CCHR *pKey, int Default)
{
char Val [12];
sprintf (Val,"%d", Default);
return (atoi (ReadString (pSection, pKey, Val)));
}
double ReadDouble (CCHR *pSection, CCHR *pKey, double Default)
{
double Val;
sprintf (m_result, "%1.10lE", Default);
sscanf (ReadString (pSection, pKey, m_result), "%lE", &Val);
return Val;
}
CCHR *ReadString (CCHR *pSection, CCHR *pKey, CCHR *pDefault)
{
EFIND List;
if (ArePtrValid (pSection, pKey, pDefault) == FALSE) { return pDefault; }
if (FindKey (pSection, pKey, &List) == TRUE) {
strcpy (m_result, List.ValText);
return m_result;
}
return pDefault;
}
void WriteBool (CCHR *pSection, CCHR *pKey, bool Value)
{
char Val [2] = {'0',0};
if (Value != 0) { Val [0] = '1'; }
WriteString (pSection, pKey, Val);
}
void WriteInt (CCHR *pSection, CCHR *pKey, int Value)
{
char Val [12]; /* 32bit maximum + sign + \0 */
sprintf (Val, "%d", Value);
WriteString (pSection, pKey, Val);
}
void WriteDouble (CCHR *pSection, CCHR *pKey, double Value)
{
char Val [32]; /* DDDDDDDDDDDDDDD+E308\0 */
sprintf (Val, "%1.10lE", Value);
WriteString (pSection, pKey, Val);
}
void WriteString (CCHR *pSection, CCHR *pKey, CCHR *pValue)
{
EFIND List;
char Str [255];
if (ArePtrValid (pSection, pKey, pValue) == FALSE) { return; }
if (FindKey (pSection, pKey, &List) == TRUE) {
sprintf (Str, "%s=%s%s", List.KeyText, pValue, List.Comment);
FreeMem (List.pKey->pText);
List.pKey->pText = (char *)malloc (strlen (Str)+1);
strcpy (List.pKey->pText, Str);
} else {
if ((List.pSec != NULL) && (List.pKey == NULL)) /* section exist, Key not */ {
AddKey (List.pSec, pKey, pValue);
} else {
AddSectionAndKey (pSection, pKey, pValue);
}
}
}
protected:
struct ENTRY *m_pEntry;
struct ENTRY *m_pCurEntry;
char m_result [255];
FILE *m_pIniFile;
void AddKey (struct ENTRY *pEntry, CCHR *pKey, CCHR *pValue)
{
char Text [255];
sprintf (Text, "%s=%s", pKey, pValue);
AddItemAt (pEntry, tpKEYVALUE, Text);
}
BOOL AddItem (char Type, CCHR *pText)
{
struct ENTRY *pEntry = MakeNewEntry ();
if (pEntry == NULL) { return FALSE; }
pEntry->Type = Type;
pEntry->pText = (char*)malloc (strlen (pText) +1);
if (pEntry->pText == NULL) {
free (pEntry);
return FALSE;
}
strcpy (pEntry->pText, pText);
pEntry->pNext = NULL;
if (m_pCurEntry != NULL) { m_pCurEntry->pNext = pEntry; }
m_pCurEntry = pEntry;
return TRUE;
}
bool AddItemAt (struct ENTRY *pEntryAt, char Mode, CCHR *pText)
{
struct ENTRY *pNewEntry;
if (pEntryAt == NULL) { return FALSE; }
pNewEntry = (struct ENTRY*) malloc (sizeof (ENTRY));
if (pNewEntry == NULL) { return FALSE; }
pNewEntry->pText = (char *) malloc (strlen (pText)+1);
if (pNewEntry->pText == NULL) {
free (pNewEntry);
return FALSE;
}
strcpy (pNewEntry->pText, pText);
if (pEntryAt->pNext == NULL) /* No following nodes. */ {
pEntryAt->pNext = pNewEntry;
pNewEntry->pNext = NULL;
} else {
pNewEntry->pNext = pEntryAt->pNext;
pEntryAt->pNext = pNewEntry;
}
pNewEntry->pPrev = pEntryAt;
pNewEntry->Type = Mode;
return TRUE;
}
void FreeMem (void *pPtr)
{
if (pPtr != NULL) { free (pPtr); }
}
void FreeAllMem (void)
{
struct ENTRY *pEntry;
struct ENTRY *pNextEntry;
pEntry = m_pEntry;
while (1) {
if (pEntry == NULL) { break; }
pNextEntry = pEntry->pNext;
FreeMem (pEntry->pText); /* Frees the pointer if not NULL */
FreeMem (pEntry);
pEntry = pNextEntry;
}
m_pEntry = NULL;
m_pCurEntry = NULL;
}
bool FindKey (CCHR *pSection, CCHR *pKey, EFIND *pList)
{
char Search [130];
char Found [130];
char Text [255];
char *pText;
struct ENTRY *pEntry;
pList->pSec = NULL;
pList->pKey = NULL;
pEntry = FindSection (pSection);
if (pEntry == NULL) { return FALSE; }
pList->pSec = pEntry;
pList->KeyText[0] = 0;
pList->ValText[0] = 0;
pList->Comment[0] = 0;
pEntry = pEntry->pNext;
if (pEntry == NULL) { return FALSE; }
sprintf (Search, "%s",pKey);
strupr (Search);
while (pEntry != NULL) {
if ((pEntry->Type == tpSECTION) || /* Stop after next section or EOF */
(pEntry->Type == tpNULL )) {
return FALSE;
}
if (pEntry->Type == tpKEYVALUE) {
strcpy (Text, pEntry->pText);
pText = strchr (Text, ';');
if (pText != NULL) {
strcpy (pList->Comment, pText);
*pText = 0;
}
pText = strchr (Text, '=');
if (pText != NULL) {
*pText = 0;
strcpy (pList->KeyText, Text);
strcpy (Found, Text);
*pText = '=';
strupr (Found);
/* printf ("%s,%s\n", Search, Found); */
if (strcmp (Found,Search) == 0) {
strcpy (pList->ValText, pText+1);
pList->pKey = pEntry;
return TRUE;
}
}
}
pEntry = pEntry->pNext;
}
return NULL;
}
bool AddSectionAndKey (CCHR *pSection, CCHR *pKey, CCHR *pValue)
{
char Text [255];
sprintf (Text, "[%s]", pSection);
if (AddItem (tpSECTION, Text) == FALSE) { return FALSE; }
sprintf (Text, "%s=%s", pKey, pValue);
return AddItem (tpKEYVALUE, Text)? 1 : 0;
}
struct ENTRY *MakeNewEntry (void)
{
struct ENTRY *pEntry;
pEntry = (struct ENTRY *)malloc (sizeof (ENTRY));
if (pEntry == NULL) {
FreeAllMem ();
return NULL;
}
if (m_pEntry == NULL) {
m_pEntry = pEntry;
}
pEntry->Type = tpNULL;
pEntry->pPrev = m_pCurEntry;
pEntry->pNext = NULL;
pEntry->pText = NULL;
if (m_pCurEntry != NULL) {
m_pCurEntry->pNext = pEntry;
}
return pEntry;
}
struct ENTRY *FindSection (CCHR *pSection)
{
char Sec [130];
char iSec [130];
struct ENTRY *pEntry;
sprintf (Sec, "[%s]", pSection);
strupr (Sec);
pEntry = m_pEntry; /* Get a pointer to the first Entry */
while (pEntry != NULL) {
if (pEntry->Type == tpSECTION) {
strcpy (iSec, pEntry->pText);
strupr (iSec);
if (strcmp (Sec, iSec) == 0) {
return pEntry;
}
}
pEntry = pEntry->pNext;
}
return NULL;
}
#ifdef DONT_HAVE_STRUPR
/* DONT_HAVE_STRUPR is set when INI_REMOVE_CR is defined */
void strupr( char *str )
{
// We dont check the ptr because the original also dont do it.
while (*str != 0) {
if ( islower( *str ) ) {
*str = toupper( *str );
}
str++;
}
}
#endif
private:
};
#endif
#ifdef INIFILE_TEST_THIS_FILE
int main (void)
{
CIniFile iFile;
printf ("Hello World\n");
iFile.OpenIniFile ("Test.Ini");
iFile.WriteString ("Test", "Name", "Value");
iFile.WriteString ("Test", "Name", "OverWrittenValue");
iFile.WriteString ("Test", "Port", "COM1");
iFile.WriteString ("Test", "User", "James Brown jr.");
iFile.WriteString ("Configuration", "eDriver", "MBM2.VXD");
iFile.WriteString ("Configuration", "Wrap", "LPT.VXD");
iFile.WriteInt ("IO-Port", "Com", 2);
iFile.WriteBool ("IO-Port", "IsValid", 0);
iFile.WriteDouble ("TheMoney", "TheMoney", 67892.00241);
iFile.WriteInt ("Test" , "ToDelete", 1234);
iFile.WriteIniFile ("Test.Ini");
printf ("Key ToDelete created. Check ini file. Any key to continue");
while (!kbhit());
iFile.OpenIniFile ("Test.Ini");
iFile.DeleteKey ("Test" , "ToDelete");
iFile.WriteIniFile ("Test.Ini");
printf ("[Test] Name = %s\n", iFile.ReadString ("Test", "Name", "NotFound"));
printf ("[Test] Port = %s\n", iFile.ReadString ("Test", "Port", "NotFound"));
printf ("[Test] User = %s\n", iFile.ReadString ("Test", "User", "NotFound"));
printf ("[Configuration] eDriver = %s\n", iFile.ReadString ("Configuration", "eDriver", "NotFound"));
printf ("[Configuration] Wrap = %s\n", iFile.ReadString ("Configuration", "Wrap", "NotFound"));
printf ("[IO-Port] Com = %d\n", iFile.ReadInt ("IO-Port", "Com", 0));
printf ("[IO-Port] IsValid = %d\n", iFile.ReadBool ("IO-Port", "IsValid", 0));
printf ("[TheMoney] TheMoney = %1.10lf\n", iFile.ReadDouble ("TheMoney", "TheMoney", 111));
iFile.CloseIniFile ();
return 0;
}
#endif