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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | #ifndef STLPLUS_INI_MANAGER #define STLPLUS_INI_MANAGER //////////////////////////////////////////////////////////////////////////////// // Author: Andy Rushton // Copyright: (c) Southampton University 1999-2004 // (c) Andy Rushton 2004 onwards // License: BSD License, see ../docs/license.html // A subsystem for managing INI (i.e. .ini) files // An INI file has the following format // file ::= header { section }* // header ::= { comment | blank }* // section ::= section_header { declaration | comment | blank }* // section_header ::= '[' title ']' '\n' // declaration ::= variable '=' value '\n' // comment ::= ';' text '\n' // blank ::= '\n' // title ::= [~']']* // variable ::= [~'=']* // value ::= .* // text ::= .* // Whitespace is trimmed from the leading and trailing ends of title, variable and value // Note: a header is represented internally as a Clint section (i.e. a section with no name) //////////////////////////////////////////////////////////////////////////////// #include "subsystems_fixes.hpp" #include <vector> #include <string> #include <iostream> namespace stlplus { //////////////////////////////////////////////////////////////////////////////// // Internals class ini_manager_body; //////////////////////////////////////////////////////////////////////////////// // Ini-file manager class class ini_manager { public : ini_manager( void ); explicit ini_manager( const std:: vector <std:: string >& filenames); ini_manager( const ini_manager&); ini_manager& operator = ( const ini_manager&); ~ini_manager( void ); ////////////////////////////////////////////////////////////////////////////// // file management // add files starting with the most local file (e.g. the current project) which has depth 0 // and working back to the most global (e.g. the installation settings) which has a depth of size()-1 // This does nothing if the file has already been loaded - it is not permitted to manage the same file twice. // Returns true if the file loaded okay or was already loaded (it is counted as successful if the file did // not exist, only read errors cause a failure) bool add_file( const std:: string & filename); // as above, returns false if *none* of the files were added // filenames[0] is the local file, and so on bool add_files( const std:: vector <std:: string >& filenames); // saves modified ini files - returns true if all modified files were written successfully bool save( void ); // get the number of files being managed unsigned size( void ) const ; // get the ini filename associated with a depth std:: string filename( unsigned depth = 0) const ; // test whether a file in the ini manager is writable bool writable( unsigned depth = 0) const ; // test whether a file is empty // An ini file is considered empty if it has no named sections and the header is empty or missing bool empty( unsigned depth = 0) const ; // erase the ini file from the ini manager and from the disk bool erase( unsigned depth = 0); // remove the file from the ini manager but do not erase it from the disk bool remove ( unsigned depth = 0); ////////////////////////////////////////////////////////////////////////////// // section management // returns the union of all section names in all of the ini files std:: vector <std:: string > section_names( void ) const ; // returns the section names in one of the ini files std:: vector <std:: string > section_names( unsigned depth) const ; // tests whether a section is found in any of the ini files bool section_exists( const std:: string & title) const ; // tests whether the section is found in the specific ini file bool section_exists( const std:: string & title, unsigned depth) const ; // adds a section to the specified ini file - does nothing if it is already present bool add_section( const std:: string & section, unsigned depth = 0); // test whether a section is empty bool empty_section( const std:: string & section, unsigned depth = 0); // removes a section from the specified ini file if it exists there but cannot remove it from any other file bool erase_section( const std:: string & section, unsigned depth = 0); // removes all the contents of a section from the specified ini file but keeps the empty section bool clear_section( const std:: string & section, unsigned depth = 0); ////////////////////////////////////////////////////////////////////////////// // variable management // test whether a variable exists in any of the ini files bool variable_exists( const std:: string & section, const std:: string variable) const ; // test whether a variable exists in specified ini file bool variable_exists( const std:: string & section, const std:: string variable, unsigned depth) const ; // get the union of all variables declared in all ini files std:: vector <std:: string > variable_names( const std:: string & section) const ; // get the set of all varaibale names from one file std:: vector <std:: string > variable_names( const std:: string & section, unsigned depth) const ; // get the depth of the first ini file to define a variable // returns 0 if defined in the local ini file, etc. Returns (unsigned)-1 if the variable doesn't exist unsigned variable_depth( const std:: string & section, const std:: string variable) const ; // get the filename that first defines the variable std:: string variable_filename( const std:: string & section, const std:: string variable) const ; // ditto for its linenumber within that file unsigned variable_linenumber( const std:: string & section, const std:: string variable) const ; // get the value of a variable as a single unprocessed string // if the variable does not exist the string will be empty, but beware that // you also get an empty string if a variable exists but has no value // you can differentiate between the two cases by using variable_exists_all above std:: string variable_value( const std:: string & section, const std:: string variable) const ; // get the value from the specified file std:: string variable_value( const std:: string & section, const std:: string variable, unsigned depth) const ; // get the value of a variable as a processed string // processing splits the value at commas and furthermore supports quoted strings (so that values can contain commas for example) // quoted strings are dequoted before they are added to the result // the result is a vector of dequoted strings, one per value in the comma-separated list std:: vector <std:: string > variable_values( const std:: string & section, const std:: string variable) const ; // get the processed variable from the specified file std:: vector <std:: string > variable_values( const std:: string & section, const std:: string variable, unsigned depth) const ; // add a variable to the specified file bool add_variable( const std:: string & section, const std:: string & variable, const std:: string & value, unsigned depth = 0); // add a variable as a processed string // processing means that the values in the string vector are converted into a comma-separated list // values containing reserved characters are automatically quoted - so you should not even try to quote them yourself bool add_variable( const std:: string & section, const std:: string & variable, const std:: vector <std:: string >& values, unsigned depth = 0); // erase a variable from the specified file // this does not remove the variable from other ini files, so the variable may still exist // to mask a global variable, set the variable to an empty string instead bool erase_variable( const std:: string & section, const std:: string & variable, unsigned depth = 0); ////////////////////////////////////////////////////////////////////////////// // sundry line-entry management // add a comment to the specified ini file bool add_comment( const std:: string & section, const std:: string & comment, unsigned depth = 0); // add a blank line to the specified ini file bool add_blank( const std:: string & section, unsigned depth = 0); bool print(std::ostream&) const ; private : friend class ini_manager_body; ini_manager_body* m_body; }; //////////////////////////////////////////////////////////////////////////////// // diagnostic print routine std::ostream& operator << (std::ostream&, const ini_manager&); //////////////////////////////////////////////////////////////////////////////// } // end namespace stlplus #endif |