Mercurial > audlegacy-plugins
comparison src/projectm-1.0/ConfigFile.h @ 1920:a6d84a2cfaa7
projectm-1.0: add the new files this time
| author | Kieran Clancy <clancy.kieran+audacious@gmail.com> |
|---|---|
| date | Sun, 30 Sep 2007 13:46:31 +0930 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1919:266f1bf0d5fc | 1920:a6d84a2cfaa7 |
|---|---|
| 1 // ConfigFile.h | |
| 2 // Class for reading named values from configuration files | |
| 3 // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu | |
| 4 | |
| 5 // Copyright (c) 2004 Richard J. Wagner | |
| 6 // | |
| 7 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 8 // of this software and associated documentation files (the "Software"), to | |
| 9 // deal in the Software without restriction, including without limitation the | |
| 10 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
| 11 // sell copies of the Software, and to permit persons to whom the Software is | |
| 12 // furnished to do so, subject to the following conditions: | |
| 13 // | |
| 14 // The above copyright notice and this permission notice shall be included in | |
| 15 // all copies or substantial portions of the Software. | |
| 16 // | |
| 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 23 // IN THE SOFTWARE. | |
| 24 | |
| 25 // Typical usage | |
| 26 // ------------- | |
| 27 // | |
| 28 // Given a configuration file "settings.inp": | |
| 29 // atoms = 25 | |
| 30 // length = 8.0 # nanometers | |
| 31 // name = Reece Surcher | |
| 32 // | |
| 33 // Named values are read in various ways, with or without default values: | |
| 34 // ConfigFile config( "settings.inp" ); | |
| 35 // int atoms = config.read<int>( "atoms" ); | |
| 36 // double length = config.read( "length", 10.0 ); | |
| 37 // string author, title; | |
| 38 // config.readInto( author, "name" ); | |
| 39 // config.readInto( title, "title", string("Untitled") ); | |
| 40 // | |
| 41 // See file example.cpp for more examples. | |
| 42 | |
| 43 #ifndef CONFIGFILE_H | |
| 44 #define CONFIGFILE_H | |
| 45 | |
| 46 #include <string> | |
| 47 #include <map> | |
| 48 #include <iostream> | |
| 49 #include <fstream> | |
| 50 #include <sstream> | |
| 51 | |
| 52 using std::string; | |
| 53 | |
| 54 class ConfigFile { | |
| 55 // Data | |
| 56 protected: | |
| 57 string myDelimiter; // separator between key and value | |
| 58 string myComment; // separator between value and comments | |
| 59 string mySentry; // optional string to signal end of file | |
| 60 std::map<string,string> myContents; // extracted keys and values | |
| 61 | |
| 62 typedef std::map<string,string>::iterator mapi; | |
| 63 typedef std::map<string,string>::const_iterator mapci; | |
| 64 | |
| 65 // Methods | |
| 66 public: | |
| 67 ConfigFile( string filename, | |
| 68 string delimiter = "=", | |
| 69 string comment = "#", | |
| 70 string sentry = "EndConfigFile" ); | |
| 71 ConfigFile(); | |
| 72 | |
| 73 // Search for key and read value or optional default value | |
| 74 template<class T> T read( const string& key ) const; // call as read<T> | |
| 75 template<class T> T read( const string& key, const T& value ) const; | |
| 76 template<class T> bool readInto( T& var, const string& key ) const; | |
| 77 template<class T> | |
| 78 bool readInto( T& var, const string& key, const T& value ) const; | |
| 79 | |
| 80 // Modify keys and values | |
| 81 template<class T> void add( string key, const T& value ); | |
| 82 void remove( const string& key ); | |
| 83 | |
| 84 // Check whether key exists in configuration | |
| 85 bool keyExists( const string& key ) const; | |
| 86 | |
| 87 // Check or change configuration syntax | |
| 88 string getDelimiter() const { return myDelimiter; } | |
| 89 string getComment() const { return myComment; } | |
| 90 string getSentry() const { return mySentry; } | |
| 91 string setDelimiter( const string& s ) | |
| 92 { string old = myDelimiter; myDelimiter = s; return old; } | |
| 93 string setComment( const string& s ) | |
| 94 { string old = myComment; myComment = s; return old; } | |
| 95 | |
| 96 // Write or read configuration | |
| 97 friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ); | |
| 98 friend std::istream& operator>>( std::istream& is, ConfigFile& cf ); | |
| 99 | |
| 100 protected: | |
| 101 template<class T> static string T_as_string( const T& t ); | |
| 102 template<class T> static T string_as_T( const string& s ); | |
| 103 static void trim( string& s ); | |
| 104 | |
| 105 | |
| 106 // Exception types | |
| 107 public: | |
| 108 struct file_not_found { | |
| 109 string filename; | |
| 110 file_not_found( const string& filename_ = string() ) | |
| 111 : filename(filename_) {} }; | |
| 112 struct key_not_found { // thrown only by T read(key) variant of read() | |
| 113 string key; | |
| 114 key_not_found( const string& key_ = string() ) | |
| 115 : key(key_) {} }; | |
| 116 }; | |
| 117 | |
| 118 | |
| 119 /* static */ | |
| 120 template<class T> | |
| 121 string ConfigFile::T_as_string( const T& t ) | |
| 122 { | |
| 123 // Convert from a T to a string | |
| 124 // Type T must support << operator | |
| 125 std::ostringstream ost; | |
| 126 ost << t; | |
| 127 return ost.str(); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 /* static */ | |
| 132 template<class T> | |
| 133 T ConfigFile::string_as_T( const string& s ) | |
| 134 { | |
| 135 // Convert from a string to a T | |
| 136 // Type T must support >> operator | |
| 137 T t; | |
| 138 std::istringstream ist(s); | |
| 139 ist >> t; | |
| 140 return t; | |
| 141 } | |
| 142 | |
| 143 | |
| 144 /* static */ | |
| 145 template<> | |
| 146 inline string ConfigFile::string_as_T<string>( const string& s ) | |
| 147 { | |
| 148 // Convert from a string to a string | |
| 149 // In other words, do nothing | |
| 150 return s; | |
| 151 } | |
| 152 | |
| 153 | |
| 154 /* static */ | |
| 155 template<> | |
| 156 inline bool ConfigFile::string_as_T<bool>( const string& s ) | |
| 157 { | |
| 158 // Convert from a string to a bool | |
| 159 // Interpret "false", "F", "no", "n", "0" as false | |
| 160 // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true | |
| 161 bool b = true; | |
| 162 string sup = s; | |
| 163 for( string::iterator p = sup.begin(); p != sup.end(); ++p ) | |
| 164 *p = toupper(*p); // make string all caps | |
| 165 if( sup==string("FALSE") || sup==string("F") || | |
| 166 sup==string("NO") || sup==string("N") || | |
| 167 sup==string("0") || sup==string("NONE") ) | |
| 168 b = false; | |
| 169 return b; | |
| 170 } | |
| 171 | |
| 172 | |
| 173 template<class T> | |
| 174 T ConfigFile::read( const string& key ) const | |
| 175 { | |
| 176 // Read the value corresponding to key | |
| 177 mapci p = myContents.find(key); | |
| 178 if( p == myContents.end() ) throw key_not_found(key); | |
| 179 return string_as_T<T>( p->second ); | |
| 180 } | |
| 181 | |
| 182 | |
| 183 template<class T> | |
| 184 T ConfigFile::read( const string& key, const T& value ) const | |
| 185 { | |
| 186 // Return the value corresponding to key or given default value | |
| 187 // if key is not found | |
| 188 mapci p = myContents.find(key); | |
| 189 if( p == myContents.end() ) return value; | |
| 190 return string_as_T<T>( p->second ); | |
| 191 } | |
| 192 | |
| 193 | |
| 194 template<class T> | |
| 195 bool ConfigFile::readInto( T& var, const string& key ) const | |
| 196 { | |
| 197 // Get the value corresponding to key and store in var | |
| 198 // Return true if key is found | |
| 199 // Otherwise leave var untouched | |
| 200 mapci p = myContents.find(key); | |
| 201 bool found = ( p != myContents.end() ); | |
| 202 if( found ) var = string_as_T<T>( p->second ); | |
| 203 return found; | |
| 204 } | |
| 205 | |
| 206 | |
| 207 template<class T> | |
| 208 bool ConfigFile::readInto( T& var, const string& key, const T& value ) const | |
| 209 { | |
| 210 // Get the value corresponding to key and store in var | |
| 211 // Return true if key is found | |
| 212 // Otherwise set var to given default | |
| 213 mapci p = myContents.find(key); | |
| 214 bool found = ( p != myContents.end() ); | |
| 215 if( found ) | |
| 216 var = string_as_T<T>( p->second ); | |
| 217 else | |
| 218 var = value; | |
| 219 return found; | |
| 220 } | |
| 221 | |
| 222 | |
| 223 template<class T> | |
| 224 void ConfigFile::add( string key, const T& value ) | |
| 225 { | |
| 226 // Add a key with given value | |
| 227 string v = T_as_string( value ); | |
| 228 trim(key); | |
| 229 trim(v); | |
| 230 myContents[key] = v; | |
| 231 return; | |
| 232 } | |
| 233 | |
| 234 #endif // CONFIGFILE_H | |
| 235 | |
| 236 // Release notes: | |
| 237 // v1.0 21 May 1999 | |
| 238 // + First release | |
| 239 // + Template read() access only through non-member readConfigFile() | |
| 240 // + ConfigurationFileBool is only built-in helper class | |
| 241 // | |
| 242 // v2.0 3 May 2002 | |
| 243 // + Shortened name from ConfigurationFile to ConfigFile | |
| 244 // + Implemented template member functions | |
| 245 // + Changed default comment separator from % to # | |
| 246 // + Enabled reading of multiple-line values | |
| 247 // | |
| 248 // v2.1 24 May 2004 | |
| 249 // + Made template specializations inline to avoid compiler-dependent linkage | |
| 250 // + Allowed comments within multiple-line values | |
| 251 // + Enabled blank line termination for multiple-line values | |
| 252 // + Added optional sentry to detect end of configuration file | |
| 253 // + Rewrote messy trimWhitespace() function as elegant trim() |
