Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/util/ini_parser.cc @ 5933

Last change on this file since 5933 was 5933, checked in by bensch, 19 years ago

orxonox/trunk: sync (not running)

File size: 11.1 KB
RevLine 
[4597]1/*
[2064]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
[5014]12   main-programmer: Benjamin Grauer
13   co-programmer: Christian Meyer
14
15   2005-08-14: complete reimplementation:
16               now the File is parsed at the initialisation,
17               and informations is gathered there.
[2064]18*/
19
20
21#include "ini_parser.h"
[4381]22
[5031]23#include <stdlib.h>
24#include <string.h>
[2064]25
[5933]26#ifdef DEBUG
27 #include "debug.h"
28#else
29 #define PRINTF(x) printf
30#endif
31
[2064]32using namespace std;
33
[2141]34/**
[4836]35 *  constructs an IniParser using a file
[5017]36 * @param fileName: the path and name of the file to parse
[5933]37 */
[5014]38IniParser::IniParser (const char* fileName)
[2064]39{
[5031]40  this->fileName = NULL;
[5933]41
[5014]42  if (fileName != NULL)
[5018]43    this->readFile(fileName);
[2064]44}
45
[5933]46
[2141]47/**
[4836]48 *  removes the IniParser from memory
[5933]49 */
[2064]50IniParser::~IniParser ()
51{
[5933]52  this->deleteSections();
[2064]53}
54
[5933]55
[5015]56/**
57 * removes all the sections. This is like delete, but even cooler :)
58 */
[5014]59void IniParser::deleteSections()
[2064]60{
[5933]61  while(!this->sections.empty())
[5014]62  {
[5933]63    IniSection section = this->sections.front();
64
65    while(!section.entries.empty())
[3231]66    {
[5933]67      IniEntry entry = section.entries.front();
68      delete []entry.name;
69      delete []entry.value;
70      section.entries.pop_front();
71    }
[5014]72
[5933]73    delete []section.name;
74    this->sections.pop_front();
[5014]75  }
[5933]76
77//  this->currentEntry = NULL;
78//  this->currentSection = NULL;
[5031]79  this->setFileName(NULL);
[2064]80}
81
[5933]82
[2141]83/**
[5014]84 * opens another file to parse
[5017]85 * @param fileName: path and name of the new file to parse
[5014]86 * @return true on success false otherwise;
[5933]87 */
[5018]88bool IniParser::readFile(const char* fileName)
[2064]89{
[5014]90  FILE*    stream;           //!< The stream we use to read the file.
[5933]91  if (!sections.empty())
[5014]92    deleteSections();
[5015]93  if( fileName == NULL)
94    return false;
[5031]95  this->setFileName(fileName);
[5014]96
[5015]97  if( (stream = fopen (fileName, "r")) == NULL)
[5014]98  {
[5015]99    PRINTF(1)("IniParser could not open %s\n", fileName);
[5014]100    return false;
101  }
102  else
103  {
[5933]104    this->currentEntry = 0;//this->sections.begin();
105    this->currentSection = this->sections.begin();
[5014]106
107    /////////////////////////////
108    // READING IN THE INI-FILE //
109    /////////////////////////////
110    char lineBuffer[PARSELINELENGHT];
111    char buffer[PARSELINELENGHT];
[5021]112    const char* lineBegin;
[5014]113    char* ptr;
114
[5319]115    while( fgets (lineBuffer, PARSELINELENGHT, stream))
[2551]116    {
[5021]117      lineBegin = lineBuffer;
[5014]118      // remove newline char, and \0-terminate
119      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
120        *ptr = 0;
[5021]121      // cut up to the beginning of the line.
122      while((*lineBegin == ' ' || *lineBegin == '\t') && lineBegin < lineBuffer + strlen(lineBuffer))
123        ++lineBegin;
124      if (strlen(lineBegin) <= 1 || *lineBegin == '#' || *lineBegin == ';')
125        continue;//printf("empty Line\n");
[2551]126      // check for section identifyer
[5021]127      else if( sscanf (lineBegin, "[%s", buffer) == 1)
[5014]128      {
129        if( (ptr = strchr( buffer, ']')) != NULL)
[4597]130        {
[5014]131          *ptr = 0;
[5020]132          this->addSection(buffer);
[4597]133        }
[5014]134      }
[5018]135      // check for Entry identifier (Entry = Value)
[5021]136      else if( (ptr = strchr( lineBegin, '=')) != NULL)
[5014]137      {
138        if (currentSection == NULL)
139        {
[5021]140          PRINTF(2)("Not in a Section yet for %s\n", lineBegin);
[5014]141          continue;
142        }
[5021]143        if( ptr == lineBegin)
[5014]144          continue;
145        char* valueBegin = ptr+1;
[5021]146        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBegin + strlen(lineBegin))
[5014]147          ++valueBegin;
[5022]148        char* valueEnd = valueBegin + strlen(valueBegin)-1;
149        while ((*valueEnd == ' ' || *valueEnd == '\t') && valueEnd >= valueBegin)
150          --valueEnd;
151        valueEnd[1] = '\0';
[5018]152        char* nameEnd = ptr-1;
[5021]153        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= lineBegin)
[5014]154          --nameEnd;
155        nameEnd[1] = '\0';
[5018]156
[5021]157        this->addVar(lineBegin, valueBegin);
[5014]158      }
[2551]159    }
[5014]160  }
161  fclose(stream);
162  return true;
[2064]163}
164
[5933]165
[2141]166/**
[5020]167 * opens a file and writes to it
168 * @param fileName: path and name of the new file to write to
169 * @return true on success false otherwise
170 */
171bool IniParser::writeFile(const char* fileName)
172{
173  FILE*    stream;           //!< The stream we use to read the file.
174  if( fileName == NULL)
175    return false;
176
177  if( (stream = fopen (fileName, "w")) == NULL)
178  {
179    PRINTF(1)("IniParser could not open %s\n", fileName);
180    return false;
181  }
182  else
183  {
[5933]184    if (!this->sections.empty())
[5020]185    {
[5933]186      std::list<IniSection>::iterator section;
187      for (section = this->sections.begin(); section != this->sections.end(); section++)
[5020]188      {
[5933]189        fprintf(stream, "\n [%s]\n", (*section).name);
[5020]190
[5933]191        std::list<IniEntry>::iterator entry;
192        for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
193          fprintf(stream, "   %s = %s\n", (*entry).name, (*entry).value);
[5020]194      }
195    }
196    else
197      PRINTF(1)("%s no sections defined yet\n", fileName);
198  }
199  fclose(stream);
200}
201
[5933]202
[5021]203/**
204 * adds a section to the list of Sections,
205 * if no Section list is availiable, it will create it
206 * @param sectionName the Name of the section to add
207 * @return true on success... there is only success or segfault :)
208 */
[5020]209bool IniParser::addSection(const char* sectionName)
210{
[5933]211  this->sections.push_back(IniSection());
[5020]212
[5933]213  this->sections.back().name = new char[strlen(sectionName)+1];
214  strcpy(this->sections.back().name, sectionName);
215
216  this->currentSection = --this->sections.end();
[5031]217  PRINTF(5)("Added Section %s\n", sectionName);
[5021]218  return true;
[5020]219}
220
[5933]221
[5020]222/**
[5014]223 *  set the parsing cursor to the specified section
224 * @param sectionName: the name of the section to set the cursor to
225 * @return true on success or false if the section could not be found
[2141]226*/
[5014]227bool IniParser::getSection( const char* sectionName)
[2064]228{
[5933]229  std::list<IniSection>::iterator section;
230  for (section = this->sections.begin(); section != this->sections.end(); section++)
[5014]231  {
[5933]232    if (!strcmp((*section).name, sectionName))
[3231]233    {
[5933]234      this->currentSection = section;
235      this->currentEntry = (*section).entries.begin();
[5014]236      return true;
[3231]237    }
[5014]238  }
239  return false;
240}
[4597]241
[5933]242
[5014]243/**
[5015]244 * moves to the first section
245 */
246void IniParser::getFirstSection()
247{
[5933]248  this->currentSection = this->sections.begin();
249  this->currentEntry = (*this->currentSection).entries.begin();
[5015]250}
251
[5933]252
[5015]253/**
[5014]254 * searches the next section
255 * @returns the name of the section if found, NULL otherwise
256 */
257const char* IniParser::nextSection()
258{
[5933]259  if (this->currentSection == this->sections.end())
[5014]260    return NULL;
261  else
262  {
[5933]263    if (this->currentSection == this->sections.end())
264      return NULL;
265    else
266      this->currentSection++;
[5014]267  }
[5015]268
[5014]269  if (this->currentSection != NULL)
270    return this->currentSection->name;
271  else
272    return NULL;
[2064]273}
274
[5933]275
[2141]276/**
[5015]277 * moves to the first Variable of the current Section
278 */
279void IniParser::getFirstVar()
280{
[5933]281  if (this->currentSection != this->sections.end())
282    this->currentEntry = (*this->currentSection).entries.begin();
283//  else
284//    this->currentEntry = NULL;
[5015]285}
286
[5933]287
[5015]288/**
[5014]289 *  gets the next VarName=VarValue pair from the parsing stream
290 * @return true on success, false otherwise (in the latter case name and value will be NULL)
291 */
292bool IniParser::nextVar()
293{
[5015]294  if (this->currentSection == NULL
295      || this->currentEntry == NULL
[5933]296      || this->currentEntry == (*this->currentSection).entries.end())
[5014]297  {
298    this->currentEntry = NULL;
299    return false;
300  }
[5933]301  this->currentEntry++;
[5014]302
303  if (this->currentEntry == NULL)
304    return false;
305  else
306    return true;
307}
308
[5933]309
[5014]310/**
[5020]311 * adds a new Entry to either the currentSection or the section called by sectionName
312 * @param entryName the Name of the Entry to add
313 * @param value the value to assign to this entry
314 * @param sectionName if NULL then this entry will be set to the currentSection
315 * otherwise to the section refered to by sectionName.
316 * If both are NULL no entry will be added
317 * @return true if everything is ok false on error
318 */
319bool IniParser::addVar(const char* entryName, const char* value, const char* sectionName)
320{
[5933]321  std::list<IniSection>::iterator section = this->sections.end();
322
[5020]323  if (sectionName != NULL)
324  {
[5933]325    for (section = this->sections.begin(); section != this->sections.end(); section++)
326      if (!strcmp((*section).name, sectionName))
[5020]327        break;
328  }
329  else
[5933]330    section = this->currentSection;
[5020]331
[5933]332  if (section == this->sections.end())
[5020]333  {
334    PRINTF(2)("section not found for value %s\n", entryName);
335    return false;
336  }
337  else
338  {
[5933]339    (*section).entries.push_back(IniEntry());
340    (*section).entries.back().name = new char[strlen (entryName)+1];
341    strcpy((*section).entries.back().name, entryName);
342    (*section).entries.back().value = new char[strlen(value)+1];
343    strcpy((*section).entries.back().value, value);
344    PRINTF(5)("Added Entry %s with Value '%s' to Section %s\n", entryName, value, (*section).name);
[5020]345    return true;
346  }
347}
348
[5933]349
[5020]350/**
[4836]351 *  directly acesses an entry in a section
[5014]352 * @param entryName: the name of the entry to find
353 * @param sectionName: the section where the entry is to be found
354 * @param defaultValue: what should be returned in case the entry cannot be found
[4836]355 * @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
[5020]356 *
357 *  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
358 * lead to unwanted behaviour.
[2141]359*/
[5014]360const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
[2065]361{
[5933]362  if (fileName != NULL)
[5014]363  {
[5933]364    std::list<IniSection>::const_iterator section;
365    for (section = this->sections.begin(); section != this->sections.end(); section++)
[3231]366    {
[5933]367      if (!strcmp((*section).name, sectionName))
[5014]368      {
[5933]369        std::list<IniEntry>::const_iterator entry;
370        for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
371          if (!strcmp((*entry).name, entryName))
372            return (*entry).value;
373        PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
374        break;
[5014]375      }
[3231]376    }
[5014]377    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
378  }
379  else
[5031]380    PRINTF(1)("%s not opened\n", fileName);
[5014]381
382  return defaultValue;
383
[2065]384}
[5014]385
[5031]386
387void IniParser::setFileName(const char* fileName)
388{
389  if (this->fileName)
390    delete []this->fileName;
391  if (fileName)
392  {
393    this->fileName = new char[strlen(fileName)+1];
394    strcpy(this->fileName, fileName);
395  }
396  else
397    this->fileName = NULL;
398}
399
400
[5017]401/**
402 * output the whole tree in a nice and easy way.
403 */
[5014]404void IniParser::debug() const
405{
[5031]406  PRINTF(0)("Iniparser %s - debug\n", this->fileName);
[5933]407  if (this->fileName != NULL)
[5014]408  {
[5933]409    std::list<IniSection>::const_iterator section;
410    for (section = this->sections.begin(); section != this->sections.end(); section++)
[5014]411    {
[5933]412      PRINTF(0)(" [%s]\n", (*section).name);
[5014]413
[5933]414      std::list<IniEntry>::const_iterator entry;
415      for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
416        PRINTF(0)("   '%s' -> '%s'\n", (*entry).name, (*entry).value);
[5014]417    }
418  }
419  else
[5933]420    PRINTF(1)("no opened ini-file.\n");
[5014]421}
Note: See TracBrowser for help on using the repository browser.