Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/parser/ini_parser/ini_parser.cc @ 5946

Last change on this file since 5946 was 5946, checked in by bensch, 18 years ago

orxonox/trunk: adding comments (simple)

File size: 17.4 KB
RevLine 
[4597]1/*
[2064]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:
[5014]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.
[2064]18*/
19
20
21#include "ini_parser.h"
[4381]22
[5031]23#include <stdlib.h>
24#include <string.h>
[2064]25
[5944]26#if HAVE_CONFIG_H
27#include <config.h>
[5938]28#endif
29
[5933]30#ifdef DEBUG
[5944]31 #include "../../../defs/debug.h"
[5933]32#else
33 #define PRINTF(x) printf
34#endif
35
[2064]36using namespace std;
37
[2141]38/**
[5934]39 * @brief constructs an IniParser using a file
[5017]40 * @param fileName: the path and name of the file to parse
[5933]41 */
[5014]42IniParser::IniParser (const char* fileName)
[2064]43{
[5031]44  this->fileName = NULL;
[5945]45  this->comment = NULL;
[5933]46
[5014]47  if (fileName != NULL)
[5018]48    this->readFile(fileName);
[2064]49}
50
[5933]51
[2141]52/**
[5934]53 * @brief removes the IniParser from memory
[5933]54 */
[2064]55IniParser::~IniParser ()
56{
[5933]57  this->deleteSections();
[2064]58}
59
[5933]60
[5015]61/**
[5934]62 * @brief removes all the sections. This is like delete, but even cooler :)
[5015]63 */
[5014]64void IniParser::deleteSections()
[2064]65{
[5934]66  // in all sections
[5933]67  while(!this->sections.empty())
[5014]68  {
[5936]69     IniSection section = this->sections.front();
[5944]70
[5934]71    // in all entries of the sections
[5933]72    while(!section.entries.empty())
[3231]73    {
[5934]74      // delete all strings of entries.
[5933]75      IniEntry entry = section.entries.front();
76      delete []entry.name;
77      delete []entry.value;
78      section.entries.pop_front();
79    }
[5934]80    // delete all Sections
[5933]81    delete []section.name;
82    this->sections.pop_front();
[5014]83  }
[5936]84  this->currentSection = this->sections.end();
[5031]85  this->setFileName(NULL);
[2064]86}
87
[5933]88
[2141]89/**
[5934]90 * @brief sets the Name of the input-file
91 * @param fileName The new FileName to set to the IniParser
[5938]92 * If fileName is NULL the new Name will be set to NULL too.
[5934]93 */
94void IniParser::setFileName(const char* fileName)
95{
96  if (this->fileName)
97    delete []this->fileName;
[5938]98  if (fileName != NULL)
[5934]99  {
100    this->fileName = new char[strlen(fileName)+1];
101    strcpy(this->fileName, fileName);
102  }
103  else
104    this->fileName = NULL;
105}
106
107
108/**
[5944]109 * @brief opens a file to parse
[5017]110 * @param fileName: path and name of the new file to parse
[5014]111 * @return true on success false otherwise;
[5934]112 *
113 * If there was already an opened file, the file will be closed,
114 * and the new one will be opened.
[5933]115 */
[5018]116bool IniParser::readFile(const char* fileName)
[2064]117{
[5934]118  FILE*    stream;           //< The stream we use to read the file.
[5945]119  int      lineCount = 0;    //< The Count of lines.
[5934]120
[5945]121
[5934]122  if (this->fileName != NULL)
123    this->deleteSections();
[5015]124  if( fileName == NULL)
125    return false;
[5014]126
[5015]127  if( (stream = fopen (fileName, "r")) == NULL)
[5014]128  {
[5015]129    PRINTF(1)("IniParser could not open %s\n", fileName);
[5014]130    return false;
131  }
132  else
133  {
[5934]134    this->setFileName(fileName);
[5014]135
136    /////////////////////////////
137    // READING IN THE INI-FILE //
138    /////////////////////////////
139    char lineBuffer[PARSELINELENGHT];
140    char buffer[PARSELINELENGHT];
[5021]141    const char* lineBegin;
[5014]142    char* ptr;
143
[5319]144    while( fgets (lineBuffer, PARSELINELENGHT, stream))
[2551]145    {
[5021]146      lineBegin = lineBuffer;
[5014]147      // remove newline char, and \0-terminate
148      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
149        *ptr = 0;
[5021]150      // cut up to the beginning of the line.
151      while((*lineBegin == ' ' || *lineBegin == '\t') && lineBegin < lineBuffer + strlen(lineBuffer))
152        ++lineBegin;
[5946]153
154      // check if we have a FileComment
155      if ( (*lineBegin == '#' || *lineBegin == ';'))
156      {
157        printf("___________%d_____%s\n", lineCount,lineBegin);
158        char* newCommenLine = new char[strlen(lineBegin)+1];
159        strcpy(newCommenLine, lineBegin);
160        this->commentList.push_back(newCommenLine);
161        continue;
162      }
163      if (lineCount == 0 && !this->commentList.empty())
164      {
165        this->setFileComment();
166        lineCount++;
167      }
168
[2551]169      // check for section identifyer
[5021]170      else if( sscanf (lineBegin, "[%s", buffer) == 1)
[5014]171      {
172        if( (ptr = strchr( buffer, ']')) != NULL)
[4597]173        {
[5014]174          *ptr = 0;
[5020]175          this->addSection(buffer);
[5946]176          this->setSectionComment();
[4597]177        }
[5014]178      }
[5018]179      // check for Entry identifier (Entry = Value)
[5021]180      else if( (ptr = strchr( lineBegin, '=')) != NULL)
[5014]181      {
182        if (currentSection == NULL)
183        {
[5021]184          PRINTF(2)("Not in a Section yet for %s\n", lineBegin);
[5946]185          lineCount++;
[5014]186          continue;
187        }
[5946]188        if( ptr == lineBegin) {
189          lineCount++;
[5014]190          continue;
[5946]191        }
[5014]192        char* valueBegin = ptr+1;
[5021]193        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBegin + strlen(lineBegin))
[5014]194          ++valueBegin;
[5022]195        char* valueEnd = valueBegin + strlen(valueBegin)-1;
196        while ((*valueEnd == ' ' || *valueEnd == '\t') && valueEnd >= valueBegin)
197          --valueEnd;
198        valueEnd[1] = '\0';
[5018]199        char* nameEnd = ptr-1;
[5021]200        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= lineBegin)
[5014]201          --nameEnd;
202        nameEnd[1] = '\0';
[5018]203
[5021]204        this->addVar(lineBegin, valueBegin);
[5946]205        this->setEntryComment();
[5945]206
207        lineCount++;
[5014]208      }
[2551]209    }
[5014]210  }
[5934]211  this->currentSection = this->sections.begin();
212  if (!this->sections.empty())
213    this->currentEntry = (*this->currentSection).entries.begin();
214
[5014]215  fclose(stream);
216  return true;
[2064]217}
218
[5933]219
[2141]220/**
[5934]221 * @brief opens a file and writes to it
[5020]222 * @param fileName: path and name of the new file to write to
223 * @return true on success false otherwise
224 */
[5936]225bool IniParser::writeFile(const char* fileName) const
[5020]226{
227  FILE*    stream;           //!< The stream we use to read the file.
[5945]228  if( fileName == NULL && (fileName = this->fileName) == NULL )
[5020]229    return false;
230
231  if( (stream = fopen (fileName, "w")) == NULL)
232  {
233    PRINTF(1)("IniParser could not open %s\n", fileName);
234    return false;
235  }
236  else
237  {
[5936]238    std::list<IniSection>::const_iterator section;
[5934]239    for (section = this->sections.begin(); section != this->sections.end(); section++)
[5020]240      {
[5933]241        fprintf(stream, "\n [%s]\n", (*section).name);
[5944]242
[5936]243        std::list<IniEntry>::const_iterator entry;
[5933]244        for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
245          fprintf(stream, "   %s = %s\n", (*entry).name, (*entry).value);
[5020]246      }
247  }
248  fclose(stream);
249}
250
[5945]251void IniParser::setFileComment(const char* fileComment)
252{
[5946]253  if (this->comment != NULL)
254    delete this->comment;
[5933]255
[5946]256  if (fileComment != NULL)
257  {
258    this->comment = new char[strlen(fileComment)+1];
259    strcpy(this->comment, fileComment);
260  }
261  else
262    this->comment = NULL;
[5945]263}
264
265
[5021]266/**
[5934]267 * @brief adds a section to the list of Sections,
[5021]268 * if no Section list is availiable, it will create it
269 * @param sectionName the Name of the section to add
270 * @return true on success... there is only success or segfault :)
271 */
[5020]272bool IniParser::addSection(const char* sectionName)
273{
[5933]274  this->sections.push_back(IniSection());
[5946]275  this->sections.back().comment = NULL;
[5933]276  this->sections.back().name = new char[strlen(sectionName)+1];
277  strcpy(this->sections.back().name, sectionName);
278
279  this->currentSection = --this->sections.end();
[5934]280  if (!this->sections.empty())
[5936]281      this->currentEntry = (*this->currentSection).entries.begin();
[5031]282  PRINTF(5)("Added Section %s\n", sectionName);
[5021]283  return true;
[5020]284}
285
[5933]286
[5020]287/**
[5934]288 * @brief Set the parsing cursor to the specified section
[5014]289 * @param sectionName: the name of the section to set the cursor to
290 * @return true on success or false if the section could not be found
[5936]291 */
292bool IniParser::getSection(const char* sectionName)
[2064]293{
[5933]294  std::list<IniSection>::iterator section;
295  for (section = this->sections.begin(); section != this->sections.end(); section++)
296    if (!strcmp((*section).name, sectionName))
[5934]297      {
298        this->currentSection = section;
299        this->currentEntry = (*this->currentSection).entries.begin();
300        return true;
301      }
[5014]302  return false;
303}
[4597]304
[5933]305
[5945]306void IniParser::setSectionComment(const char* comment, const char* sectionName)
307{
308
309}
310
311
312const char* IniParser::getSectionComment(const char* sectionName) const
313{
314
315}
316
317
[5014]318/**
[5934]319 * @brief moves to the first section
[5015]320 */
[5936]321void IniParser::firstSection()
[5015]322{
[5933]323  this->currentSection = this->sections.begin();
[5934]324  if (!this->sections.empty())
325    this->currentEntry = (*this->currentSection).entries.begin();
[5015]326}
327
[5933]328
[5015]329/**
[5934]330 * @brief searches the next section
[5014]331 * @returns the name of the section if found, NULL otherwise
332 */
333const char* IniParser::nextSection()
334{
[5933]335  if (this->currentSection == this->sections.end())
[5014]336    return NULL;
[5015]337
[5936]338  this->currentSection++;
339
[5934]340  if (this->currentSection != this->sections.end())
341    {
342      this->currentEntry = (*this->currentSection).entries.begin();
343      return this->currentSection->name;
344    }
[5014]345  else
346    return NULL;
[2064]347}
348
[5933]349
[2141]350/**
[5934]351 * @brief adds a new Entry to either the currentSection or the section called by sectionName
[5020]352 * @param entryName the Name of the Entry to add
353 * @param value the value to assign to this entry
354 * @param sectionName if NULL then this entry will be set to the currentSection
355 * otherwise to the section refered to by sectionName.
356 * If both are NULL no entry will be added
357 * @return true if everything is ok false on error
358 */
359bool IniParser::addVar(const char* entryName, const char* value, const char* sectionName)
360{
[5934]361  std::list<IniSection>::iterator section;
[5944]362
[5020]363  if (sectionName != NULL)
364  {
[5933]365    for (section = this->sections.begin(); section != this->sections.end(); section++)
366      if (!strcmp((*section).name, sectionName))
[5020]367        break;
368  }
369  else
[5933]370    section = this->currentSection;
[5945]371
[5936]372  if (section == this->sections.end())
373    return false;
[5020]374
[5933]375  if (section == this->sections.end())
[5020]376  {
[5934]377    PRINTF(2)("section '%s' not found for value '%s'\n", sectionName, entryName);
[5020]378    return false;
379  }
380  else
381  {
[5933]382    (*section).entries.push_back(IniEntry());
[5946]383    (*section).entries.back().comment = NULL;
[5938]384    (*section).entries.back().name = new char[strlen(entryName)+1];
[5933]385    strcpy((*section).entries.back().name, entryName);
386    (*section).entries.back().value = new char[strlen(value)+1];
387    strcpy((*section).entries.back().value, value);
[5936]388    PRINTF(5)("Added Entry %s with Value '%s' to Section %s\n",
[5945]389              (*section).entries.back().name,
390              (*section).entries.back().value,
391              (*section).name);
[5946]392    this->currentEntry = --(*section).entries.end();
[5020]393    return true;
394  }
395}
396
[5933]397
[5020]398/**
[5934]399 * @brief directly acesses an entry in a section
[5014]400 * @param entryName: the name of the entry to find
401 * @param sectionName: the section where the entry is to be found
402 * @param defaultValue: what should be returned in case the entry cannot be found
[4836]403 * @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
[5020]404 *
405 *  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
406 * lead to unwanted behaviour.
[2141]407*/
[5014]408const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
[2065]409{
[5945]410  if (this->fileName != NULL)
[5014]411  {
[5945]412    std::list<IniSection>::const_iterator section = this->getSectionIT(sectionName);
[5944]413
[5945]414  if (section == this->sections.end())
415    {
416      PRINTF(2)("Section %s that should be containing %s not found.\n", sectionName, entryName);
417      return (defaultValue);
418    }
[5934]419
420    std::list<IniEntry>::const_iterator entry;
421    for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
422      if (!strcmp((*entry).name, entryName))
[5945]423        return (*entry).value;
[5934]424    PRINTF(2)("Entry '%s' in section '%s' not found.\n", entryName, sectionName);
[5944]425
[5014]426  }
427  else
[5934]428    PRINTF(2)("%s not opened\n", fileName);
[5014]429
430  return defaultValue;
431
[2065]432}
[5014]433
[5935]434
[5945]435const char* IniParser::setEntryComment(const char* comment, const char* entryName, const char* sectionName)
436{
437
438
439}
440
441
442const char* IniParser::getEntryComment(const char* entryName, const char* sectionName) const
443{
444
445
446}
447
448
[5017]449/**
[5945]450 * @brief moves to the first Variable of the current Section
451 */
452void IniParser::firstVar()
453{
454  if (!this->sections.empty() &&
455       this->currentSection != this->sections.end())
456    this->currentEntry = (*this->currentSection).entries.begin();
457}
458
459
460/**
461 * @brief gets the next VarName = VarValue pair from the parsing stream
462 * @return true on success, false otherwise (in the latter case name and value will be NULL)
463 */
464bool IniParser::nextVar()
465{
466  if ( this->sections.empty()
467       || this->currentSection == this->sections.end()
468       || this->currentEntry == (*this->currentSection).entries.end())
469    return false;
470
471  this->currentEntry++;
472
473  if (this->currentEntry == (*this->currentSection).entries.end())
474    return false;
475  else
476    return true;
477}
478
479
480
481/**
[5944]482 * @returns the name of the Current selected Section
[5935]483 */
[5944]484const char* IniParser::getCurrentSection() const
[5935]485{
[5936]486  if (!this->sections.empty() &&
[5944]487      this->currentSection != this->sections.end())
[5936]488    return this->currentSection->name;
489  else
490    return NULL;
[5935]491 }
492
493
[5944]494/**
495 * @returns the current entries Name, or NULL if we havn't selected a Entry
[5935]496 */
497const char* IniParser::getCurrentName() const
498{
499 if (!this->sections.empty() &&
[5936]500     this->currentSection != this->sections.end() &&
[5935]501     this->currentEntry != (*this->currentSection).entries.end())
502   return (*this->currentEntry).name;
503 else
504   return NULL;
505}
506
507/**
[5944]508 * @returns the current entries Value, or NULL if we havn't selected a Entry
[5935]509 */
[5944]510const char* IniParser::getCurrentValue() const
[5935]511{
[5936]512  if (!this->sections.empty() &&
513      this->currentSection != this->sections.end() &&
514      this->currentEntry != (*this->currentSection).entries.end())
[5935]515    return (*this->currentEntry).value;
516  else
[5944]517    return NULL;
[5935]518}
519
520
[5945]521std::list<IniParser::IniSection>::const_iterator IniParser::getSectionIT(const char* sectionName) const
522{
523  std::list<IniSection>::const_iterator section;
524  if (sectionName != NULL)
525  {
526    for (section = this->sections.begin(); section != this->sections.end(); section++)
527    {
528      if (!strcmp((*section).name, sectionName))
529      {
530        break;
531      }
532    }
533  }
534  else
535    section = this->currentSection;
536
537  return section;
538}
539
540
541std::list<IniParser::IniEntry>::const_iterator IniParser::getEntryIT(const char* entryName, const char* sectionName) const
542{
543  if (entryName == NULL)
544    return this->currentEntry;
545
546}
547
548
549
[5946]550void IniParser::setFileComment()
551{
552  if (this->comment != NULL)
553    delete[] this->comment;
554
555  if (this->commentList.empty()) {
556    this->comment = NULL;
557    return;
558  }
559
560  unsigned int stringLength = 1;
561  std::list<char*>::iterator comment;
562  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
563    stringLength += strlen((*comment)) +1;
564
565  this->comment = new char[stringLength];
566  this->comment[0] = '\0';
567  while (!this->commentList.empty())
568  {
569    if (*this->comment != '\0')
570      strcat(this->comment, "\n");
571    strcat(this->comment, this->commentList.front());
572    delete[] this->commentList.front();
573    this->commentList.pop_front();
574    printf("this->comment:: %s\n", this->comment);
575  }
576}
577
578void IniParser::setSectionComment()
579{
580  if ((*this->currentSection).comment != NULL)
581    delete[] (*this->currentSection).comment;
582
583  if (this->commentList.empty()) {
584    (*this->currentSection).comment = NULL;
585    return;
586  }
587
588  unsigned int stringLength = 1;
589  std::list<char*>::iterator comment;
590  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
591    stringLength += strlen((*comment)) +1;
592
593  (*this->currentSection).comment = new char[stringLength];
594  (*this->currentSection).comment[0] = '\0';
595  while (!this->commentList.empty())
596  {
597    if (*(*this->currentSection).comment != '\0')
598      strcat((*this->currentSection).comment, "\n");
599    strcat((*this->currentSection).comment, this->commentList.front());
600    delete[] this->commentList.front();
601    this->commentList.pop_front();
602    printf("this->comment:: %s", (*this->currentSection).comment);
603  }
604}
605
606void IniParser::setEntryComment()
607{
608  if ((*this->currentEntry).comment != NULL)
609    delete[] (*this->currentEntry).comment;
610
611  if (this->commentList.empty()) {
612    (*this->currentEntry).comment = NULL;
613    return;
614  }
615
616  unsigned int stringLength = 1;
617  std::list<char*>::iterator comment;
618  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
619    stringLength += strlen((*comment)) +1;
620
621  (*this->currentEntry).comment = new char[stringLength];
622  (*this->currentEntry).comment[0] = '\0';
623  while (!this->commentList.empty())
624  {
625    if (*(*this->currentEntry).comment != '\0')
626      strcat((*this->currentEntry).comment, "\n");
627    strcat((*this->currentEntry).comment, this->commentList.front());
628    delete[] this->commentList.front();
629    this->commentList.pop_front();
630    printf("=======this->comment:: %s\n", (*this->currentEntry).comment);
631  }
632
633}
634
635
[5935]636/**
[5934]637 * @brief output the whole tree in a nice and easy way.
[5017]638 */
[5014]639void IniParser::debug() const
640{
[5031]641  PRINTF(0)("Iniparser %s - debug\n", this->fileName);
[5946]642  if (this->comment != NULL)
643    PRINTF(0)("FileComment:\n %s\n\n", this->comment);
644
[5933]645  if (this->fileName != NULL)
[5014]646  {
[5933]647    std::list<IniSection>::const_iterator section;
648    for (section = this->sections.begin(); section != this->sections.end(); section++)
[5014]649    {
[5946]650      if ((*section).comment != NULL)
651        PRINTF(0)(" %s\n", (*section).comment);
[5933]652      PRINTF(0)(" [%s]\n", (*section).name);
[5014]653
[5933]654      std::list<IniEntry>::const_iterator entry;
655      for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
[5946]656      {
657        if ((*entry).comment != NULL)
658          PRINTF(0)(" %s\n", (*entry).comment);
[5933]659        PRINTF(0)("   '%s' -> '%s'\n", (*entry).name, (*entry).value);
[5946]660      }
[5014]661    }
662  }
663  else
[5933]664    PRINTF(1)("no opened ini-file.\n");
[5014]665}
[5938]666
Note: See TracBrowser for help on using the repository browser.