Collection of DPF-based plugins for packaging
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
7.6KB

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