INI Parser

As a current project, I’m developing a small game in C++ using the SDL API, the project is going well, so I thought I’d share some code. The following is a small parser to parse the game settings file. Target syntax for the INI file is within the header comment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
 * Parse and replace (set) settings within settings.ini
 * Syntax of settings.ini, command = value, ; comment
 *
 * @author  reZo <reZo@rezolabs.com>
 * @license GNU GPL (latest version)
 */
 
class Settings {
 
   private:
      // settings map to store command / value
      std::map<std::string, std::string> settings;
      // input file descriptor
      std::ifstream iSettings;
      // output file descriptor
      std::ofstream oSettings;
      // filename
      std::string filename;
      void parse (std::string line);
 
   public:
      void load (std::string file);
      void set (std::string command, std::string value);
      std::string get (std::string command);
} Settings;
 
/**
 * Open file for parsing
 *
 * @param std::string file filename to open
 */
 
void Settings::load (std::string file) {
 
   std::string line;
   filename = file;
 
   iSettings.open (filename.data(), std::ios::in);
 
   if (!iSettings.is_open())
      return;
 
   while (!iSettings.eof()) {
      getline (iSettings, line);
      parse (line);
   }
 
   iSettings.close();
}
 
/**
 * Get value from settings map<std::string, std::string>
 *
 * @param  std::string commmand name of command of which value to return
 * @return std::string value
 */
 
std::string Settings::get (std::string command) {
 
   return settings[command];
}
 
/**
 * Use iterator object from map object to compare command index std::string
 *
 * @param std::string command holds command to change value of
 * @param std::string value   value command will be replaced with
 */
 
void Settings::set (std::string command, std::string value) {
 
   oSettings.open (filename.data(), std::ios::out);
 
   std::map<std::string, std::string>::iterator line;
 
   for (line = settings.begin(); line != settings.end(); line++) {
      if (((*line).first).compare(command) == 0)
         oSettings << command  << " = " << value;
      else
         oSettings << (*line).first << " = " << (*line).second << "\n";
   }
 
   settings[command] = value;
 
   oSettings.close();
}
 
/**
 * Parse command and value from @param std::string line into settings map<std::string,
 * std::string>
 *
 * @param std::string line the line to parse
 *
 * Uses ; for comment
 */
 
void Settings::parse (std::string line) {
 
   if (line.substr(0, 1).compare(";") == 0 || line.compare("") == 0)
      return;
 
   std::string command, value;
   std::string::size_type location;
 
   location = line.find (" = ", 0);
 
   if (location != std::string::npos) {
      command = line.substr(0, location);
      value = line.substr(location + 3, line.length());
   }
 
   settings[command] = value;
}

  1. Eric Nitzsche on February 25th, 2009

    I implemented almost exactly the same code earlier this week, and found your code belatedly after doing a “.ini std::map” google search.

    The similarity is quite shocking, though I did include sections by using a secondary map to implement sections:

    typedef std::map INI_MAP_TYPE;
    typedef std::map MAP_OF_MAPS_TYPE;

    It’s worth noting that you are searching for ” = ” instead of “=” in .parse(), which won’t work for normal .ini files.

Feedback