Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor cleanup

File size: 9.4 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->readFile(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::readFile(const char* fileName)
94{
95  FILE*    stream;           //!< The stream we use to read the file.
96  if (sections != NULL)
97    deleteSections();
98  if( fileName == NULL)
99    return false;
100
101  printf("1\n");
102  if( (stream = fopen (fileName, "r")) == NULL)
103  {
104    PRINTF(1)("IniParser could not open %s\n", fileName);
105    return false;
106  }
107  else
108  {
109    printf("2\n");
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    while( !feof( stream))
122    {
123      // get next line
124      fgets (lineBuffer, PARSELINELENGHT, stream);
125      // remove newline char, and \0-terminate
126      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
127        *ptr = 0;
128      // check for section identifyer
129      if (strlen(lineBuffer) <= 1)
130        ;//printf("empty Line\n");
131      else if( sscanf (lineBuffer, "[%s", buffer) == 1)
132      {
133        if( (ptr = strchr( buffer, ']')) != NULL)
134        {
135          *ptr = 0;
136          IniSection* newSection = new IniSection;
137          newSection->name = new char[strlen(buffer)+1];
138          strcpy(newSection->name, buffer);
139          newSection->entries = new tList<IniEntry>;
140          this->currentSection = newSection;
141          this->sections->add(newSection);
142        }
143      }
144      // check for Entry identifier (Entry = Value)
145      else if( (ptr = strchr( lineBuffer, '=')) != NULL)
146      {
147        if (currentSection == NULL)
148        {
149          PRINTF(2)("Not in a Section yet for %s\n", lineBuffer);
150          continue;
151        }
152        if( ptr == lineBuffer)
153          continue;
154        char* valueBegin = ptr+1;
155        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBuffer + strlen(lineBuffer))
156          ++valueBegin;
157        char* nameBegin = lineBuffer;
158        while ((*nameBegin == ' ' || *nameBegin == '\t') && nameBegin < ptr)
159          ++nameBegin;
160        char* nameEnd = ptr-1;
161        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= nameBegin)
162          --nameEnd;
163        nameEnd[1] = '\0';
164
165        IniEntry* newEntry = new IniEntry;
166        newEntry->value = new char[strlen(valueBegin)+1];
167        strcpy(newEntry->value, valueBegin);
168        newEntry->name = new char[strlen (nameBegin)+1];
169        strcpy(newEntry->name, nameBegin);
170
171        this->currentSection->entries->add(newEntry);
172      }
173    }
174  }
175  fclose(stream);
176  return true;
177}
178
179/**
180 *  set the parsing cursor to the specified section
181 * @param sectionName: the name of the section to set the cursor to
182 * @return true on success or false if the section could not be found
183*/
184bool IniParser::getSection( const char* sectionName)
185{
186  tIterator<IniSection>* sectionIt = this->sections->getIterator();
187  IniSection* sectionEnum = sectionIt->nextElement();
188  while (sectionEnum)
189  {
190    if (!strcmp(sectionEnum->name, sectionName))
191    {
192      this->currentSection = sectionEnum;
193      this->currentEntry = NULL;
194      delete sectionIt;
195      return true;
196    }
197
198    sectionEnum = sectionIt->nextElement();
199  }
200  delete sectionIt;
201  return false;
202}
203
204/**
205 * moves to the first section
206 */
207void IniParser::getFirstSection()
208{
209  if (this->sections)
210    this->currentSection = this->sections->firstElement();
211  else
212    this->currentSection = NULL;
213  this->currentEntry = NULL;
214}
215
216/**
217 * searches the next section
218 * @returns the name of the section if found, NULL otherwise
219 */
220const char* IniParser::nextSection()
221{
222  if (this->currentSection == NULL)
223    return NULL;
224  else
225  {
226    if (this->sections)
227    {
228      if (this->currentSection == this->sections->lastElement())
229        this->currentSection = NULL;
230      else
231        this->currentSection = this->sections->nextElement(this->currentSection);
232    }
233  }
234
235  if (this->currentSection != NULL)
236    return this->currentSection->name;
237  else
238    return NULL;
239}
240
241/**
242 * moves to the first Variable of the current Section
243 */
244void IniParser::getFirstVar()
245{
246  if (this->currentSection)
247    this->currentEntry = this->currentSection->entries->firstElement();
248  else
249    this->currentEntry = NULL;
250}
251
252/**
253 *  gets the next VarName=VarValue pair from the parsing stream
254 * @return true on success, false otherwise (in the latter case name and value will be NULL)
255 */
256bool IniParser::nextVar()
257{
258  if (this->currentSection == NULL
259      || this->currentEntry == NULL
260      || this->currentEntry == this->currentSection->entries->lastElement())
261  {
262    this->currentEntry = NULL;
263    return false;
264  }
265  this->currentEntry = this->currentSection->entries->nextElement(this->currentEntry);
266
267  if (this->currentEntry == NULL)
268    return false;
269  else
270    return true;
271}
272
273/**
274 *  directly acesses an entry in a section
275 * @param entryName: the name of the entry to find
276 * @param sectionName: the section where the entry is to be found
277 * @param defaultValue: what should be returned in case the entry cannot be found
278 * @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
279
280   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
281   lead to unwanted behaviour.
282*/
283const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
284{
285  if (this->sections)
286  {
287    tIterator<IniSection>* sectionIt = this->sections->getIterator();
288    IniSection* sectionEnum = sectionIt->nextElement();
289    while (sectionEnum)
290    {
291      if (!strcmp(sectionEnum->name, sectionName))
292      {
293        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
294        IniEntry* entryEnum = entryIt->nextElement();
295        while (entryEnum)
296        {
297          if (!strcmp(entryEnum->name, entryName))
298          {
299            delete entryIt;
300            delete sectionIt;
301            return entryEnum->value;
302          }
303          entryEnum = entryIt->nextElement();
304        }
305         delete entryIt;
306         PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
307         break;
308      }
309      sectionEnum = sectionIt->nextElement();
310    }
311    delete sectionIt;
312    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
313  }
314  else
315    PRINTF(1)("%s not opened\n", this->getName());
316
317  return defaultValue;
318
319}
320
321/**
322 * output the whole tree in a nice and easy way.
323 */
324void IniParser::debug() const
325{
326  PRINTF(0)("Iniparser %s - debug\n", this->getName());
327  if (this->sections)
328  {
329    tIterator<IniSection>* sectionIt = this->sections->getIterator();
330    IniSection* sectionEnum = sectionIt->nextElement();
331    while (sectionEnum)
332    {
333      PRINTF(0)(" [%s]\n", sectionEnum->name);
334
335      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
336      IniEntry* entryEnum = entryIt->nextElement();
337      while (entryEnum)
338      {
339        PRINTF(0)("   :%s: -> '%s'\n", entryEnum->name, entryEnum->value);
340
341        entryEnum = entryIt->nextElement();
342      }
343      delete entryIt;
344
345      sectionEnum = sectionIt->nextElement();
346    }
347    delete sectionIt;
348  }
349  else
350    PRINTF(1)("%s not opened\n", this->getName());
351}
Note: See TracBrowser for help on using the repository browser.