Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: doxygen tags

File size: 9.2 KB
Line 
1/*
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:
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.
18*/
19
20
21#include "ini_parser.h"
22
23#include "list.h"
24#include "stdlibincl.h"
25#include "debug.h"
26
27using namespace std;
28
29/**
30 *  constructs an IniParser using a file
31 * @param fileName: the path and name of the file to parse
32*/
33IniParser::IniParser (const char* fileName)
34{
35  this->setClassID(CL_INI_PARSER, "IniParser");
36  this->setName(fileName);
37
38  this->currentEntry = NULL;
39  this->currentSection = NULL;
40  this->sections = NULL;
41  if (fileName != NULL)
42    this->openFile(fileName);
43}
44
45/**
46 *  removes the IniParser from memory
47*/
48IniParser::~IniParser ()
49{
50  deleteSections();
51}
52
53/**
54 * removes all the sections. This is like delete, but even cooler :)
55 */
56void IniParser::deleteSections()
57{
58  if (this->sections)
59  {
60    tIterator<IniSection>* sectionIt = this->sections->getIterator();
61    IniSection* sectionEnum = sectionIt->nextElement();
62    while (sectionEnum)
63    {
64      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
65      IniEntry* entryEnum = entryIt->nextElement();
66      while (entryEnum)
67      {
68        delete []entryEnum->name;
69        delete []entryEnum->value;
70        delete entryEnum;
71        entryEnum = entryIt->nextElement();
72      }
73      delete entryIt;
74
75      delete []sectionEnum->name;
76      delete sectionEnum->entries;
77      delete sectionEnum;
78      sectionEnum = sectionIt->nextElement();
79    }
80    delete sectionIt;
81  }
82  delete this->sections;
83  this->currentEntry = NULL;
84  this->currentSection = NULL;
85  this->sections = NULL;
86}
87
88/**
89 * opens another file to parse
90 * @param fileName: path and name of the new file to parse
91 * @return true on success false otherwise;
92*/
93bool IniParser::openFile(const char* fileName)
94{
95  FILE*    stream;           //!< The stream we use to read the file.
96
97
98  if (sections != NULL)
99    deleteSections();
100  if( fileName == NULL)
101    return false;
102
103  if( (stream = fopen (fileName, "r")) == NULL)
104  {
105    PRINTF(1)("IniParser could not open %s\n", fileName);
106    return false;
107  }
108  else
109  {
110    this->currentEntry = NULL;
111    this->currentSection = NULL;
112    this->sections = new tList<IniSection>;
113
114    /////////////////////////////
115    // READING IN THE INI-FILE //
116    /////////////////////////////
117    char lineBuffer[PARSELINELENGHT];
118    char buffer[PARSELINELENGHT];
119    char* ptr;
120
121    rewind (stream);
122    while( !feof( stream))
123    {
124      // get next line
125      fgets (lineBuffer, PARSELINELENGHT, stream);
126      // remove newline char, and \0-terminate
127      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
128        *ptr = 0;
129      // check for section identifyer
130      if( sscanf (lineBuffer, "[%s", buffer) == 1)
131      {
132        if( (ptr = strchr( buffer, ']')) != NULL)
133        {
134          *ptr = 0;
135          IniSection* newSection = new IniSection;
136          newSection->name = new char[strlen(buffer)+1];
137          strcpy(newSection->name, buffer);
138          newSection->entries = new tList<IniEntry>;
139          this->sections->add(newSection);
140          this->currentSection = newSection;
141        }
142      }
143      else if( (ptr = strchr( lineBuffer, '=')) != NULL)
144      {
145        if (currentSection == NULL)
146        {
147          PRINTF(2)("Not in a Section yet for %s\n", lineBuffer);
148          continue;
149        }
150        if( ptr == lineBuffer)
151          continue;
152        IniEntry* newEntry = new IniEntry;
153
154        char* valueBegin = ptr+1;
155        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBuffer + strlen(lineBuffer))
156          ++valueBegin;
157        newEntry->value = new char[strlen(valueBegin)+1];
158        strcpy(newEntry->value, valueBegin);
159        char* nameEnd = ptr-1, *nameBegin = lineBuffer;
160        while ((*nameBegin == ' ' || *nameBegin == '\t') && nameBegin < ptr)
161          ++nameBegin;
162        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= nameBegin)
163          --nameEnd;
164        nameEnd[1] = '\0';
165        newEntry->name = new char[strlen (nameBegin)];
166        strcpy(newEntry->name, nameBegin);
167
168        this->currentSection->entries->add(newEntry);
169      }
170
171    }
172  }
173  fclose(stream);
174  return true;
175}
176
177/**
178 *  set the parsing cursor to the specified section
179 * @param sectionName: the name of the section to set the cursor to
180 * @return true on success or false if the section could not be found
181*/
182bool IniParser::getSection( const char* sectionName)
183{
184  tIterator<IniSection>* sectionIt = this->sections->getIterator();
185  IniSection* sectionEnum = sectionIt->nextElement();
186  while (sectionEnum)
187  {
188    if (!strcmp(sectionEnum->name, sectionName))
189    {
190      this->currentSection = sectionEnum;
191      this->currentEntry = NULL;
192      delete sectionIt;
193      return true;
194    }
195
196    sectionEnum = sectionIt->nextElement();
197  }
198  delete sectionIt;
199  return false;
200}
201
202/**
203 * moves to the first section
204 */
205void IniParser::getFirstSection()
206{
207  if (this->sections)
208    this->currentSection = this->sections->firstElement();
209  else
210    this->currentSection = NULL;
211  this->currentEntry = NULL;
212}
213
214/**
215 * searches the next section
216 * @returns the name of the section if found, NULL otherwise
217 */
218const char* IniParser::nextSection()
219{
220  if (this->currentSection == NULL)
221    return NULL;
222  else
223  {
224    if (this->sections)
225    {
226      if (this->currentSection == this->sections->lastElement())
227        this->currentSection = NULL;
228      else
229        this->currentSection = this->sections->nextElement(this->currentSection);
230    }
231  }
232
233  if (this->currentSection != NULL)
234    return this->currentSection->name;
235  else
236    return NULL;
237}
238
239/**
240 * moves to the first Variable of the current Section
241 */
242void IniParser::getFirstVar()
243{
244  if (this->currentSection)
245    this->currentEntry = this->currentSection->entries->firstElement();
246  else
247    this->currentEntry = NULL;
248}
249
250/**
251 *  gets the next VarName=VarValue pair from the parsing stream
252 * @return true on success, false otherwise (in the latter case name and value will be NULL)
253 */
254bool IniParser::nextVar()
255{
256  if (this->currentSection == NULL
257      || this->currentEntry == NULL
258      || this->currentEntry == this->currentSection->entries->lastElement())
259  {
260    this->currentEntry = NULL;
261    return false;
262  }
263  this->currentEntry = this->currentSection->entries->nextElement(this->currentEntry);
264
265  if (this->currentEntry == NULL)
266    return false;
267  else
268    return true;
269}
270
271/**
272 *  directly acesses an entry in a section
273 * @param entryName: the name of the entry to find
274 * @param sectionName: the section where the entry is to be found
275 * @param defaultValue: what should be returned in case the entry cannot be found
276 * @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
277
278   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
279   lead to unwanted behaviour.
280*/
281const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
282{
283  if (this->sections)
284  {
285    tIterator<IniSection>* sectionIt = this->sections->getIterator();
286    IniSection* sectionEnum = sectionIt->nextElement();
287    while (sectionEnum)
288    {
289      if (!strcmp(sectionEnum->name, sectionName))
290      {
291        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
292        IniEntry* entryEnum = entryIt->nextElement();
293        while (entryEnum)
294        {
295          if (!strcmp(entryEnum->name, entryName))
296          {
297            delete entryIt;
298            delete sectionIt;
299            return entryEnum->value;
300          }
301          entryEnum = entryIt->nextElement();
302        }
303         delete entryIt;
304         PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
305         break;
306      }
307      sectionEnum = sectionIt->nextElement();
308    }
309    delete sectionIt;
310    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
311  }
312  else
313    PRINTF(1)("%s not opened\n", this->getName());
314
315  return defaultValue;
316
317}
318
319/**
320 * output the whole tree in a nice and easy way.
321 */
322void IniParser::debug() const
323{
324  PRINTF(0)("Iniparser %s - debug\n", this->getName());
325  if (this->sections)
326  {
327    tIterator<IniSection>* sectionIt = this->sections->getIterator();
328    IniSection* sectionEnum = sectionIt->nextElement();
329    while (sectionEnum)
330    {
331      PRINTF(0)(" [%s]\n", sectionEnum->name);
332
333      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
334      IniEntry* entryEnum = entryIt->nextElement();
335      while (entryEnum)
336      {
337        PRINTF(0)("   :%s: -> '%s'\n", entryEnum->name, entryEnum->value);
338
339        entryEnum = entryIt->nextElement();
340      }
341      delete entryIt;
342
343      sectionEnum = sectionIt->nextElement();
344    }
345    delete sectionIt;
346  }
347  else
348    PRINTF(1)("%s not opened\n", this->getName());
349}
Note: See TracBrowser for help on using the repository browser.