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
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 <stdlib.h>
24#include <string.h>
25
26#ifdef DEBUG
27 #include "debug.h"
28#else
29 #define PRINTF(x) printf
30#endif
31
32using namespace std;
33
34/**
35 *  constructs an IniParser using a file
36 * @param fileName: the path and name of the file to parse
37 */
38IniParser::IniParser (const char* fileName)
39{
40  this->fileName = NULL;
41
42  if (fileName != NULL)
43    this->readFile(fileName);
44}
45
46
47/**
48 *  removes the IniParser from memory
49 */
50IniParser::~IniParser ()
51{
52  this->deleteSections();
53}
54
55
56/**
57 * removes all the sections. This is like delete, but even cooler :)
58 */
59void IniParser::deleteSections()
60{
61  while(!this->sections.empty())
62  {
63    IniSection section = this->sections.front();
64
65    while(!section.entries.empty())
66    {
67      IniEntry entry = section.entries.front();
68      delete []entry.name;
69      delete []entry.value;
70      section.entries.pop_front();
71    }
72
73    delete []section.name;
74    this->sections.pop_front();
75  }
76
77//  this->currentEntry = NULL;
78//  this->currentSection = NULL;
79  this->setFileName(NULL);
80}
81
82
83/**
84 * opens another file to parse
85 * @param fileName: path and name of the new file to parse
86 * @return true on success false otherwise;
87 */
88bool IniParser::readFile(const char* fileName)
89{
90  FILE*    stream;           //!< The stream we use to read the file.
91  if (!sections.empty())
92    deleteSections();
93  if( fileName == NULL)
94    return false;
95  this->setFileName(fileName);
96
97  if( (stream = fopen (fileName, "r")) == NULL)
98  {
99    PRINTF(1)("IniParser could not open %s\n", fileName);
100    return false;
101  }
102  else
103  {
104    this->currentEntry = 0;//this->sections.begin();
105    this->currentSection = this->sections.begin();
106
107    /////////////////////////////
108    // READING IN THE INI-FILE //
109    /////////////////////////////
110    char lineBuffer[PARSELINELENGHT];
111    char buffer[PARSELINELENGHT];
112    const char* lineBegin;
113    char* ptr;
114
115    while( fgets (lineBuffer, PARSELINELENGHT, stream))
116    {
117      lineBegin = lineBuffer;
118      // remove newline char, and \0-terminate
119      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
120        *ptr = 0;
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");
126      // check for section identifyer
127      else if( sscanf (lineBegin, "[%s", buffer) == 1)
128      {
129        if( (ptr = strchr( buffer, ']')) != NULL)
130        {
131          *ptr = 0;
132          this->addSection(buffer);
133        }
134      }
135      // check for Entry identifier (Entry = Value)
136      else if( (ptr = strchr( lineBegin, '=')) != NULL)
137      {
138        if (currentSection == NULL)
139        {
140          PRINTF(2)("Not in a Section yet for %s\n", lineBegin);
141          continue;
142        }
143        if( ptr == lineBegin)
144          continue;
145        char* valueBegin = ptr+1;
146        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBegin + strlen(lineBegin))
147          ++valueBegin;
148        char* valueEnd = valueBegin + strlen(valueBegin)-1;
149        while ((*valueEnd == ' ' || *valueEnd == '\t') && valueEnd >= valueBegin)
150          --valueEnd;
151        valueEnd[1] = '\0';
152        char* nameEnd = ptr-1;
153        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= lineBegin)
154          --nameEnd;
155        nameEnd[1] = '\0';
156
157        this->addVar(lineBegin, valueBegin);
158      }
159    }
160  }
161  fclose(stream);
162  return true;
163}
164
165
166/**
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  {
184    if (!this->sections.empty())
185    {
186      std::list<IniSection>::iterator section;
187      for (section = this->sections.begin(); section != this->sections.end(); section++)
188      {
189        fprintf(stream, "\n [%s]\n", (*section).name);
190
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);
194      }
195    }
196    else
197      PRINTF(1)("%s no sections defined yet\n", fileName);
198  }
199  fclose(stream);
200}
201
202
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 */
209bool IniParser::addSection(const char* sectionName)
210{
211  this->sections.push_back(IniSection());
212
213  this->sections.back().name = new char[strlen(sectionName)+1];
214  strcpy(this->sections.back().name, sectionName);
215
216  this->currentSection = --this->sections.end();
217  PRINTF(5)("Added Section %s\n", sectionName);
218  return true;
219}
220
221
222/**
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
226*/
227bool IniParser::getSection( const char* sectionName)
228{
229  std::list<IniSection>::iterator section;
230  for (section = this->sections.begin(); section != this->sections.end(); section++)
231  {
232    if (!strcmp((*section).name, sectionName))
233    {
234      this->currentSection = section;
235      this->currentEntry = (*section).entries.begin();
236      return true;
237    }
238  }
239  return false;
240}
241
242
243/**
244 * moves to the first section
245 */
246void IniParser::getFirstSection()
247{
248  this->currentSection = this->sections.begin();
249  this->currentEntry = (*this->currentSection).entries.begin();
250}
251
252
253/**
254 * searches the next section
255 * @returns the name of the section if found, NULL otherwise
256 */
257const char* IniParser::nextSection()
258{
259  if (this->currentSection == this->sections.end())
260    return NULL;
261  else
262  {
263    if (this->currentSection == this->sections.end())
264      return NULL;
265    else
266      this->currentSection++;
267  }
268
269  if (this->currentSection != NULL)
270    return this->currentSection->name;
271  else
272    return NULL;
273}
274
275
276/**
277 * moves to the first Variable of the current Section
278 */
279void IniParser::getFirstVar()
280{
281  if (this->currentSection != this->sections.end())
282    this->currentEntry = (*this->currentSection).entries.begin();
283//  else
284//    this->currentEntry = NULL;
285}
286
287
288/**
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{
294  if (this->currentSection == NULL
295      || this->currentEntry == NULL
296      || this->currentEntry == (*this->currentSection).entries.end())
297  {
298    this->currentEntry = NULL;
299    return false;
300  }
301  this->currentEntry++;
302
303  if (this->currentEntry == NULL)
304    return false;
305  else
306    return true;
307}
308
309
310/**
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{
321  std::list<IniSection>::iterator section = this->sections.end();
322
323  if (sectionName != NULL)
324  {
325    for (section = this->sections.begin(); section != this->sections.end(); section++)
326      if (!strcmp((*section).name, sectionName))
327        break;
328  }
329  else
330    section = this->currentSection;
331
332  if (section == this->sections.end())
333  {
334    PRINTF(2)("section not found for value %s\n", entryName);
335    return false;
336  }
337  else
338  {
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);
345    return true;
346  }
347}
348
349
350/**
351 *  directly acesses an entry in a section
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
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
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.
359*/
360const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
361{
362  if (fileName != NULL)
363  {
364    std::list<IniSection>::const_iterator section;
365    for (section = this->sections.begin(); section != this->sections.end(); section++)
366    {
367      if (!strcmp((*section).name, sectionName))
368      {
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;
375      }
376    }
377    PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
378  }
379  else
380    PRINTF(1)("%s not opened\n", fileName);
381
382  return defaultValue;
383
384}
385
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
401/**
402 * output the whole tree in a nice and easy way.
403 */
404void IniParser::debug() const
405{
406  PRINTF(0)("Iniparser %s - debug\n", this->fileName);
407  if (this->fileName != NULL)
408  {
409    std::list<IniSection>::const_iterator section;
410    for (section = this->sections.begin(); section != this->sections.end(); section++)
411    {
412      PRINTF(0)(" [%s]\n", (*section).name);
413
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);
417    }
418  }
419  else
420    PRINTF(1)("no opened ini-file.\n");
421}
Note: See TracBrowser for help on using the repository browser.