Hello,
I used your libini. It was a great help.
I feel free to give you the update I did in order that I
could use it.
I hope you can make some time to eventually release it
on this site.
Note: around this c lib I created a wrapper class; just
tell me if you are interessed then I send you that source
as well.
ChangeLog:
Fixed:
Modified:
*libini.so is renamed to libgccini.so so -l option should be
changed to -lgccini
*Ini parser is case insensitive for headings and keys
- changed files:
- heading.i: __ini_locateHeading (ini_t *ini, const
char *heading)
- key.i: __ini_locateKey (ini_t *ini, const char
*key)
- ini.cpp: __ini_createCrc32 (const char *pBuf,
size_t length)
*ini_store starts writing with a space ' ' see also bugs
*ini_readInt returns zero only if succesful conversion is
done.
*ini_readDouble returns zero only if succesful conversion
is done.
*ini_readLong returns zero only if succesful conversion is
done.
*ini_readBool true has now synoniem yes, on; false has
no, off
*libini.spec.in: make it compactible with red hat 5.2 rpm
2.5.5
Added:
*support for exploring an ini file by indeces
- function int ini_locateKeyIndex(ini_fd_t fd, const int
key);
- function int ini_locateKeys (ini_fd_t fd);
- function int ini_locateHeadingIndex (ini_fd_t fd, const
int heading);
- funciton int ini_locateHeadings(ini_fd_t fd);
- function const char * INI_LINKAGE ini_currentKey
(ini_fd_t fd);
- function const char * INI_LINKAGE ini_currentHeading
(ini_fd_t fd);
*bugs:
- I didn't check support for SWIG translations... and
also no VB, VC check
- when an ini-file starts with "key=value" the 'k' is
disappeared (already in V1.9)
Logged In: YES
user_id=1103526
Attachement seems to be missing..
Logged In: YES
user_id=1103526
Attachment send by email at s_a_white@email.com
Logged In: YES
user_id=59929
Thankyou for the submission. Am curious as to the reasons
behind the library name change from -lini to -lgccini?
I'd be interested in having a look at the wrapper.
Compatibility interfaces for those found standard on a
particular platform are also welcome.
Logged In: YES
user_id=1103526
Hi Simon,
ok, the reason why I changed it is more due to my system.
I have to use 3rd party software and they have there own ini
parser lib which they call also libini.so (This one is buggy
when you open more then 2 files at a time). But I can't ask to
change it.
And thus to avoid undefined reference I renamed the library
to libgccini analog to libtclini. I'm sorry for this.
The wrapper is made and used on RH5.2 RH7.2 and RH7.3.
Pls see below the listing:
Regards,
Karel.
/* $Id: IniParser.h,v 1.1 2004/08/18 12:57:11 kva Exp $ */
#ifndef INIPARSER_H
#define INIPARSER_H
#include <stdarg.h>
#include <string>
typedef void *ini_fd_t;
class IniParser
{
public:
enum Mode {READ, NEW, EXISTS};
IniParser ();
IniParser (const char *fileName);
IniParser (const char *fileName, Mode mode, const char
*lineComment);
~IniParser ();
bool open ();
bool open (const char *fileName, ...);
bool open (const char *fileName, Mode mode);
bool open (const char *fileName, Mode mode, const char
*lineComment);
bool close ();
bool flush ();
bool remove ();
bool add (IniParser &iniParser);
bool update (IniParser &iniParser);
bool setLineComment (const char *lineComment);
bool setMode (Mode mode);
bool setFileName (const char *fileName, ...);
bool setValueDelimiter (const char *delimiters);
bool heading (const char *heading);
bool heading (const int index);
int nHeadings ();
const char *currentHeading ();
bool key (const char *key);
bool key (const int index);
int nKeys ();
const char *currentKey ();
bool value (const int index);
int nValues ();
bool readString (std::string &value);
bool readDouble (double &value);
bool readFloat (float &value);
bool readLong (long &value);
bool readInt (int &value);
bool readShort (short &value);
bool readBool (int &value);
bool writeString (const std::string &value);
bool writeDouble (const double &value);
bool writeFloat (const float value);
bool writeLong (const long value);
bool writeInt (const int value);
bool writeShort (const short value);
bool writeBool (const int value);
bool deleteHeading (const char *heading);
bool deleteHeading (const int index);
bool deleteKey (const char *key);
bool deleteKey (const int index);
void print ();
protected:
private:
ini_fd_t fd_;
std::string fileName_;
Mode mode_;
std::string lineComment_;
bool foundHeading_;
bool foundKey_;
};
#endif //INIPARSER_H
/* $Id: IniParser.cpp,v 1.1 2004/08/18 12:57:11 kva Exp $ */
#include <stdio.h>
#include <limits.h>
#include <float.h>
#include <mlxtestlib/utility/IniParser.h>
#include <libini.h>
IniParser::IniParser ()
{
foundHeading_ = false;
foundKey_ = false;
fd_ = NULL;
mode_ = READ;
lineComment_ = "#";
}
IniParser::IniParser (const char *fileName)
{
foundHeading_ = false;
foundKey_ = false;
fd_ = NULL;
mode_ = READ;
lineComment_ = "#";
open (fileName);
}
IniParser::IniParser (const char *fileName, Mode mode, const
char *lineComment)
{
foundHeading_ = false;
foundKey_ = false;
fd_ = NULL;
mode_ = READ;
lineComment_ = "#";
open (fileName, mode, lineComment);
}
IniParser::~IniParser ()
{
close ();
}
bool
IniParser::open ()
{
if (fileName_ == "") return false;
return open (fileName_.c_str (), mode_, lineComment_.c_str
());
}
bool
IniParser::open (const char *fileName, ...)
{
char buffer[512];
va_list ap;
va_start (ap, fileName);
vsnprintf (buffer, 512, fileName, ap);
buffer[511] = '\0';
va_end (ap);
return open (buffer, mode_, lineComment_.c_str ());
}
bool
IniParser::open (const char *fileName, Mode mode)
{
return open (fileName, mode, lineComment_.c_str ());
}
bool
IniParser::open (const char *fileName, Mode mode, const
char *lineComment)
{
setFileName (fileName);
setMode (mode);
setLineComment (lineComment);
char modeBuffer = 'w';
switch (mode_)
{
case NEW:
modeBuffer = 'w';
break;
case EXISTS:
modeBuffer = 'a';
break;
case READ:
modeBuffer = 'r';
break;
}
// a bug is in the libini --> the first key/value is not read!
unless the very first char is a ' '
// bug fix is done in this function
// now copy the file to a temp file starting with a ' ' and
read this one.
std::string tempName = tmpnam (NULL);
FILE *readFile = fopen (fileName_.c_str (), "r");
bool fileIsBugFree = false;
if (readFile == NULL)
{
foundHeading_ = false;
foundKey_ = false;
if (mode_ != NEW) return false;
fileIsBugFree = true;
}
if (!fileIsBugFree)
{
char firstChar = '\0';
fread (&firstChar, 1, 1, readFile);
switch (firstChar)
{
case '\n':
case '\r':
case ' ':
case '[':
case '\0':
fileIsBugFree = true;
break;
}
fclose (readFile);
}
if (fileIsBugFree)
{
tempName = fileName_;
}
if (!fileIsBugFree)
{
readFile = fopen (fileName_.c_str (), "r");
FILE *tempFile = fopen (tempName.c_str (), "w");
if ((tempFile == NULL) || (readFile == NULL))
{
foundHeading_ = false;
foundKey_ = false;
return false;
} else
{
// first write a ' '
fprintf (tempFile, " ");
// now copy the file
while (!feof (readFile))
{
char buffer[128];
int count = fread (buffer, 1, sizeof (buffer), readFile);
if (count > 0)
{
fwrite (buffer, 1, count, tempFile);
}
}
fclose (tempFile);
fclose (readFile);
// when we need to write the file back we should have
write access and thus we have the corrected file back
if (mode_ != READ)
{
readFile = fopen (fileName_.c_str (), "w");
tempFile = fopen (tempName.c_str (), "r");
if ((tempFile == NULL) || (readFile == NULL))
{
foundHeading_ = false;
foundKey_ = false;
return false;
} else
{
// now copy the file
while (!feof (tempFile))
{
char buffer[128];
int count = fread (buffer, 1, sizeof (buffer),
tempFile);
if (count > 0)
{
fwrite (buffer, 1, count, readFile);
}
}
fclose (tempFile);
fclose (readFile);
tempName = fileName_;
}
}
}
// end of bugfix
}
fd_ = ini_open (tempName.c_str (), &modeBuffer,
lineComment_.c_str ());
// fd_ = ini_open (fileName_.c_str (), &modeBuffer,
lineComment_.c_str ());
// remove temporary shit
if (tempName != fileName)
::remove (tempName.c_str ());
if (fd_)
{
heading (""); // default heading is ""
} else
{
foundHeading_ = false;
foundKey_ = false;
}
if (fd_)
if (fd_ == NULL) return false;
return true;
}
bool
IniParser::close ()
{
if (fd_) ini_close (fd_);
fd_ = NULL;
foundHeading_ = false;
foundKey_ = false;
return true;
}
bool
IniParser::flush ()
{
if (!fd_) return false;
int ret = ini_flush (fd_);
foundHeading_ = false;
foundKey_ = false;
return (ret >= 0);
}
bool
IniParser::remove ()
{
if (!fd_) return false;
int ret = ini_delete (fd_);
foundHeading_ = false;
foundKey_ = false;
return (ret >= 0);
}
bool
IniParser::add (IniParser &iniParser)
{
if (!fd_) return false;
int ret = ini_append (fd_, iniParser.fd_);
foundHeading_ = false;
foundKey_ = false;
return (ret >= 0);
}
bool
IniParser::update (IniParser &iniParser)
{
foundHeading_ = false;
foundKey_ = false;
return false; // todo : create implementaiton
}
bool
IniParser::setLineComment (const char *lineComment)
{
lineComment_ = lineComment;
return true;
}
bool
IniParser::setMode (Mode mode)
{
mode_ = mode;
return true;
}
bool
IniParser::setFileName (const char *fileName, ...)
{
char buffer[512];
va_list ap;
va_start (ap, fileName);
vsnprintf (buffer, 512, fileName, ap);
buffer[511] = '\0';
va_end (ap);
fileName_ = buffer;
return (strlen (buffer) < 512);
}
bool
IniParser::setValueDelimiter (const char *delimiters)
{
if (!fd_) return false;
int ret = ini_listDelims (fd_, delimiters);
return (ret >= 0);
}
bool
IniParser::heading (const char *heading)
{
if (!fd_) return false;
int ret = ini_locateHeading (fd_, heading);
if (ret >= 0)
{
foundHeading_ = true;
foundKey_ = false;
return true;
}
foundHeading_ = false;
foundKey_ = false;
return false;
}
bool
IniParser::heading (const int index)
{
if (!fd_) return false;
int ret = ini_locateHeadingIndex (fd_, index);
if (ret >= 0)
{
foundHeading_ = true;
foundKey_ = false;
return true;
}
foundHeading_ = false;
foundKey_ = false;
return false;
}
int
IniParser::nHeadings ()
{
if (!fd_) return -1;
return ini_locateHeadings (fd_);
}
const char *
IniParser::currentHeading ()
{
if (!fd_) return NULL;
if (!foundHeading_) return NULL;
return ini_currentHeading (fd_);
}
bool
IniParser::key (const char *key)
{
if (!fd_) return false;
int ret = ini_locateKey (fd_, key);
if (!foundHeading_) return false; // keep it here after locate -
-> for writing purposes
if (ret >= 0)
{
foundKey_ = true;
return true;
}
foundKey_ = false;
return false;
}
bool
IniParser::key (const int index)
{
if (!fd_) return false;
if (!foundHeading_) return false; // keep it here before
locate --> not possible to write to new heading by selection
of index!
int ret = ini_locateKeyIndex (fd_, index);
if (ret >= 0)
{
foundKey_ = true;
return true;
}
foundKey_ = false;
return false;
}
int
IniParser::nKeys ()
{
if (!fd_) return -1;
return ini_locateKeys (fd_);
}
const char *
IniParser::currentKey ()
{
if (!fd_) return NULL;
if (!foundHeading_) return NULL;
if (!foundKey_) return NULL;
return ini_currentKey (fd_);
}
bool
IniParser::value (const int index)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_listIndex (fd_, index);
return (ret >= 0);
}
int
IniParser::nValues ()
{
if (!fd_) return -1;
if (!foundKey_) return -1;
int ret = ini_listLength (fd_);
return ret;
}
bool
IniParser::readString (std::string &value)
{
value = "";
if (!fd_) return false;
if (!foundKey_) return false;
char *buffer;
int minSize = ini_dataLength (fd_);
buffer = new char[minSize+10];
int ret = ini_readString (fd_, buffer, minSize + 5);
if (ret >= 0) value = buffer;
delete[] buffer;
return (ret >= 0);
}
bool
IniParser::readDouble (double &value)
{
value = DBL_MAX;
if (!foundKey_) return false;
int ret = ini_readDouble (fd_, &value);
if (ret < 0) value = DBL_MAX;
return (ret >= 0);
}
bool
IniParser::readFloat (float &value)
{
value = FLT_MAX;
if (!foundKey_) return false;
double doubleValue;
int ret = ini_readDouble (fd_, &doubleValue);
if (ret >= 0) value = doubleValue;
return (ret >= 0);
}
bool
IniParser::readLong (long &value)
{
value = LONG_MAX;
if (!foundKey_) return false;
int ret = ini_readLong (fd_, &value);
if (ret < 0) value = LONG_MAX;
return (ret >= 0);
}
bool
IniParser::readInt (int &value)
{
value = INT_MAX;
if (!foundKey_) return false;
int ret = ini_readInt (fd_, &value);
printf ("ret = %d %d\n", ret, value);
if (ret < 0) value = INT_MAX;
return (ret >= 0);
}
bool
IniParser::readShort (short &value)
{
value = SHRT_MAX;
if (!foundKey_) return false;
int intValue;
int ret = ini_readInt (fd_, &intValue);
if (ret >= 0) value = (short)intValue;
return (ret >= 0);
}
bool
IniParser::readBool (int &value)
{
value = -1;
if (!foundKey_) return false;
int ret = ini_readBool (fd_, &value);
if (ret < 0) value = -1;
return (ret >= 0);
}
bool
IniParser::writeString (const std::string &value)
{
if (!fd_) return false;
//if (!foundKey_) return false;
int ret = ini_writeString (fd_, value.c_str ());
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeDouble (const double &value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeDouble (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeFloat (const float value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeDouble (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeLong (const long value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeLong (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeInt (const int value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeLong (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeShort (const short value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeLong (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::writeBool (const int value)
{
if (!fd_) return false;
if (!foundKey_) return false;
int ret = ini_writeBool (fd_, value);
ini_flush (fd_);
return (ret >= 0);
}
bool
IniParser::deleteHeading (const char *heading)
{
if (!fd_) return false;
if (!this->heading (heading)) return false;
int ret = ini_deleteHeading (fd_);
if (ret >= 0)
{
foundHeading_ = false;
foundKey_ = false;
}
return (ret >= 0);
}
bool
IniParser::deleteHeading (const int index)
{
if (!fd_) return false;
if (!this->heading (index)) return false;
int ret = ini_deleteHeading (fd_);
if (ret >= 0)
{
foundHeading_ = false;
foundKey_ = false;
}
return (ret >= 0);
}
bool
IniParser::deleteKey (const char *key)
{
if (!fd_) return false;
if (!foundHeading_) return false;
if (!this->key (key)) return false;
int ret = ini_deleteKey (fd_);
if (ret >= 0)
{
foundKey_ = false;
}
return (ret >= 0);
}
bool
IniParser::deleteKey (const int index)
{
if (!fd_) return false;
if (!foundHeading_) return false;
if (!this->key (index)) return false;
int ret = ini_deleteKey (fd_);
if (ret >= 0)
{
foundKey_ = false;
}
return (ret >= 0);
}
void
IniParser::print ()
{
heading ("");
for (int k=0; k<nKeys (); k++)
{
key (k);
std::string value;
if (readString (value))
{
printf ("%s = %s\n", currentKey (), value.c_str ());
}
}
for (int h=0; h<nHeadings (); h++)
{
heading (h);
if (!strcmp (currentHeading (), "")) continue;
printf ("[%s]\n", currentHeading ());
for (int k=0; k<nKeys (); k++)
{
key (k);
std::string value;
readString (value);
printf (" %s = %s\n", currentKey (), value.c_str ());
}
}
}
#ifdef TEST_INI_PARSER
int main ()
{
IniParser ini ("ex.ini", IniParser::READ, "#");
// IniParser ini ("ex.ini");
// ini.setValueDelimiter (",.");
// if (ini.heading ("dir")) printf ("ok\n");
if (ini.key ("kVa")) printf ("ok\n");
std::string test;
if (ini.readString (test)) printf ("ok\n");
printf ("%s\n", test.c_str ());
if (ini.key ("bool")) printf ("okkey\n");
int testBool;
if (ini.readInt (testBool)) printf ("okread\n");
printf ("bool = %d\n", testBool);
ini.writeString ("write!!");
// if (ini.heading ("Home")) printf ("ok\n");
// if (ini.key ("tel")) printf ("ok\n");
if (ini.readString (test)) printf ("ok\n");
printf ("%s\n", test.c_str ());
if (ini.readString (test)) printf ("ok\n");
printf ("%s\n", test.c_str ());
if (ini.readString (test)) printf ("ok\n");
printf ("%s\n", test.c_str ());
if (ini.readString (test)) printf ("ok\n");
printf ("%s\n", test.c_str ());
printf ("headings %d\n", ini.nHeadings ());
for (int h=0; h < ini.nHeadings (); h++)
{
ini.heading (h);
printf ("[%s]\n", ini.currentHeading ());
for (int k=0; k < ini.nKeys (); k++)
{
ini.key (k);
std::string value;
ini.readString (value);
printf (" %s = %s \n", ini.currentKey (), value.c_str ());
}
}
return 0;
}
#endif
Logged In: YES
user_id=59929
Patches integrated:
*ini_readInt returns zero only if succesful conversion is
done.
*ini_readDouble returns zero only if succesful conversion
is done.
*ini_readLong returns zero only if succesful conversion is
done.
*ini_readBool true has now synoniem yes, on; false has
no, off
*libini.spec.in: make it compactible with red hat 5.2 rpm
2.5.5
Patches delayed (something should be available for 1.1.11):
*support for exploring an ini file by indeces
Patches redundent (other code fixed or alternatives put in
place):
*Ini parser is case insensitive for headings and keys
*ini_store starts writing with a space ' ' see also bugs
Patches not being applied:
*libini.so is renamed to libgccini.so so -l option should be
changed to -lgccini
A C++ interface on some form will be provided 1.1.11.
Logged In: YES
user_id=59929
The spec patch has caused an undesirable side effect that I
did not realise would occur. Is this spec file change
absolutely required for the older redhat or was it just away
for you to install the rpm in a different location than default?
Logged In: YES
user_id=59929
Believe I have found a fix for the spec issue. Please can
you test the new spec file as now works again for newer
versions of rpm?
CHANGE: Found a RedHat page on defining macros if they don't
exist, so now use:
%{!?_prefix: %define _prefix /usr}
etc. Hope RedHat 5.2 supports that.
Logged In: YES
user_id=59929
Re opened, something funny with pending. Please read
attached comments at the sourceforge page.