Index: orxonox/trunk/src/lib/util/ini_parser.cc
===================================================================
--- orxonox/trunk/src/lib/util/ini_parser.cc	(revision 5011)
+++ orxonox/trunk/src/lib/util/ini_parser.cc	(revision 5014)
@@ -10,10 +10,17 @@
 
    ### File Specific:
-   main-programmer: Christian Meyer
-   co-programmer: ...
+   main-programmer: Benjamin Grauer
+   co-programmer: Christian Meyer
+
+   2005-08-14: complete reimplementation:
+               now the File is parsed at the initialisation,
+               and informations is gathered there.
 */
 
 
 #include "ini_parser.h"
+
+#include "list.h"
+#include "stdlibincl.h"
 
 #include "resource_manager.h"
@@ -26,11 +33,14 @@
  * @param filename: the path and name of the file to parse
 */
-IniParser::IniParser (const char* filename)
+IniParser::IniParser (const char* fileName)
 {
   this->setClassID(CL_INI_PARSER, "IniParser");
-
-  stream = NULL;
-  bInSection = false;
-  this->openFile(filename);
+  this->setName(fileName);
+
+  this->currentEntry = NULL;
+  this->currentSection = NULL;
+  this->sections = NULL;
+  if (fileName != NULL)
+    this->openFile(fileName);
 }
 
@@ -40,116 +50,203 @@
 IniParser::~IniParser ()
 {
-  if( stream != NULL) fclose (stream);
-}
-
-/**
- *  opens another file to parse
+  deleteSections();
+}
+
+void IniParser::deleteSections()
+{
+  if (this->sections)
+  {
+    tIterator<IniSection>* sectionIt = this->sections->getIterator();
+    IniSection* sectionEnum = sectionIt->nextElement();
+    while (sectionEnum)
+    {
+      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
+      IniEntry* entryEnum = entryIt->nextElement();
+      while (entryEnum)
+      {
+        delete []entryEnum->name;
+        delete []entryEnum->value;
+        delete entryEnum;
+        entryEnum = entryIt->nextElement();
+      }
+      delete entryIt;
+
+      delete []sectionEnum->name;
+      delete sectionEnum->entries;
+      delete sectionEnum;
+      sectionEnum = sectionIt->nextElement();
+    }
+    delete sectionIt;
+  }
+  delete this->sections;
+  this->sections = NULL;
+}
+
+/**
+ * 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)
-{
+ * @return true on success false otherwise;
+*/
+bool IniParser::openFile(const char* filename)
+{
+  FILE*    stream;           //!< The stream we use to read the file.
+
+
+  if( filename == NULL)
+    return false;
   char* tmpName = ResourceManager::homeDirCheck(filename);
-  if( filename == NULL) return -1;
-  if( stream != NULL)   fclose (stream);
+
+  if (sections != NULL)
+    deleteSections();
+
   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;
+  {
+    PRINTF(1)("IniParser could not open %s\n", filename);
+    delete tmpName;
+    return false;
+  }
+  else
+  {
+    this->currentEntry = NULL;
+    this->currentSection = NULL;
+    this->sections = new tList<IniSection>;
+
+    /////////////////////////////
+    // READING IN THE INI-FILE //
+    /////////////////////////////
+    char lineBuffer[PARSELINELENGHT];
+    char buffer[PARSELINELENGHT];
+    char* ptr;
+
+    rewind (stream);
+    while( !feof( stream))
+    {
+      // get next line
+      fgets (lineBuffer, PARSELINELENGHT, stream);
+      // remove newline char, and \0-terminate
+      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
+        *ptr = 0;
+      // check for section identifyer
+      if( sscanf (lineBuffer, "[%s", buffer) == 1)
+      {
+        if( (ptr = strchr( buffer, ']')) != NULL)
+        {
+          *ptr = 0;
+          IniSection* newSection = new IniSection;
+          newSection->name = new char[strlen(buffer)+1];
+          strcpy(newSection->name, buffer);
+          newSection->entries = new tList<IniEntry>;
+          this->sections->add(newSection);
+          this->currentSection = newSection;
+        }
+      }
+      else if( (ptr = strchr( lineBuffer, '=')) != NULL)
+      {
+        if (currentSection == NULL)
+        {
+          PRINTF(2)("Not in a Section yet for %s\n", lineBuffer);
+          continue;
+        }
+        if( ptr == lineBuffer)
+          continue;
+        IniEntry* newEntry = new IniEntry;
+
+        char* valueBegin = ptr+1;
+        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBuffer + strlen(lineBuffer))
+          ++valueBegin;
+        newEntry->value = new char[strlen(valueBegin)+1];
+        strcpy(newEntry->value, valueBegin);
+        char* nameEnd = ptr-1, *nameBegin = lineBuffer;
+        while ((*nameBegin == ' ' || *nameBegin == '\t') && nameBegin < ptr)
+          ++nameBegin;
+        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= nameBegin)
+          --nameEnd;
+        nameEnd[1] = '\0';
+        newEntry->name = new char[strlen (nameBegin)];
+        strcpy(newEntry->name, nameBegin);
+
+        this->currentSection->entries->add(newEntry);
+      }
+
+    }
+  }
+  fclose(stream);
+  return true;
 }
 
 /**
  *  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( const 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;
+ * @param sectionName: the name of the section to set the cursor to
+ * @return true on success or false if the section could not be found
+*/
+bool IniParser::getSection( const char* sectionName)
+{
+  tIterator<IniSection>* sectionIt = this->sections->getIterator();
+  IniSection* sectionEnum = sectionIt->nextElement();
+  while (sectionEnum)
+  {
+    if (!strcmp(sectionEnum->name, sectionName))
+    {
+      this->currentSection = sectionEnum;
+      delete sectionIt;
+      return true;
+    }
+
+    sectionEnum = sectionIt->nextElement();
+  }
+  delete sectionIt;
+  return false;
+}
+
+/**
+ * searches the next section
+ * @returns the name of the section if found, NULL otherwise
+ */
+const char* IniParser::nextSection()
+{
+  if (this->currentSection == NULL)
+    return NULL;
+  else
+  {
+    if (this->sections)
+      this->currentSection = sections->nextElement(this->currentSection);
+  }
+  if (this->currentSection != NULL)
+    return this->currentSection->name;
+  else
+    return NULL;
 }
 
 /**
  *  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( const char* name, const 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;
+ * @param name: a pointer to the Name of the next Var
+ * @param value: a pointer to the Value of the next Var
+ * @return true on success, false otherwise (in the latter case name and value will be NULL)
+ */
+bool IniParser::nextVar()
+{
+  if (this->currentSection == NULL)
+    return false;
+  if(this->currentEntry == this->currentSection->entries->lastElement())
+  {
+    this->currentEntry = NULL;
+    return false;
+  }
+  if (this->currentEntry == NULL)
+    this->currentEntry = this->currentSection->entries->firstElement();
+  else
+    this->currentEntry = this->currentSection->entries->nextElement(this->currentEntry);
+
+  if (this->currentEntry == NULL)
+    return false;
+  else
+    return true;
 }
 
 /**
  *  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
+ * @param entryName: the name of the entry to find
+ * @param sectionName: the section where the entry is to be found
+ * @param defaultValue: 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
 
@@ -157,20 +254,68 @@
    lead to unwanted behaviour.
 */
-const char* IniParser::getVar(const char* name, const char* section, const 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))
+const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
+{
+  if (this->sections)
+  {
+    tIterator<IniSection>* sectionIt = this->sections->getIterator();
+    IniSection* sectionEnum = sectionIt->nextElement();
+    while (sectionEnum)
+    {
+      if (!strcmp(sectionEnum->name, sectionName))
+      {
+        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
+        IniEntry* entryEnum = entryIt->nextElement();
+        while (entryEnum)
         {
-          strcpy (internbuf, valuebuf);
-          return internbuf;
+          if (!strcmp(entryEnum->name, entryName))
+          {
+            delete entryIt;
+            delete sectionIt;
+            return entryEnum->value;
+          }
+          entryEnum = entryIt->nextElement();
         }
-    }
-  return internbuf;
-}
+         delete entryIt;
+         PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
+         break;
+      }
+      sectionEnum = sectionIt->nextElement();
+    }
+    delete sectionIt;
+    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
+  }
+  else
+    PRINTF(1)("%s not opened\n", this->getName());
+
+  return defaultValue;
+
+}
+
+void IniParser::debug() const
+{
+  PRINTF(0)("Iniparser %s - debug\n", this->getName());
+  if (this->sections)
+  {
+    tIterator<IniSection>* sectionIt = this->sections->getIterator();
+    IniSection* sectionEnum = sectionIt->nextElement();
+    while (sectionEnum)
+    {
+      PRINTF(0)(" [%s]\n", sectionEnum->name);
+
+      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
+      IniEntry* entryEnum = entryIt->nextElement();
+      while (entryEnum)
+      {
+        PRINTF(0)("   :%s: -> '%s'\n", entryEnum->name, entryEnum->value);
+
+        entryEnum = entryIt->nextElement();
+      }
+      delete entryIt;
+
+      sectionEnum = sectionIt->nextElement();
+    }
+    delete sectionIt;
+  }
+  else
+    PRINTF(1)("%s not opened\n", this->getName());
+}
Index: orxonox/trunk/src/lib/util/ini_parser.h
===================================================================
--- orxonox/trunk/src/lib/util/ini_parser.h	(revision 5011)
+++ orxonox/trunk/src/lib/util/ini_parser.h	(revision 5014)
@@ -1,40 +1,66 @@
 /*!
-    \file ini_parser.h
-  *  A small ini file parser
-
-    Can be used to find a defined [Section] in an ini file and get the VarName=Value entries
-*/
+ * @file ini_parser.h
+ * A small ini file parser
+ *
+ * Can be used to find a defined [Section] in an ini file and get the VarName = Value entries
+ */
 
 #ifndef _INI_PARSER_H
 #define _INI_PARSER_H
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
+#define PARSELINELENGHT     512       //!< how many chars to read at once
+
 #include "base_object.h"
 
-#define PARSELINELENGHT     512       //!< how many chars to read at once
+// FORWARD DEFINITION //
+template<class T> class tList;
 
 //! ini-file parser
 /**
-        This class can be used to load an initializer file and parse it's contents for variablename=value pairs.
-*/
+ * This class can be used to load an initializer file and parse it's contents for variablename=value pairs.
+ */
 class IniParser : public BaseObject
 {
- public:
-  IniParser (const char* filename);
-  ~IniParser ();
+  private:
+    ////////////////////////////////////
+    struct IniEntry
+    {
+      char*              name;
+      char*              value;
+    };
 
-  const char* getVar(const char* name, const char* section, const char* defvalue);
-  int openFile(const char* name);
-  int getSection( const char* section);
-  int nextVar( const char* name, const char* value);
+    struct IniSection
+    {
+      char*               name;
+      tList<IniEntry>*    entries;
+    };
+    ////////////////////////////////////
 
- private:
-  FILE*         stream;                       //!< A FileStream to be loaded
-  bool          bInSection;                   //!< if the requested parameter is in the section.
-  char          internbuf[PARSELINELENGHT];   //!< a buffer
+  public:
+    IniParser (const char* filename = NULL);
+    ~IniParser ();
 
+    bool openFile(const char* name);
 
+    bool getSection( const char* sectionName);
+    const char* nextSection();
+
+    bool isOpen() const { return (sections != NULL)?true:false; };
+
+    const char* getVar(const char* entryName, const char* sectionName, const char* defaultValue = "") const;
+    bool nextVar();
+
+    const char* getCurrentName() const { return (currentEntry!=NULL)?currentEntry->name:NULL; };
+    const char* getCurrentValue() const { return (currentEntry!=NULL)?currentEntry->value:NULL; };
+
+    void debug() const;
+
+  private:
+    void deleteSections();
+
+  private:
+    tList<IniSection>*    sections;
+    IniSection*           currentSection;
+    IniEntry*             currentEntry;
 };
 
