Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/preferences/src/lib/parser/ini_parser/ini_parser.cc @ 6388

Last change on this file since 6388 was 6388, checked in by rennerc, 19 years ago

reading and writing inifiles now works

File size: 23.2 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#if HAVE_CONFIG_H
27#include <config.h>
28#endif
29
30#ifdef DEBUG
31 #include "../../../defs/debug.h"
32#else
33 #define PRINTF(x) printf
34#endif
35
36using namespace std;
37
38/**
39 * @brief constructs an IniParser using a file
40 * @param fileName: the path and name of the file to parse
41 */
42IniParser::IniParser (const char* fileName)
43{
44  this->fileName = NULL;
45  this->comment = NULL;
46
47  if (fileName != NULL)
48    this->readFile(fileName);
49}
50
51
52/**
53 * @brief removes the IniParser from memory
54 */
55IniParser::~IniParser ()
56{
57  this->deleteSections();
58  this->setFileName(NULL);
59}
60
61
62/**
63 * @brief removes all the sections. This is like delete, but even cooler :)
64 */
65void IniParser::deleteSections()
66{
67  // in all sections
68  while(!this->sections.empty())
69  {
70     IniSection section = this->sections.front();
71
72    // in all entries of the sections
73    while(!section.entries.empty())
74    {
75      // delete all strings of entries.
76      IniEntry entry = section.entries.front();
77      delete[] entry.name;
78      delete[] entry.value;
79      delete[] entry.comment;
80      section.entries.pop_front();
81    }
82    // delete all Sections
83    delete[] section.name;
84    delete[] section.comment;
85    this->sections.pop_front();
86  }
87  this->currentSection = this->sections.end();
88  this->setFileName(NULL);
89}
90
91
92/**
93 * @brief sets the Name of the input-file
94 * @param fileName The new FileName to set to the IniParser
95 * If fileName is NULL the new Name will be set to NULL too.
96 */
97void IniParser::setFileName(const char* fileName)
98{
99  if (this->fileName != NULL)
100    delete[] this->fileName;
101  if  (this->comment != NULL)
102    delete[] this->comment;
103  this->comment = NULL;
104
105  if (fileName != NULL)
106  {
107    this->fileName = new char[strlen(fileName)+1];
108    strcpy(this->fileName, fileName);
109  }
110  else
111    this->fileName = NULL;
112}
113
114
115/**
116 * @brief opens a file to parse
117 * @param fileName: path and name of the new file to parse
118 * @return true on success false otherwise;
119 *
120 * If there was already an opened file, the file will be closed,
121 * and the new one will be opened.
122 */
123bool IniParser::readFile(const char* fileName)
124{
125  FILE*    stream;           //< The stream we use to read the file.
126  int      lineCount = 0;    //< The Count of lines.
127
128  if (this->fileName != NULL)
129    this->deleteSections();
130  if( fileName == NULL)
131    return false;
132
133  if( (stream = fopen (fileName, "r")) == NULL)
134  {
135    PRINTF(1)("IniParser could not open %s\n", fileName);
136    return false;
137  }
138  else
139  {
140    this->setFileName(fileName);
141
142    /////////////////////////////
143    // READING IN THE INI-FILE //
144    /////////////////////////////
145    char lineBuffer[PARSELINELENGHT];
146    char buffer[PARSELINELENGHT];
147    const char* lineBegin;
148    char* ptr;
149
150    while( fgets (lineBuffer, PARSELINELENGHT, stream))
151    {
152      lineBegin = lineBuffer;
153      // remove newline char, and \0-terminate
154      if( (ptr = strchr( lineBuffer, '\n')) != NULL)
155        *ptr = 0;
156      // cut up to the beginning of the line.
157      while((*lineBegin == ' ' || *lineBegin == '\t') && lineBegin < lineBuffer + strlen(lineBuffer))
158        ++lineBegin;
159
160      // check if we have a FileComment
161      if ( (*lineBegin == '#' || *lineBegin == ';'))
162      {
163        char* newCommenLine = new char[strlen(lineBegin)+1];
164        strcpy(newCommenLine, lineBegin);
165        this->commentList.push_back(newCommenLine);
166        continue;
167      }
168      if (lineCount == 0 && !this->commentList.empty())
169      {
170        this->setFileComment();
171        lineCount++;
172      }
173
174      // check for section identifyer
175      else if( sscanf (lineBegin, "[%s", buffer) == 1)
176      {
177        if( (ptr = strchr( buffer, ']')) != NULL)
178        {
179          *ptr = 0;
180          this->addSection(buffer);
181          this->setSectionComment();
182        }
183      }
184      // check for Entry identifier (Entry = Value)
185      else if( (ptr = strchr( lineBegin, '=')) != NULL)
186      {
187        if (currentSection == NULL)
188        {
189          PRINTF(2)("Not in a Section yet for %s\n", lineBegin);
190          lineCount++;
191          continue;
192        }
193        if( ptr == lineBegin) {
194          lineCount++;
195          continue;
196        }
197        char* valueBegin = ptr+1;
198        while ((*valueBegin == ' ' || *valueBegin == '\t') && valueBegin <= lineBegin + strlen(lineBegin))
199          ++valueBegin;
200        char* valueEnd = valueBegin + strlen(valueBegin)-1;
201        while ((*valueEnd == ' ' || *valueEnd == '\t') && valueEnd >= valueBegin)
202          --valueEnd;
203        valueEnd[1] = '\0';
204        char* nameEnd = ptr-1;
205        while ((*nameEnd == ' ' || *nameEnd == '\t' ) && nameEnd >= lineBegin)
206          --nameEnd;
207        nameEnd[1] = '\0';
208
209        this->addVar(lineBegin, valueBegin);
210        this->setEntryComment();
211
212        lineCount++;
213      }
214    }
215  }
216  this->currentSection = this->sections.begin();
217  if (!this->sections.empty())
218    this->currentEntry = (*this->currentSection).entries.begin();
219
220  fclose(stream);
221  return true;
222}
223
224
225/**
226 * @brief opens a file and writes to it
227 * @param fileName: path and name of the new file to write to
228 * @return true on success false otherwise
229 */
230bool IniParser::writeFile(const char* fileName) const
231{
232  FILE*    stream;           //!< The stream we use to read the file.
233  if( fileName == NULL && (fileName = this->fileName) == NULL )
234    return false;
235
236  if( (stream = fopen (fileName, "w")) == NULL)
237  {
238    PRINTF(1)("IniParser could not open %s\n", fileName);
239    return false;
240  }
241  else
242  {
243    if (this->comment != NULL)
244      fprintf(stream, "%s\n\n", this->comment);
245
246    std::list<IniSection>::const_iterator section;
247    for (section = this->sections.begin(); section != this->sections.end(); section++)
248      {
249        if ((*section).comment != NULL)
250          fprintf(stream, "%s", (*section).comment);
251        fprintf(stream, "\n [%s]\n", (*section).name);
252
253        std::list<IniEntry>::const_iterator entry;
254        for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
255        {
256          if ((*entry).comment != NULL)
257            fprintf(stream, "%s", (*entry).comment);
258          fprintf(stream, "   %s = %s\n", (*entry).name, (*entry).value);
259         }
260      }
261  }
262  fclose(stream);
263}
264
265void IniParser::setFileComment(const char* fileComment)
266{
267  if (this->comment != NULL)
268    delete this->comment;
269
270  if (fileComment != NULL)
271  {
272    this->comment = new char[strlen(fileComment)+1];
273    strcpy(this->comment, fileComment);
274  }
275  else
276    this->comment = NULL;
277}
278
279
280/**
281 * @brief adds a section to the list of Sections,
282 * if no Section list is availiable, it will create it
283 * @param sectionName the Name of the section to add
284 * @return true on success... there is only success or segfault :)
285 */
286bool IniParser::addSection(const char* sectionName)
287{
288  if (sectionName == NULL)
289    return false;
290  this->sections.push_back(IniSection());
291  this->sections.back().comment = NULL;
292  this->sections.back().name = new char[strlen(sectionName)+1];
293  strcpy(this->sections.back().name, sectionName);
294
295  this->currentSection = --this->sections.end();
296  if (!this->sections.empty())
297      this->currentEntry = (*this->currentSection).entries.begin();
298  PRINTF(5)("Added Section %s\n", sectionName);
299  return true;
300}
301
302
303/**
304 * @brief Set the parsing cursor to the specified section
305 * @param sectionName: the name of the section to set the cursor to
306 * @return true on success or false if the section could not be found
307 */
308bool IniParser::getSection(const char* sectionName)
309{
310  this->currentSection = this->getSectionIT(sectionName);
311  if (this->currentSection != this->sections.end())
312  {
313    this->currentEntry = (*this->currentSection).entries.begin();
314    return true;
315  }
316  else
317    return false;
318}
319
320/**
321 *
322 */
323void IniParser::setSectionComment(const char* comment, const char* sectionName)
324{
325  std::list<IniSection>::iterator section = this->getSectionIT(sectionName);
326  if (section == this->sections.end())
327    return;
328
329  if ((*section).comment != NULL)
330    delete[] (*section).comment;
331  if (comment != NULL)
332  {
333    (*section).comment = new char[strlen (comment)+1];
334    strcpy((*section).comment, comment);
335  }
336  else
337    (*section).comment = NULL;
338}
339
340/**
341 * @param sectionName the Section to query for
342 * @returns the Comment, or NULL on error.
343 */
344const char* IniParser::getSectionComment(const char* sectionName) const
345{
346  std::list<IniSection>::const_iterator section = this->getSectionIT(sectionName);
347  if (section != this->sections.end())
348    return (*section).comment;
349  else
350    return NULL;
351}
352
353
354/**
355 * @brief moves to the first section
356 */
357void IniParser::firstSection()
358{
359  this->currentSection = this->sections.begin();
360  if (!this->sections.empty())
361    this->currentEntry = (*this->currentSection).entries.begin();
362}
363
364
365/**
366 * @brief searches the next section
367 * @returns the name of the section if found, NULL otherwise
368 */
369const char* IniParser::nextSection()
370{
371  if (this->currentSection == this->sections.end())
372    return NULL;
373
374  this->currentSection++;
375
376  if (this->currentSection != this->sections.end())
377    {
378      this->currentEntry = (*this->currentSection).entries.begin();
379      return this->currentSection->name;
380    }
381  else
382    return NULL;
383}
384
385
386/**
387 * @brief adds a new Entry to either the currentSection or the section called by sectionName
388 * @param entryName the Name of the Entry to add
389 * @param value the value to assign to this entry
390 * @param sectionName if NULL then this entry will be set to the currentSection
391 * otherwise to the section refered to by sectionName.
392 * If both are NULL no entry will be added
393 * @return true if everything is ok false on error
394 */
395bool IniParser::addVar(const char* entryName, const char* value, const char* sectionName)
396{
397  std::list<IniSection>::iterator section;
398
399  if (sectionName != NULL)
400  {
401    for (section = this->sections.begin(); section != this->sections.end(); section++)
402      if (!strcmp((*section).name, sectionName))
403        break;
404  }
405  else
406    section = this->currentSection;
407
408  if (section == this->sections.end())
409    return false;
410
411  if (section == this->sections.end())
412  {
413    PRINTF(2)("section '%s' not found for value '%s'\n", sectionName, entryName);
414    return false;
415  }
416  else
417  {
418    (*section).entries.push_back(IniEntry());
419    (*section).entries.back().comment = NULL;
420    (*section).entries.back().name = new char[strlen(entryName)+1];
421    strcpy((*section).entries.back().name, entryName);
422    (*section).entries.back().value = new char[strlen(value)+1];
423    strcpy((*section).entries.back().value, value);
424    PRINTF(5)("Added Entry %s with Value '%s' to Section %s\n",
425              (*section).entries.back().name,
426              (*section).entries.back().value,
427              (*section).name);
428    this->currentEntry = --(*section).entries.end();
429    return true;
430  }
431}
432
433/**
434 * @brief edits the entry speciefied by entryName in sectionName/currentSection or creates it if it doesn't exist
435 * @param entryName the Name of the Entry to add
436 * @param value the value to assign to this entry
437 * @param sectionName if NULL then this entry will be set to the currentSection
438 * otherwise to the section refered to by sectionName.
439 * If both are NULL no entry will be added
440 * @return true if everything is ok false on error
441 */
442bool IniParser::editVar(const char* entryName, const char* value, const char* sectionName)
443{
444  std::list<IniSection>::iterator section;
445
446  if (sectionName != NULL)
447  {
448    for (section = this->sections.begin(); section != this->sections.end(); section++)
449      if (!strcmp((*section).name, sectionName))
450        break;
451  }
452  else
453    section = this->currentSection;
454
455  if (section == this->sections.end())
456  {
457    assert( sectionName != NULL );
458
459    IniSection sec;
460    sec.comment = NULL;
461    sec.name = new char[strlen(sectionName)+1];
462    strcpy(sec.name, sectionName);
463    section = this->sections.insert(this->sections.end(), sec);
464  }
465
466  if (section == this->sections.end())
467  {
468    PRINTF(2)("section '%s' not found for value '%s'\n", sectionName, entryName);
469    return false;
470  }
471  else
472  {
473    //try find item
474    std::list<IniEntry>::iterator entry;
475    for (entry = section->entries.begin(); entry!=section->entries.end(); entry++)
476      if (!strcmp( entry->name, entryName ))
477        break;
478
479    //found it?
480    if ( entry != section->entries.end() )
481    {
482      if ( entry->value != NULL )
483      {
484        delete[] entry->value;
485      }
486      entry->value = new char[strlen(value)+1];
487      strcpy(entry->value, value);
488
489      return true;
490    }
491
492    //not found -> create it
493    (*section).entries.push_back(IniEntry());
494    (*section).entries.back().comment = NULL;
495    (*section).entries.back().name = new char[strlen(entryName)+1];
496    strcpy((*section).entries.back().name, entryName);
497    (*section).entries.back().value = new char[strlen(value)+1];
498    strcpy((*section).entries.back().value, value);
499    PRINTF(5)("Added Entry %s with Value '%s' to Section %s\n",
500    (*section).entries.back().name,
501    (*section).entries.back().value,
502    (*section).name);
503    this->currentEntry = --(*section).entries.end();
504    return true;
505  }
506}
507
508
509/**
510 * @brief directly acesses an entry in a section
511 * @param entryName: the name of the entry to find
512 * @param sectionName: the section where the entry is to be found
513 * @param defaultValue: what should be returned in case the entry cannot be found
514 * @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
515 *
516 *  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
517 * lead to unwanted behaviour.
518*/
519const char* IniParser::getVar(const char* entryName, const char* sectionName, const char* defaultValue) const
520{
521  if (this->fileName != NULL)
522  {
523    std::list<IniEntry>::const_iterator entry = this->getEntryIT(entryName, sectionName);
524    if (entry != NULL &&  !strcmp((*entry).name, entryName))
525      return (*entry).value;
526    PRINTF(2)("Entry '%s' in section '%s' not found.\n", entryName, sectionName);
527
528  }
529  else
530    PRINTF(2)("no File opened\n");
531
532  return defaultValue;
533
534}
535
536/**
537 * Set the Comment of a specified Entry.
538 * @param comment the Comment to set
539 * @param entryName the Name of the Entry
540 * @param sectionName the Name of the Section
541 */
542void IniParser::setEntryComment(const char* comment, const char* entryName, const char* sectionName)
543{
544  std::list<IniEntry>::iterator entry = this->getEntryIT(entryName, sectionName);
545
546  if ((*entry).comment != NULL)
547    delete[] (*entry).comment;
548  if (comment != NULL)
549  {
550    (*entry).comment = new char[strlen (comment)+1];
551    strcpy((*entry).comment, comment);
552  }
553  else
554    (*entry).comment = NULL;
555
556
557}
558
559/**
560 * @param entryName the Entry to query for
561 * @param sectionName the Section to Query for
562 * @returns the queried Comment.
563 */
564const char* IniParser::getEntryComment(const char* entryName, const char* sectionName) const
565{
566  std::list<IniEntry>::const_iterator entry = this->getEntryIT(entryName, sectionName);
567
568  return (*entry).comment;
569}
570
571
572/**
573 * @brief moves to the first Variable of the current Section
574 */
575void IniParser::firstVar()
576{
577  if (!this->sections.empty() &&
578       this->currentSection != this->sections.end())
579    this->currentEntry = (*this->currentSection).entries.begin();
580}
581
582
583/**
584 * @brief gets the next VarName = VarValue pair from the parsing stream
585 * @return true on success, false otherwise (in the latter case name and value will be NULL)
586 */
587bool IniParser::nextVar()
588{
589  if ( this->sections.empty()
590       || this->currentSection == this->sections.end()
591       || this->currentEntry == (*this->currentSection).entries.end())
592    return false;
593
594  this->currentEntry++;
595
596  if (this->currentEntry == (*this->currentSection).entries.end())
597    return false;
598  else
599    return true;
600}
601
602
603
604/**
605 * @returns the name of the Current selected Section
606 */
607const char* IniParser::getCurrentSection() const
608{
609  if (!this->sections.empty() &&
610      this->currentSection != this->sections.end())
611    return this->currentSection->name;
612  else
613    return NULL;
614 }
615
616
617/**
618 * @returns the current entries Name, or NULL if we havn't selected a Entry
619 */
620const char* IniParser::getCurrentName() const
621{
622 if (!this->sections.empty() &&
623     this->currentSection != this->sections.end() &&
624     this->currentEntry != (*this->currentSection).entries.end())
625   return (*this->currentEntry).name;
626 else
627   return NULL;
628}
629
630/**
631 * @returns the current entries Value, or NULL if we havn't selected a Entry
632 */
633const char* IniParser::getCurrentValue() const
634{
635  if (!this->sections.empty() &&
636      this->currentSection != this->sections.end() &&
637      this->currentEntry != (*this->currentSection).entries.end())
638    return (*this->currentEntry).value;
639  else
640    return NULL;
641}
642
643
644/**
645 * Finds the Section Iterator of the Section Called sectionName
646 * @param sectionName the Name of the Section to get the Iterator from
647 */
648std::list<IniParser::IniSection>::const_iterator IniParser::getSectionIT(const char* sectionName) const
649{
650  std::list<IniSection>::const_iterator section = this->currentSection;
651  if (sectionName == NULL)
652    return this->currentSection;
653  else
654    for (section = this->sections.begin(); section != this->sections.end(); section++)
655      if (!strcmp((*section).name, sectionName))
656        break;
657  return section;
658}
659
660
661/**
662 * Finds the Section Iterator of the Section Called sectionName
663 * @param sectionName the Name of the Section to get the Iterator from
664 */
665std::list<IniParser::IniSection>::iterator IniParser::getSectionIT(const char* sectionName)
666{
667  std::list<IniSection>::iterator section = this->currentSection;
668  if (sectionName == NULL)
669    return this->currentSection;
670  else
671    for (section = this->sections.begin(); section != this->sections.end(); section++)
672      if (!strcmp((*section).name, sectionName))
673        break;
674  return section;
675}
676
677
678/**
679 * Finds the Entry Iterator of the Section Called sectionName and entry called EntryName
680 * @param entryName the Name of the Entry to get the Iterator from
681 * @param sectionName the Name of the Section to get the Iterator from
682 */
683std::list<IniParser::IniEntry>::const_iterator IniParser::getEntryIT(const char* entryName, const char* sectionName) const
684{
685  if (entryName == NULL)
686    return this->currentEntry;
687  std::list<IniSection>::const_iterator section = this->getSectionIT(sectionName);
688  std::list<IniEntry>::const_iterator entry = this->currentEntry;
689
690  if (section != this->sections.end())
691    for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
692      if (!strcmp((*entry).name, entryName))
693        break;
694  if (entry == (*section).entries.end())
695    return NULL;
696  else
697    return entry;
698}
699
700
701/**
702 * Finds the Entry Iterator of the Section Called sectionName and entry called EntryName
703 * @param entryName the Name of the Entry to get the Iterator from
704 * @param sectionName the Name of the Section to get the Iterator from
705 */
706std::list<IniParser::IniEntry>::iterator IniParser::getEntryIT(const char* entryName, const char* sectionName)
707{
708  if (entryName == NULL)
709    return this->currentEntry;
710  std::list<IniSection>::iterator section = this->getSectionIT(sectionName);
711  std::list<IniEntry>::iterator entry = this->currentEntry;
712
713  if (section != this->sections.end())
714    for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
715      if (!strcmp((*entry).name, entryName))
716        break;
717  if (entry == (*section).entries.end())
718    return NULL;
719  else
720    return entry;
721}
722
723
724/**
725 * takes lines together to form one FileComment, ereasing the commentList
726 */
727void IniParser::setFileComment()
728{
729  if (this->comment != NULL)
730    delete[] this->comment;
731
732  if (this->commentList.empty()) {
733    this->comment = NULL;
734    return;
735  }
736
737  unsigned int stringLength = 1;
738  std::list<char*>::iterator comment;
739  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
740    stringLength += strlen((*comment)) +1;
741
742  this->comment = new char[stringLength];
743  this->comment[0] = '\0';
744  while (!this->commentList.empty())
745  {
746    if (*this->comment != '\0')
747      strcat(this->comment, "\n");
748    strcat(this->comment, this->commentList.front());
749    delete[] this->commentList.front();
750    this->commentList.pop_front();
751  }
752}
753
754/**
755 * takes lines together to form one SectionComment, ereasing the commentList
756 */
757void IniParser::setSectionComment()
758{
759  if ((*this->currentSection).comment != NULL)
760    delete[] (*this->currentSection).comment;
761
762  if (this->commentList.empty()) {
763    (*this->currentSection).comment = NULL;
764    return;
765  }
766
767  unsigned int stringLength = 1;
768  std::list<char*>::iterator comment;
769  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
770    stringLength += strlen((*comment)) +1;
771
772  (*this->currentSection).comment = new char[stringLength];
773  (*this->currentSection).comment[0] = '\0';
774  while (!this->commentList.empty())
775  {
776    if (*(*this->currentSection).comment != '\0')
777      strcat((*this->currentSection).comment, "\n");
778    strcat((*this->currentSection).comment, this->commentList.front());
779    delete[] this->commentList.front();
780    this->commentList.pop_front();
781  }
782}
783
784/**
785 * takes lines together to form one EntryComment, ereasing the commentList
786 */
787void IniParser::setEntryComment()
788{
789  if ((*this->currentEntry).comment != NULL)
790    delete[] (*this->currentEntry).comment;
791
792  if (this->commentList.empty()) {
793    (*this->currentEntry).comment = NULL;
794    return;
795  }
796
797  unsigned int stringLength = 1;
798  std::list<char*>::iterator comment;
799  for (comment = this->commentList.begin(); comment != this->commentList.end(); comment++)
800    stringLength += strlen((*comment)) +1;
801
802  (*this->currentEntry).comment = new char[stringLength];
803  (*this->currentEntry).comment[0] = '\0';
804  while (!this->commentList.empty())
805  {
806    if (*(*this->currentEntry).comment != '\0')
807      strcat((*this->currentEntry).comment, "\n");
808    strcat((*this->currentEntry).comment, this->commentList.front());
809    delete[] this->commentList.front();
810    this->commentList.pop_front();
811  }
812
813}
814
815
816/**
817 * @brief output the whole tree in a nice and easy way.
818 */
819void IniParser::debug() const
820{
821  PRINTF(0)("Iniparser %s - debug\n", this->fileName);
822  if (this->comment != NULL)
823    PRINTF(0)("FileComment:\n %s\n\n", this->comment);
824
825  if (this->fileName != NULL)
826  {
827    std::list<IniSection>::const_iterator section;
828    for (section = this->sections.begin(); section != this->sections.end(); section++)
829    {
830      if ((*section).comment != NULL)
831        PRINTF(0)(" %s\n", (*section).comment);
832      PRINTF(0)(" [%s]\n", (*section).name);
833
834      std::list<IniEntry>::const_iterator entry;
835      for (entry = (*section).entries.begin(); entry != (*section).entries.end(); entry++)
836      {
837        if ((*entry).comment != NULL)
838          PRINTF(0)(" %s\n", (*entry).comment);
839        PRINTF(0)("   '%s' -> '%s'\n", (*entry).name, (*entry).value);
840      }
841    }
842  }
843  else
844    PRINTF(1)("no opened ini-file.\n");
845}
846
Note: See TracBrowser for help on using the repository browser.