Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: implemented a new kind of ini-parser
this parser first reads the file, and then one can search through without accessing the file anymore

File size: 8.7 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
26#include "resource_manager.h"
27#include "debug.h"
28
29using namespace std;
30
31/**
32 *  constructs an IniParser using a file
33 * @param filename: the path and name of the file to parse
34*/
35IniParser::IniParser (const char* fileName)
36{
37  this->setClassID(CL_INI_PARSER, "IniParser");
38  this->setName(fileName);
39
40  this->currentEntry = NULL;
41  this->currentSection = NULL;
42  this->sections = NULL;
43  if (fileName != NULL)
44    this->openFile(fileName);
45}
46
47/**
48 *  removes the IniParser from memory
49*/
50IniParser::~IniParser ()
51{
52  deleteSections();
53}
54
55void IniParser::deleteSections()
56{
57  if (this->sections)
58  {
59    tIterator<IniSection>* sectionIt = this->sections->getIterator();
60    IniSection* sectionEnum = sectionIt->nextElement();
61    while (sectionEnum)
62    {
63      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
64      IniEntry* entryEnum = entryIt->nextElement();
65      while (entryEnum)
66      {
67        delete []entryEnum->name;
68        delete []entryEnum->value;
69        delete entryEnum;
70        entryEnum = entryIt->nextElement();
71      }
72      delete entryIt;
73
74      delete []sectionEnum->name;
75      delete sectionEnum->entries;
76      delete sectionEnum;
77      sectionEnum = sectionIt->nextElement();
78    }
79    delete sectionIt;
80  }
81  delete this->sections;
82  this->sections = NULL;
83}
84
85/**
86 * opens another file to parse
87 * @param filename: path and name of the new file to parse
88 * @return true on success false otherwise;
89*/
90bool IniParser::openFile(const char* filename)
91{
92  FILE*    stream;           //!< The stream we use to read the file.
93
94
95  if( filename == NULL)
96    return false;
97  char* tmpName = ResourceManager::homeDirCheck(filename);
98
99  if (sections != NULL)
100    deleteSections();
101
102  if( (stream = fopen (tmpName, "r")) == NULL)
103  {
104    PRINTF(1)("IniParser could not open %s\n", filename);
105    delete tmpName;
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      delete sectionIt;
192      return true;
193    }
194
195    sectionEnum = sectionIt->nextElement();
196  }
197  delete sectionIt;
198  return false;
199}
200
201/**
202 * searches the next section
203 * @returns the name of the section if found, NULL otherwise
204 */
205const char* IniParser::nextSection()
206{
207  if (this->currentSection == NULL)
208    return NULL;
209  else
210  {
211    if (this->sections)
212      this->currentSection = sections->nextElement(this->currentSection);
213  }
214  if (this->currentSection != NULL)
215    return this->currentSection->name;
216  else
217    return NULL;
218}
219
220/**
221 *  gets the next VarName=VarValue pair from the parsing stream
222 * @param name: a pointer to the Name of the next Var
223 * @param value: a pointer to the Value of the next Var
224 * @return true on success, false otherwise (in the latter case name and value will be NULL)
225 */
226bool IniParser::nextVar()
227{
228  if (this->currentSection == NULL)
229    return false;
230  if(this->currentEntry == this->currentSection->entries->lastElement())
231  {
232    this->currentEntry = NULL;
233    return false;
234  }
235  if (this->currentEntry == NULL)
236    this->currentEntry = this->currentSection->entries->firstElement();
237  else
238    this->currentEntry = this->currentSection->entries->nextElement(this->currentEntry);
239
240  if (this->currentEntry == NULL)
241    return false;
242  else
243    return true;
244}
245
246/**
247 *  directly acesses an entry in a section
248 * @param entryName: the name of the entry to find
249 * @param sectionName: the section where the entry is to be found
250 * @param defaultValue: what should be returned in case the entry cannot be found
251 * @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
252
253   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
254   lead to unwanted behaviour.
255*/
256const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
257{
258  if (this->sections)
259  {
260    tIterator<IniSection>* sectionIt = this->sections->getIterator();
261    IniSection* sectionEnum = sectionIt->nextElement();
262    while (sectionEnum)
263    {
264      if (!strcmp(sectionEnum->name, sectionName))
265      {
266        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
267        IniEntry* entryEnum = entryIt->nextElement();
268        while (entryEnum)
269        {
270          if (!strcmp(entryEnum->name, entryName))
271          {
272            delete entryIt;
273            delete sectionIt;
274            return entryEnum->value;
275          }
276          entryEnum = entryIt->nextElement();
277        }
278         delete entryIt;
279         PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
280         break;
281      }
282      sectionEnum = sectionIt->nextElement();
283    }
284    delete sectionIt;
285    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
286  }
287  else
288    PRINTF(1)("%s not opened\n", this->getName());
289
290  return defaultValue;
291
292}
293
294void IniParser::debug() const
295{
296  PRINTF(0)("Iniparser %s - debug\n", this->getName());
297  if (this->sections)
298  {
299    tIterator<IniSection>* sectionIt = this->sections->getIterator();
300    IniSection* sectionEnum = sectionIt->nextElement();
301    while (sectionEnum)
302    {
303      PRINTF(0)(" [%s]\n", sectionEnum->name);
304
305      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
306      IniEntry* entryEnum = entryIt->nextElement();
307      while (entryEnum)
308      {
309        PRINTF(0)("   :%s: -> '%s'\n", entryEnum->name, entryEnum->value);
310
311        entryEnum = entryIt->nextElement();
312      }
313      delete entryIt;
314
315      sectionEnum = sectionIt->nextElement();
316    }
317    delete sectionIt;
318  }
319  else
320    PRINTF(1)("%s not opened\n", this->getName());
321}
Note: See TracBrowser for help on using the repository browser.