/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Christian Meyer co-programmer: ... */ #include "ini_parser.h" #include "resource_manager.h" #include "debug.h" using namespace std; /** \brief constructs an IniParser using a file \param filename: the path and name of the file to parse */ IniParser::IniParser (const char* filename) { this->setClassID(CL_INI_PARSER, "IniParser"); stream = NULL; bInSection = false; this->openFile(filename); } /** \brief removes the IniParser from memory */ IniParser::~IniParser () { if( stream != NULL) fclose (stream); } /** \brief opens another file to parse \param filename: path and name of the new file to parse \return zero on success or -1 if an error occured; */ int IniParser::openFile(const char* filename) { char* tmpName = ResourceManager::homeDirCheck(filename); if( filename == NULL) return -1; if( stream != NULL) fclose (stream); if( (stream = fopen (tmpName, "r")) == NULL) { PRINTF(1)("IniParser could not open %s\n", filename); delete tmpName; return -1; } bInSection = false; delete tmpName; return 0; } /** \brief set the parsing cursor to the specified section \param section: the name of the section to set the cursor to \return zero on success or -1 if the section could not be found */ int IniParser::getSection( char* section) { bInSection = false; if( stream == NULL) return -1; char linebuffer[PARSELINELENGHT]; char secbuffer[PARSELINELENGHT]; char* ptr; rewind (stream); while( !feof( stream)) { // get next line fgets (linebuffer, PARSELINELENGHT, stream); // remove newline char if( (ptr = strchr( linebuffer, '\n')) != NULL) *ptr = 0; // check for section identifyer if( sscanf (linebuffer, "[%s", secbuffer) == 1) { if( (ptr = strchr( secbuffer, ']')) != NULL) { *ptr = 0; if( !strcmp( secbuffer, section)) { bInSection = true; return 0; } } } } return -1; } /** \brief gets the next VarName=VarValue pair from the parsing stream \param name: a pointer to a buffer to store the name of the entry \param value: a pointer to a buffer to store the value of the entry \return zero if the buffers have been filled with data or -1 if there are no entries left in the current section */ int IniParser::nextVar( char* name, char* value) { if( stream == NULL) { bInSection = false; return -1; } if( !bInSection) return -1; char linebuffer[PARSELINELENGHT]; char* ptr; while( !feof( stream)) { // get next line fgets (linebuffer, PARSELINELENGHT, stream); // remove newline char if( (ptr = strchr( linebuffer, '\n')) != NULL) *ptr = 0; if( linebuffer[0] == '[') { bInSection = false; return -1; } sscanf(linebuffer, "%s = %s", name, value); return 0; /* if( (ptr = strchr( tmpBuffer, '=')) != NULL) { if( ptr == linebuffer) continue; strcpy (value, &ptr[1]); strncpy (name, linebuffer, strlen (linebuffer) - strlen (value) - 1); printf ("%s, %s\n", value, name); return 0; } */ } return -1; } /** \brief directly acesses an entry in a section \param name: the name of the entry to find \param section: the section where the entry is to be found \param defvalue: what should be returned in case the entry cannot be found \return a pointer to a buffer conatining the value of the specified entry. This buffer will contain the data specified in defvalue in case the entry wasn't found The returned pointer points to an internal buffer, so do not free it on your own. Do not give a NULL pointer to defvalue, this will certainly lead to unwanted behaviour. */ char* IniParser::getVar(const char* name, char* section, char* defvalue = "") { strcpy (internbuf, defvalue); if( getSection (section) == -1) return internbuf; char namebuf[PARSELINELENGHT]; char valuebuf[PARSELINELENGHT]; while( nextVar (namebuf, valuebuf) != -1) { if( !strcmp (name, namebuf)) { strcpy (internbuf, valuebuf); return internbuf; } } return internbuf; }