Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: IniParser: added the ability to write to files

File size: 11.8 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
37  this->currentEntry = NULL;
38  this->currentSection = NULL;
39  this->sections = NULL;
40  if (fileName != NULL)
41    this->readFile(fileName);
42}
43
44/**
45 *  removes the IniParser from memory
46*/
47IniParser::~IniParser ()
48{
49  deleteSections();
50}
51
52/**
53 * removes all the sections. This is like delete, but even cooler :)
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->currentEntry = NULL;
83  this->currentSection = NULL;
84  this->sections = NULL;
85  this->setName(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  this->setName(fileName);
101
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    this->currentEntry = NULL;
110    this->currentSection = NULL;
111    this->sections = new tList<IniSection>;
112
113    /////////////////////////////
114    // READING IN THE INI-FILE //
115    /////////////////////////////
116    char lineBuffer[PARSELINELENGHT];
117    char buffer[PARSELINELENGHT];
118    char* ptr;
119
120    while( !feof( stream))
121    {
122      // get next line
123      fgets (lineBuffer, PARSELINELENGHT, stream);
124      // remove newline char, and \0-terminate
125      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
126        *ptr = 0;
127      // check for section identifyer
128      if (strlen(lineBuffer) <= 1)
129        ;//printf("empty Line\n");
130      else if( sscanf (lineBuffer, "[%s", buffer) == 1)
131      {
132        if( (ptr = strchr( buffer, ']')) != NULL)
133        {
134          *ptr = 0;
135          this->addSection(buffer);
136        }
137      }
138      // check for Entry identifier (Entry = Value)
139      else if( (ptr = strchr( lineBuffer, '=')) != NULL)
140      {
141        if (currentSection == NULL)
142        {
143          PRINTF(2)("Not in a Section yet for %s\n", lineBuffer);
144          continue;
145        }
146        if( ptr == lineBuffer)
147          continue;
148        char* valueBegin = ptr+1;
149        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBuffer + strlen(lineBuffer))
150          ++valueBegin;
151        char* nameBegin = lineBuffer;
152        while ((*nameBegin == ' ' || *nameBegin == '\t') && nameBegin < ptr)
153          ++nameBegin;
154        char* nameEnd = ptr-1;
155        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= nameBegin)
156          --nameEnd;
157        nameEnd[1] = '\0';
158
159        this->addVar(nameBegin, valueBegin);
160      }
161    }
162  }
163  fclose(stream);
164  return true;
165}
166
167/**
168 * opens a file and writes to it
169 * @param fileName: path and name of the new file to write to
170 * @return true on success false otherwise
171 */
172bool IniParser::writeFile(const char* fileName)
173{
174  FILE*    stream;           //!< The stream we use to read the file.
175  if (sections != NULL)
176    deleteSections();
177  if( fileName == NULL)
178    return false;
179
180  if( (stream = fopen (fileName, "w")) == NULL)
181  {
182    PRINTF(1)("IniParser could not open %s\n", fileName);
183    return false;
184  }
185  else
186  {
187    if (this->sections)
188    {
189      tIterator<IniSection>* sectionIt = this->sections->getIterator();
190      IniSection* sectionEnum = sectionIt->nextElement();
191      while (sectionEnum)
192      {
193        fprintf(stream, " [%s]\n", sectionEnum->name);
194
195        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
196        IniEntry* entryEnum = entryIt->nextElement();
197        while (entryEnum)
198        {
199          fprintf(stream, " %s = %s\n", entryEnum->name, entryEnum->value);
200
201          entryEnum = entryIt->nextElement();
202        }
203        delete entryIt;
204
205        sectionEnum = sectionIt->nextElement();
206      }
207      delete sectionIt;
208    }
209    else
210      PRINTF(1)("%s no sections defined yet\n", fileName);
211  }
212  fclose(stream);
213}
214
215bool IniParser::addSection(const char* sectionName)
216{
217  if (this->sections == NULL)
218    this->sections = new tList<IniSection>;
219
220  IniSection* newSection = new IniSection;
221  newSection->name = new char[strlen(sectionName)+1];
222  strcpy(newSection->name, sectionName);
223  newSection->entries = new tList<IniEntry>;
224  this->currentSection = newSection;
225  this->sections->add(newSection);
226}
227
228/**
229 *  set the parsing cursor to the specified section
230 * @param sectionName: the name of the section to set the cursor to
231 * @return true on success or false if the section could not be found
232*/
233bool IniParser::getSection( const char* sectionName)
234{
235  tIterator<IniSection>* sectionIt = this->sections->getIterator();
236  IniSection* sectionEnum = sectionIt->nextElement();
237  while (sectionEnum)
238  {
239    if (!strcmp(sectionEnum->name, sectionName))
240    {
241      this->currentSection = sectionEnum;
242      this->currentEntry = NULL;
243      delete sectionIt;
244      return true;
245    }
246
247    sectionEnum = sectionIt->nextElement();
248  }
249  delete sectionIt;
250  return false;
251}
252
253/**
254 * moves to the first section
255 */
256void IniParser::getFirstSection()
257{
258  if (this->sections)
259    this->currentSection = this->sections->firstElement();
260  else
261    this->currentSection = NULL;
262  this->currentEntry = NULL;
263}
264
265/**
266 * searches the next section
267 * @returns the name of the section if found, NULL otherwise
268 */
269const char* IniParser::nextSection()
270{
271  if (this->currentSection == NULL)
272    return NULL;
273  else
274  {
275    if (this->sections)
276    {
277      if (this->currentSection == this->sections->lastElement())
278        this->currentSection = NULL;
279      else
280        this->currentSection = this->sections->nextElement(this->currentSection);
281    }
282  }
283
284  if (this->currentSection != NULL)
285    return this->currentSection->name;
286  else
287    return NULL;
288}
289
290/**
291 * moves to the first Variable of the current Section
292 */
293void IniParser::getFirstVar()
294{
295  if (this->currentSection)
296    this->currentEntry = this->currentSection->entries->firstElement();
297  else
298    this->currentEntry = NULL;
299}
300
301/**
302 *  gets the next VarName=VarValue pair from the parsing stream
303 * @return true on success, false otherwise (in the latter case name and value will be NULL)
304 */
305bool IniParser::nextVar()
306{
307  if (this->currentSection == NULL
308      || this->currentEntry == NULL
309      || this->currentEntry == this->currentSection->entries->lastElement())
310  {
311    this->currentEntry = NULL;
312    return false;
313  }
314  this->currentEntry = this->currentSection->entries->nextElement(this->currentEntry);
315
316  if (this->currentEntry == NULL)
317    return false;
318  else
319    return true;
320}
321
322/**
323 * adds a new Entry to either the currentSection or the section called by sectionName
324 * @param entryName the Name of the Entry to add
325 * @param value the value to assign to this entry
326 * @param sectionName if NULL then this entry will be set to the currentSection
327 * otherwise to the section refered to by sectionName.
328 * If both are NULL no entry will be added
329 * @return true if everything is ok false on error
330 */
331bool IniParser::addVar(const char* entryName, const char* value, const char* sectionName)
332{
333  IniSection* addSection = NULL;
334  if (sectionName != NULL)
335  {
336    tIterator<IniSection>* sectionIt = this->sections->getIterator();
337    IniSection* sectionEnum = sectionIt->nextElement();
338    while (sectionEnum)
339    {
340      if (!strcmp(sectionEnum->name, sectionName))
341      {
342        addSection = sectionEnum;
343        break;
344      }
345      sectionEnum = sectionIt->nextElement();
346    }
347    delete sectionIt;
348  }
349  else
350    addSection = this->currentSection;
351
352  if (addSection == NULL)
353  {
354    PRINTF(2)("section not found for value %s\n", entryName);
355    return false;
356  }
357  else
358  {
359    IniEntry* newEntry = new IniEntry;
360    newEntry->name = new char[strlen (entryName)+1];
361    strcpy(newEntry->name, entryName);
362    newEntry->value = new char[strlen(value)+1];
363    strcpy(newEntry->value, value);
364    this->currentSection->entries->add(newEntry);
365    return true;
366  }
367}
368
369/**
370 *  directly acesses an entry in a section
371 * @param entryName: the name of the entry to find
372 * @param sectionName: the section where the entry is to be found
373 * @param defaultValue: what should be returned in case the entry cannot be found
374 * @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
375 *
376 *  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
377 * lead to unwanted behaviour.
378*/
379const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
380{
381  if (this->sections)
382  {
383    tIterator<IniSection>* sectionIt = this->sections->getIterator();
384    IniSection* sectionEnum = sectionIt->nextElement();
385    while (sectionEnum)
386    {
387      if (!strcmp(sectionEnum->name, sectionName))
388      {
389        tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
390        IniEntry* entryEnum = entryIt->nextElement();
391        while (entryEnum)
392        {
393          if (!strcmp(entryEnum->name, entryName))
394          {
395            delete entryIt;
396            delete sectionIt;
397            return entryEnum->value;
398          }
399          entryEnum = entryIt->nextElement();
400        }
401         delete entryIt;
402         PRINTF(2)("Entry %s in section %s not found.\n", entryName, sectionName);
403         break;
404      }
405      sectionEnum = sectionIt->nextElement();
406    }
407    delete sectionIt;
408    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
409  }
410  else
411    PRINTF(1)("%s not opened\n", this->getName());
412
413  return defaultValue;
414
415}
416
417/**
418 * output the whole tree in a nice and easy way.
419 */
420void IniParser::debug() const
421{
422  PRINTF(0)("Iniparser %s - debug\n", this->getName());
423  if (this->sections)
424  {
425    tIterator<IniSection>* sectionIt = this->sections->getIterator();
426    IniSection* sectionEnum = sectionIt->nextElement();
427    while (sectionEnum)
428    {
429      PRINTF(0)(" [%s]\n", sectionEnum->name);
430
431      tIterator<IniEntry>* entryIt = sectionEnum->entries->getIterator();
432      IniEntry* entryEnum = entryIt->nextElement();
433      while (entryEnum)
434      {
435        PRINTF(0)("   :%s: -> '%s'\n", entryEnum->name, entryEnum->value);
436
437        entryEnum = entryIt->nextElement();
438      }
439      delete entryIt;
440
441      sectionEnum = sectionIt->nextElement();
442    }
443    delete sectionIt;
444  }
445  else
446    PRINTF(1)("%s not opened\n", this->getName());
447}
Note: See TracBrowser for help on using the repository browser.