subsystems/ini_manager.hpp
1: #ifndef STLPLUS_INI_MANAGER
2: #define STLPLUS_INI_MANAGER
3: ////////////////////////////////////////////////////////////////////////////////
4:
5: // Author: Andy Rushton
6: // Copyright: (c) Andy Rushton, 2007
7: // License: BSD License, see ../docs/license.html
8:
9: // A subsystem for managing INI (i.e. .ini) files
10: // An INI file has the following format
11:
12: // file ::= header { section }*
13: // header ::= { comment | blank }*
14: // section ::= section_header { declaration | comment | blank }*
15: // section_header ::= '[' title ']' '\n'
16: // declaration ::= variable '=' value '\n'
17: // comment ::= ';' text '\n'
18: // blank ::= '\n'
19: // title ::= [~']']*
20: // variable ::= [~'=']*
21: // value ::= .*
22: // text ::= .*
23:
24: // Whitespace is trimmed from the leading and trailing ends of title, variable and value
25: // Note: a header is represented internally as a Clint section (i.e. a section with no name)
26:
27: ////////////////////////////////////////////////////////////////////////////////
28: #include "subsystems_fixes.hpp"
29: #include <vector>
30: #include <string>
31: #include <iostream>
32:
33: namespace stlplus
34: {
35:
36: ////////////////////////////////////////////////////////////////////////////////
37: // Internals
38:
39: class ini_manager_body;
40:
41: ////////////////////////////////////////////////////////////////////////////////
42: // Ini-file manager class
43:
44: class ini_manager
45: {
46: public:
47:
48: ini_manager(void);
49:
50: explicit ini_manager(const std::vector<std::string>& filenames);
51:
52: ini_manager(const ini_manager&);
53: ini_manager& operator= (const ini_manager&);
54:
55: ~ini_manager(void);
56:
57: //////////////////////////////////////////////////////////////////////////////
58: // file management
59:
60: // add files starting with the most local file (e.g. the current project) which has depth 0
61: // and working back to the most global (e.g. the installation settings) which has a depth of size()-1
62: // This does nothing if the file has already been loaded - it is not permitted to manage the same file twice.
63: // Returns true if the file loaded okay or was already loaded (it is counted as successful if the file did
64: // not exist, only read errors cause a failure)
65: bool add_file(const std::string& filename);
66:
67: // as above, returns false if *none* of the files were added
68: // filenames[0] is the local file, and so on
69: bool add_files(const std::vector<std::string>& filenames);
70:
71: // saves modified ini files - returns true if all modified files were written successfully
72: bool save(void);
73:
74: // get the number of files being managed
75: unsigned size(void) const;
76:
77: // get the ini filename associated with a depth
78: std::string filename(unsigned depth = 0) const;
79:
80: // test whether a file in the ini manager is writable
81: bool writable(unsigned depth = 0) const;
82:
83: // test whether a file is empty
84: // An ini file is considered empty if it has no named sections and the header is empty or missing
85: bool empty(unsigned depth = 0) const;
86:
87: // erase the ini file from the ini manager and from the disk
88: bool erase(unsigned depth = 0);
89:
90: // remove the file from the ini manager but do not erase it from the disk
91: bool remove(unsigned depth = 0);
92:
93: //////////////////////////////////////////////////////////////////////////////
94: // section management
95:
96: // returns the union of all section names in all of the ini files
97: std::vector<std::string> section_names(void) const;
98:
99: // returns the section names in one of the ini files
100: std::vector<std::string> section_names(unsigned depth) const;
101:
102: // tests whether a section is found in any of the ini files
103: bool section_exists(const std::string& title) const;
104:
105: // tests whether the section is found in the specific ini file
106: bool section_exists(const std::string& title, unsigned depth) const;
107:
108: // adds a section to the specified ini file - does nothing if it is already present
109: bool add_section(const std::string& section, unsigned depth = 0);
110:
111: // test whether a section is empty
112: bool empty_section(const std::string& section, unsigned depth = 0);
113:
114: // removes a section from the specified ini file if it exists there but cannot remove it from any other file
115: bool erase_section(const std::string& section, unsigned depth = 0);
116:
117: // removes all the contents of a section from the specified ini file but keeps the empty section
118: bool clear_section(const std::string& section, unsigned depth = 0);
119:
120: //////////////////////////////////////////////////////////////////////////////
121: // variable management
122:
123: // test whether a variable exists in any of the ini files
124: bool variable_exists(const std::string& section, const std::string variable) const;
125:
126: // test whether a variable exists in specified ini file
127: bool variable_exists(const std::string& section, const std::string variable, unsigned depth) const;
128:
129: // get the union of all variables declared in all ini files
130: std::vector<std::string> variable_names(const std::string& section) const;
131:
132: // get the set of all varaibale names from one file
133: std::vector<std::string> variable_names(const std::string& section, unsigned depth) const;
134:
135: // get the depth of the first ini file to define a variable
136: // returns 0 if defined in the local ini file, etc. Returns (unsigned)-1 if the variable doesn't exist
137: unsigned variable_depth(const std::string& section, const std::string variable) const;
138:
139: // get the filename that first defines the variable
140: std::string variable_filename(const std::string& section, const std::string variable) const;
141: // ditto for its linenumber within that file
142: unsigned variable_linenumber(const std::string& section, const std::string variable) const;
143:
144: // get the value of a variable as a single unprocessed string
145: // if the variable does not exist the string will be empty, but beware that
146: // you also get an empty string if a variable exists but has no value
147: // you can differentiate between the two cases by using variable_exists_all above
148: std::string variable_value(const std::string& section, const std::string variable) const;
149:
150: // get the value from the specified file
151: std::string variable_value(const std::string& section, const std::string variable, unsigned depth) const;
152:
153: // get the value of a variable as a processed string
154: // processing splits the value at commas and furthermore supports quoted strings (so that values can contain commas for example)
155: // quoted strings are dequoted before they are added to the result
156: // the result is a vector of dequoted strings, one per value in the comma-separated list
157: std::vector<std::string> variable_values(const std::string& section, const std::string variable) const;
158:
159: // get the processed variable from the specified file
160: std::vector<std::string> variable_values(const std::string& section, const std::string variable, unsigned depth) const;
161:
162: // add a variable to the specified file
163: bool add_variable(const std::string& section, const std::string& variable, const std::string& value, unsigned depth = 0);
164:
165: // add a variable as a processed string
166: // processing means that the values in the string vector are converted into a comma-separated list
167: // values containing reserved characters are automatically quoted - so you should not even try to quote them yourself
168: bool add_variable(const std::string& section, const std::string& variable, const std::vector<std::string>& values, unsigned depth = 0);
169:
170: // erase a variable from the specified file
171: // this does not remove the variable from other ini files, so the variable may still exist
172: // to mask a global variable, set the variable to an empty string instead
173: bool erase_variable(const std::string& section, const std::string& variable, unsigned depth = 0);
174:
175: //////////////////////////////////////////////////////////////////////////////
176: // sundry line-entry management
177:
178: // add a comment to the specified ini file
179: bool add_comment(const std::string& section, const std::string& comment, unsigned depth = 0);
180:
181: // add a blank line to the specified ini file
182: bool add_blank(const std::string& section, unsigned depth = 0);
183:
184: bool print(std::ostream&) const;
185:
186: private:
187: friend class ini_manager_body;
188: ini_manager_body* m_body;
189: };
190:
191: ////////////////////////////////////////////////////////////////////////////////
192: // diagnostic print routine
193:
194: std::ostream& operator << (std::ostream&, const ini_manager&);
195:
196: ////////////////////////////////////////////////////////////////////////////////
197:
198: } // end namespace stlplus
199:
200: #endif