转 源码分享:c++配置类

网上一个热心的大牛分享了一个c++配置类,如下:
Config.h 

[cpp]  view plain copy
  1. //Config.h    
  2. #pragma once    
  3.     
  4. #include <string>    
  5. #include <map>    
  6. #include <iostream>    
  7. #include <fstream>    
  8. #include <sstream>    
  9.     
  10.     
  11. /*  
  12. * \brief Generic configuration Class  
  13.  
  14. */    
  15. class Config {    
  16.     // Data    
  17. protected:    
  18.     std::string m_Delimiter;  //!< separator between key and value    
  19.     std::string m_Comment;    //!< separator between value and comments    
  20.     std::map<std::string,std::string> m_Contents;  //!< extracted keys and values    
  21.     
  22.     typedef std::map<std::string,std::string>::iterator mapi;    
  23.     typedef std::map<std::string,std::string>::const_iterator mapci;    
  24.     // Methods    
  25. public:    
  26.     
  27.     Config( std::string filename,std::string delimiter = "=",std::string comment = "#" );    
  28.     Config();    
  29.     template<class T> T Read( const std::string& in_key ) const;  //!<Search for key and read value or optional default value, call as read<T>    
  30.     template<class T> T Read( const std::string& in_key, const T& in_value ) const;    
  31.     template<class T> bool ReadInto( T& out_var, const std::string& in_key ) const;    
  32.     template<class T>    
  33.     bool ReadInto( T& out_var, const std::string& in_key, const T& in_value ) const;    
  34.     bool FileExist(std::string filename);    
  35.     void ReadFile(std::string filename,std::string delimiter = "=",std::string comment = "#" );    
  36.     
  37.     // Check whether key exists in configuration    
  38.     bool KeyExists( const std::string& in_key ) const;    
  39.     
  40.     // Modify keys and values    
  41.     template<class T> void Add( const std::string& in_key, const T& in_value );    
  42.     void Remove( const std::string& in_key );    
  43.     
  44.     // Check or change configuration syntax    
  45.     std::string GetDelimiter() const { return m_Delimiter; }    
  46.     std::string GetComment() const { return m_Comment; }    
  47.     std::string SetDelimiter( const std::string& in_s )    
  48.     { std::string old = m_Delimiter;  m_Delimiter = in_s;  return old; }      
  49.     std::string SetComment( const std::string& in_s )    
  50.     { std::string old = m_Comment;  m_Comment =  in_s;  return old; }    
  51.     
  52.     // Write or read configuration    
  53.     friend std::ostream& operator<<( std::ostream& os, const Config& cf );    
  54.     friend std::istream& operator>>( std::istream& is, Config& cf );    
  55.     
  56. protected:    
  57.     template<class T> static std::string T_as_string( const T& t );    
  58.     template<class T> static T string_as_T( const std::string& s );    
  59.     static void Trim( std::string& inout_s );    
  60.     
  61.     
  62.     // Exception types    
  63. public:    
  64.     struct File_not_found {    
  65.         std::string filename;    
  66.         File_not_found( const std::string& filename_ = std::string() )    
  67.             : filename(filename_) {} };    
  68.         struct Key_not_found {  // thrown only by T read(key) variant of read()    
  69.             std::string key;    
  70.             Key_not_found( const std::string& key_ = std::string() )    
  71.                 : key(key_) {} };    
  72. };    
  73.     
  74.     
  75. /* static */    
  76. template<class T>    
  77. std::string Config::T_as_string( const T& t )    
  78. {    
  79.     // Convert from a T to a string    
  80.     // Type T must support << operator    
  81.     std::ostringstream ost;    
  82.     ost << t;    
  83.     return ost.str();    
  84. }    
  85.     
  86.     
  87. /* static */    
  88. template<class T>    
  89. T Config::string_as_T( const std::string& s )    
  90. {    
  91.     // Convert from a string to a T    
  92.     // Type T must support >> operator    
  93.     T t;    
  94.     std::istringstream ist(s);    
  95.     ist >> t;    
  96.     return t;    
  97. }    
  98.     
  99.     
  100. /* static */    
  101. template<>    
  102. inline std::string Config::string_as_T<std::string>( const std::string& s )    
  103. {    
  104.     // Convert from a string to a string    
  105.     // In other words, do nothing    
  106.     return s;    
  107. }    
  108.     
  109.     
  110. /* static */    
  111. template<>    
  112. inline bool Config::string_as_T<bool>( const std::string& s )    
  113. {    
  114.     // Convert from a string to a bool    
  115.     // Interpret "false", "F", "no", "n", "0" as false    
  116.     // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true    
  117.     bool b = true;    
  118.     std::string sup = s;    
  119.     for( std::string::iterator p = sup.begin(); p != sup.end(); ++p )    
  120.         *p = toupper(*p);  // make string all caps    
  121.     if( sup==std::string("FALSE") || sup==std::string("F") ||    
  122.         sup==std::string("NO") || sup==std::string("N") ||    
  123.         sup==std::string("0") || sup==std::string("NONE") )    
  124.         b = false;    
  125.     return b;    
  126. }    
  127.     
  128.     
  129. template<class T>    
  130. T Config::Read( const std::string& key ) const    
  131. {    
  132.     // Read the value corresponding to key    
  133.     mapci p = m_Contents.find(key);    
  134.     if( p == m_Contents.end() ) throw Key_not_found(key);    
  135.     return string_as_T<T>( p->second );    
  136. }    
  137.     
  138.     
  139. template<class T>    
  140. T Config::Read( const std::string& key, const T& value ) const    
  141. {    
  142.     // Return the value corresponding to key or given default value    
  143.     // if key is not found    
  144.     mapci p = m_Contents.find(key);    
  145.     if( p == m_Contents.end() ) return value;    
  146.     return string_as_T<T>( p->second );    
  147. }    
  148.     
  149.     
  150. template<class T>    
  151. bool Config::ReadInto( T& var, const std::string& key ) const    
  152. {    
  153.     // Get the value corresponding to key and store in var    
  154.     // Return true if key is found    
  155.     // Otherwise leave var untouched    
  156.     mapci p = m_Contents.find(key);    
  157.     bool found = ( p != m_Contents.end() );    
  158.     if( found ) var = string_as_T<T>( p->second );    
  159.     return found;    
  160. }    
  161.     
  162.     
  163. template<class T>    
  164. bool Config::ReadInto( T& var, const std::string& key, const T& value ) const    
  165. {    
  166.     // Get the value corresponding to key and store in var    
  167.     // Return true if key is found    
  168.     // Otherwise set var to given default    
  169.     mapci p = m_Contents.find(key);    
  170.     bool found = ( p != m_Contents.end() );    
  171.     if( found )    
  172.         var = string_as_T<T>( p->second );    
  173.     else    
  174.         var = value;    
  175.     return found;    
  176. }    
  177.     
  178.     
  179. template<class T>    
  180. void Config::Add( const std::string& in_key, const T& value )    
  181. {    
  182.     // Add a key with given value    
  183.     std::string v = T_as_string( value );    
  184.     std::string key=in_key;    
  185.     trim(key);    
  186.     trim(v);    
  187.     m_Contents[key] = v;    
  188.     return;    
  189. }    


Config.cpp

[cpp]  view plain copy
  1. // Config.cpp    
  2.     
  3. #include "Config.h"    
  4.     
  5. using namespace std;    
  6.     
  7.     
  8. Config::Config( string filename, string delimiter,    
  9.                string comment )    
  10.                : m_Delimiter(delimiter), m_Comment(comment)    
  11. {    
  12.     // Construct a Config, getting keys and values from given file    
  13.     
  14.     std::ifstream in( filename.c_str() );    
  15.     
  16.     if( !in ) throw File_not_found( filename );     
  17.     
  18.     in >> (*this);    
  19. }    
  20.     
  21.     
  22. Config::Config()    
  23. : m_Delimiter( string(1,'=') ), m_Comment( string(1,'#') )    
  24. {    
  25.     // Construct a Config without a file; empty    
  26. }    
  27.     
  28.     
  29.     
  30. bool Config::KeyExists( const string& key ) const    
  31. {    
  32.     // Indicate whether key is found    
  33.     mapci p = m_Contents.find( key );    
  34.     return ( p != m_Contents.end() );    
  35. }    
  36.     
  37.     
  38. /* static */    
  39. void Config::Trim( string& inout_s )    
  40. {    
  41.     // Remove leading and trailing whitespace    
  42.     static const char whitespace[] = " \n\t\v\r\f";    
  43.     inout_s.erase( 0, inout_s.find_first_not_of(whitespace) );    
  44.     inout_s.erase( inout_s.find_last_not_of(whitespace) + 1U );    
  45. }    
  46.     
  47.     
  48. std::ostream& operator<<( std::ostream& os, const Config& cf )    
  49. {    
  50.     // Save a Config to os    
  51.     for( Config::mapci p = cf.m_Contents.begin();    
  52.         p != cf.m_Contents.end();    
  53.         ++p )    
  54.     {    
  55.         os << p->first << " " << cf.m_Delimiter << " ";    
  56.         os << p->second << std::endl;    
  57.     }    
  58.     return os;    
  59. }    
  60.     
  61. void Config::Remove( const string& key )    
  62. {    
  63.     // Remove key and its value    
  64.     m_Contents.erase( m_Contents.find( key ) );    
  65.     return;    
  66. }    
  67.     
  68. std::istream& operator>>( std::istream& is, Config& cf )    
  69. {    
  70.     // Load a Config from is    
  71.     // Read in keys and values, keeping internal whitespace    
  72.     typedef string::size_type pos;    
  73.     const string& delim  = cf.m_Delimiter;  // separator    
  74.     const string& comm   = cf.m_Comment;    // comment    
  75.     const pos skip = delim.length();        // length of separator    
  76.     
  77.     string nextline = "";  // might need to read ahead to see where value ends    
  78.     
  79.     while( is || nextline.length() > 0 )    
  80.     {    
  81.         // Read an entire line at a time    
  82.         string line;    
  83.         if( nextline.length() > 0 )    
  84.         {    
  85.             line = nextline;  // we read ahead; use it now    
  86.             nextline = "";    
  87.         }    
  88.         else    
  89.         {    
  90.             std::getline( is, line );    
  91.         }    
  92.     
  93.         // Ignore comments    
  94.         line = line.substr( 0, line.find(comm) );    
  95.     
  96.         // Parse the line if it contains a delimiter    
  97.         pos delimPos = line.find( delim );    
  98.         if( delimPos < string::npos )    
  99.         {    
  100.             // Extract the key    
  101.             string key = line.substr( 0, delimPos );    
  102.             line.replace( 0, delimPos+skip, "" );    
  103.     
  104.             // See if value continues on the next line    
  105.             // Stop at blank line, next line with a key, end of stream,    
  106.             // or end of file sentry    
  107.             bool terminate = false;    
  108.             while( !terminate && is )    
  109.             {    
  110.                 std::getline( is, nextline );    
  111.                 terminate = true;    
  112.     
  113.                 string nlcopy = nextline;    
  114.                 Config::Trim(nlcopy);    
  115.                 if( nlcopy == "" ) continue;    
  116.     
  117.                 nextline = nextline.substr( 0, nextline.find(comm) );    
  118.                 if( nextline.find(delim) != string::npos )    
  119.                     continue;    
  120.     
  121.                 nlcopy = nextline;    
  122.                 Config::Trim(nlcopy);    
  123.                 if( nlcopy != "" ) line += "\n";    
  124.                 line += nextline;    
  125.                 terminate = false;    
  126.             }    
  127.     
  128.             // Store key and value    
  129.             Config::Trim(key);    
  130.             Config::Trim(line);    
  131.             cf.m_Contents[key] = line;  // overwrites if key is repeated    
  132.         }    
  133.     }    
  134.     
  135.     return is;    
  136. }    
  137. bool Config::FileExist(std::string filename)    
  138. {    
  139.     bool exist= false;    
  140.     std::ifstream in( filename.c_str() );    
  141.     if( in )     
  142.         exist = true;    
  143.     return exist;    
  144. }    
  145.     
  146. void Config::ReadFile( string filename, string delimiter,    
  147.                       string comment )    
  148. {    
  149.     m_Delimiter = delimiter;    
  150.     m_Comment = comment;    
  151.     std::ifstream in( filename.c_str() );    
  152.     
  153.     if( !in ) throw File_not_found( filename );     
  154.     
  155.     in >> (*this);    
  156. }    

 

引自:http://cooker.iteye.com/blog/777455

在其基础上做了下包装:

Main_config.h

[cpp]  view plain copy
  1. // Main_config.h: interface for the Main_config class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4.   
  5. #if !defined(AFX_MAIN_CONFIG_H__B4BEEE3F_3D81_4428_A25F_66E6B56318F2__INCLUDED_)  
  6. #define AFX_MAIN_CONFIG_H__B4BEEE3F_3D81_4428_A25F_66E6B56318F2__INCLUDED_  
  7.   
  8. #include "const.h"  
  9. #include "Config.h"  
  10.   
  11. // 主配置文件封装  
  12. class Main_config  
  13. {  
  14. public:  
  15.     // @brief 获取实例  
  16.     static Main_config& instance();  
  17.   
  18.     // @brief 获取配置Config对象  
  19.     const Config& get_config();  
  20.   
  21.     // @brief 导入配置文件  
  22.     bool load_config();  
  23.   
  24. private:  
  25.     Main_config();  
  26.   
  27.     virtual ~Main_config();  
  28.   
  29.     // 配置对象  
  30.     Config* _config;  
  31.   
  32.     // 配置文件路径  
  33.     char _conf_path[PATH_SIZE];  
  34.   
  35.     // 配置文件名  
  36.     char _conf_name[PATH_SIZE];  
  37. };  
  38.   
  39. #endif // !defined(AFX_MAIN_CONFIG_H__B4BEEE3F_3D81_4428_A25F_66E6B56318F2__INCLUDED_)  


Main_config.cpp

[cpp]  view plain copy
  1. // Main_config.cpp: implementation of the Main_config class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4.   
  5. #include "Main_config.h"  
  6. #include "const.h"  
  7.   
  8. //////////////////////////////////////////////////////////////////////  
  9. // Construction/Destruction  
  10. //////////////////////////////////////////////////////////////////////  
  11.   
  12. Main_config::Main_config()  
  13. {  
  14.     snprintf(_conf_path, sizeof(_conf_path), "%s""../conf");  
  15.     snprintf(_conf_name, sizeof(_conf_name), "%s/%s.%s", _conf_path, execname, "conf");  
  16. }  
  17.   
  18. Main_config::~Main_config()  
  19. {  
  20.     if(_config)  
  21.     {  
  22.         delete _config;  
  23.     }  
  24. }  
  25.   
  26. bool Main_config::load_config()  
  27. {  
  28.     bool ret = true;  
  29.       
  30.     _config = new(std::nothrow) Config(_conf_name);  
  31.     if (_config == NULL)  
  32.     {  
  33.         return false;  
  34.     }  
  35.   
  36.     return ret;  
  37. }  
  38.   
  39. Main_config& Main_config::instance()  
  40. {  
  41.     static Main_config main_config;  
  42.     return main_config;  
  43. }  
  44.   
  45. const Config& Main_config::get_config()  
  46. {  
  47.     return *_config;  
  48. }  


使用:

[cpp]  view plain copy
  1. #include "Main_config.h"  
  2. ....  
  3. // 加载主配置文件  
  4. if (!Main_config::instance().load_config())  
  5. {  
  6.     std::cout << "Main_config::load_config() failed" << std::endl;  
  7.     return false;  
  8. }  
  9. //从配置文件中读取端口号  
  10. _port = Main_config::instance().get_config().Read("PORT", 0);   
  11. ....  

 

你可能感兴趣的:(C++)