zoukankan      html  css  js  c++  java
  • 重写了iniparser类

    在MFC里面用了一下iniparser类,发现功能不健全,又重新封装了一下,删除了上一篇日志。

    MFC和boost的兼容性很烂,我为了省事专门给CString做了重载和特化。

    头文件(VS一直不支持export关键字,非常蛋疼):

      1 /************************************************************************/
      2 /* Instruction: CIniParser类主要是封装了boost::property_tree::ini_parser中的几个
      3    函数,用来操纵ini配置文件。ini文件用于比较简单的程序配置,因此该类被写成了单例。
      4    在C++11下,该类是线程安全的,否则不是。
      5    Note: 由于该类只和STL及boost打交道,因此使用了STL命名规范。注意property_tree会抛出异常,
      6    这里需要捕获异常,并返回错误码。
      7 */
      8 /************************************************************************/
      9 #ifndef CTI_SDK_USING_MFC_INI_PARSER_H
     10 #define CTI_SDK_USING_MFC_INI_PARSER_H
     11 
     12 #include <string>
     13 #include <map>
     14 #include <memory>
     15 #include <boost/property_tree/ptree.hpp>
     16 #include <boost/property_tree/ini_parser.hpp>
     17 //模板实现所需
     18 #include <boost/property_tree/exceptions.hpp>
     19 #include <boost/lexical_cast.hpp>
     20 
     21 class CIniParser :
     22     private boost::noncopyable
     23 {
     24 public:
     25     enum IniErrNo
     26     {
     27         kNoErr=0,
     28         kNotFound=1,
     29         kNotModified=2,
     30         kCanNotCreateFile=3,
     31         kOtherErr=10
     32     };
     33     static CIniParser& GetInstance(                         //获得单例
     34             const std::wstring& full_filename=L"config.ini");//文件的相对/绝对路径+文件名
     35 
     36     ~CIniParser(void){}
     37     template<typename T>
     38     int Get(const std::wstring& section_name,const std::wstring& property_name,
     39         T *result)const;
     40     template<typename T>
     41     int Put(const std::wstring& section_name,const std::wstring& property_name,
     42         const T& value);
     43     int PutMaps(const std::wstring& section_name,
     44         const std::map<std::wstring,std::wstring>& property_value_map);
     45 //#ifdef _MFC_VER
     46 //    //为方便使用,提供CString接口
     47     template<typename T>
     48     int Get(const CString& secitonName,const CString& propertyName,
     49         T* result)const;
     50     //CString非标准,lexical_cast会失败,因此需要特化
     51     template<>
     52     int Get<CString>(const CString& secitonName,const CString& propertyName,
     53         CString* result)const;
     54     template<typename T>
     55     int Put(const CString& sectionName,const CString& propertyName,
     56         const T& value);
     57     template<>
     58     int Put<CString>(const CString& sectionName,const CString& propertyName, 
     59         const CString& value);
     60     int PutMaps(const CString& sectionName,
     61         const std::map<CString,CString>& propertyValueMap);
     62 //#endif //!_MFC_VER
     63     
     64 private:
     65     CIniParser(const std::wstring& full_filename);
     66     std::string filename_;
     67     boost::property_tree::wptree pt_;
     68 };
     69 
     70 //模板函数的实现,由于VS不支持export关键字,模板函数只能定义在头文件中(考虑写在另一个文件,然后include)
     71 
     72 template<typename T>
     73 int CIniParser::Get(const std::wstring& section_name,
     74                     const std::wstring& property_name, 
     75                     T *result)const
     76 {
     77     std::wstring node(section_name+L"."+property_name);
     78     try
     79     {
     80         *result=pt_.get<T>(node);
     81     }catch(boost::property_tree::ptree_bad_data& e)
     82     {
     83         std::cout<<e.data<std::string>()<<std::endl;
     84         return CIniParser::kNotFound;
     85     }catch(boost::property_tree::ptree_bad_path& e)
     86     {
     87         std::cout<<e.what()<<std::endl;
     88         return CIniParser::kCanNotCreateFile;
     89     }
     90     catch(...)
     91     {
     92         return CIniParser::kOtherErr;
     93     }
     94     return 0;
     95 }
     96 
     97 template<typename T>
     98 int CIniParser::Get(const CString& secitonName,
     99                     const CString& propertyName,
    100                     T *result)const
    101 {
    102     return Get(wstring(secitonName.GetString()),propertyName.GetString(),result);
    103 }
    104 
    105 template<>
    106 int CIniParser::Get<CString>(const CString& secitonName,const CString& propertyName,
    107                              CString* result)const
    108 {
    109     std::wstring temp;
    110     int err=Get(std::wstring(secitonName.GetString()),
    111         propertyName.GetString(),
    112         &temp);
    113     *result=temp.c_str();
    114     return err;
    115 }
    116 template<typename T>
    117 int CIniParser::Put(const std::wstring& section_name,
    118                     const std::wstring& property_name,
    119                     const T& value)
    120 {
    121     std::wstring node(section_name+L"."+property_name);
    122     int err=0;
    123     try
    124     {
    125         pt_.put(node,value);
    126         write_ini(filename_,pt_);
    127     }
    128     catch(boost::property_tree::ptree_bad_data& e)
    129     {
    130         err=CIniParser::kNotModified;
    131         std::wcout<<e.data<std::wstring>()<<std::endl;
    132     }
    133     catch(boost::property_tree::ini_parser_error& e)
    134     {
    135         err=CIniParser::kNotModified;
    136         std::cout<<"Line "<<e.line()
    137             <<", file name: "<<e.filename()
    138             <<", message: "<<e.message()
    139             <<std::endl;
    140     }
    141     catch(...)
    142     {
    143         return CIniParser::kOtherErr;
    144     }
    145     return err;
    146 }
    147 template<typename T>
    148 int CIniParser::Put(const CString& sectionName,const CString& propertyName,
    149                     const T& value)
    150 {
    151     return Put(wstring(sectionName.GetString()),propertyName.GetString(),value);
    152 }
    153 
    154 template<>
    155 int CIniParser::Put<CString>(const CString& sectionName,const CString& propertyName, 
    156                              const CString& value)
    157 {
    158     //指定实例函数
    159     return Put(std::wstring(sectionName.GetString())
    160         ,propertyName.GetString(),value.GetString());
    161 }
    162 
    163 #endif // !CTI_SDK_USING_MFC_INI_PASER_H

    实现文件:

     1 #include "IniParser.h"
     2 #include <fstream>
     3 #include <boost/property_tree/exceptions.hpp>
     4 #include <boost/lexical_cast.hpp>
     5 #include "tools.h"
     6 using namespace std;
     7 using namespace boost::property_tree;
     8 using namespace boost;
     9 
    10 //Warn: 这种方法在C++11前是行不通的!可以使用boost::call_once完成
    11 CIniParser& CIniParser::GetInstance(const std::wstring& full_filename)
    12 {
    13     static CIniParser instance(full_filename);
    14     return instance;
    15 }
    16 
    17 
    18 int CIniParser::PutMaps(const std::wstring& section_name, 
    19                         const std::map<std::wstring,std::wstring>& property_value_map)
    20 {
    21     int err=0;
    22     for(auto pairs:property_value_map)
    23     {
    24         try
    25         {
    26             pt_.put(section_name+L"."+pairs.first,pairs.second);
    27         }
    28         catch(ptree_bad_data& e)
    29         {
    30             err=CIniParser::kNotModified;
    31             wcout<<L"write error:"<<e.data<wstring>()<<endl;
    32         }
    33     }
    34     try
    35     {
    36         write_ini(filename_,pt_);
    37     }
    38     catch(ini_parser_error& e)
    39     {
    40         err=CIniParser::kNotModified;
    41         cout<<"Line "<<e.line()
    42             <<", file name: "<<e.filename()
    43             <<", message: "<<e.message()
    44             <<endl;
    45     }
    46         return err;
    47 }
    48 
    49 int CIniParser::PutMaps( const CString& sectionName,
    50                         const std::map<CString,CString>& propertyValueMap )
    51 {
    52     map<wstring,wstring> temp_map;
    53     for(auto pairs:propertyValueMap)
    54     {
    55         temp_map[pairs.first.GetString()]=pairs.second.GetString();
    56     }
    57     return PutMaps(sectionName.GetString(),temp_map);
    58 }
    59 
    60 CIniParser::CIniParser( const std::wstring& full_filename)
    61 {
    62     wstring_to_string(full_filename,&filename_);
    63     wfstream file(filename_,ios::in);
    64     if (!file)
    65     {
    66         file.clear();
    67         file.open(filename_,ios::out);
    68         //这里可能抛出异常
    69         assert(file);
    70         file.close();
    71     }
    72     read_ini(filename_,pt_);
    73 }

    使用的工具函数:

     1 /************************************************************************/
     2 /* Instruction: 本文件主要包含了一些自己常用的工具函数,方便其他函数引用
     3 */
     4 /************************************************************************/
     5 #ifndef CTI_SDK_USING_MFC_TOOLS_H 
     6 #define CTI_SDK_USING_MFC_TOOLS_H
     7 #include <string>
     8 //UNICODE转换辅助函数
     9 //仅供内部使用
    10 static int ANSIToUnicode(const char *src,int srcCount,wchar_t *dest,int destCount);
    11 static int UnicodeToANSI(const wchar_t *src,int srcCount,char *dest,int destCount);
    12 //for MFC only
    13 #if defined(_MFC_VER)
    14 int CStringAToCStringW(const CStringA& src,CStringW *dest);
    15 int CStringWToCStringA(const CStringW& src,CStringA *dest);
    16 CString GetIPFromDWORD(const DWORD& dw);
    17 DWORD MakeIPToDWORD(const CString& ip);
    18 #endif
    19 //只涉及标准库,使用STL命名约定
    20 int string_to_wstring(const std::string& src,std::wstring *dest);
    21 int wstring_to_string(const std::wstring& src,std::string *dest);
    22 
    23 int GetUniqueName(const TCHAR *prefix,TCHAR *out,int outCount);
    24 #endif // !CTI_SDK_USING_MFC_TOOLS_H 

    实现:

      1 #include "tools.h"
      2 #include <boost/lexical_cast.hpp>
      3 
      4 using namespace std;
      5 using namespace boost;
      6 
      7 int ANSIToUnicode(const char *src,int srcCount,wchar_t *dest,int destCount)
      8 {
      9     assert(src && dest);
     10     assert(destCount >= srcCount);
     11 #ifdef WIN32
     12 #include <stringapiset.h>
     13     int err=MultiByteToWideChar(CP_ACP,0,src,-1,dest,destCount*sizeof(dest[0]));
     14     if (err==0)
     15     {
     16         err=static_cast<int>(GetLastError());
     17     }
     18     else
     19     {
     20         err=0;
     21     }
     22     return err;
     23 #else
     24     setlocale(LC_ALL,"");
     25     int err=mbstowcs(dest,src,destCount*sizeof(dest[0]));
     26     setlocale(LC_ALL,"C");
     27     return err;
     28 #endif // WIN32
     29 }
     30 int UnicodeToANSI(const wchar_t *src,int srcCount,char *dest,int destCount)
     31 {
     32     assert(src && dest);
     33     assert(destCount >= srcCount);
     34 #ifdef WIN32
     35     int err=WideCharToMultiByte(CP_ACP,0,src,-1,dest,destCount,NULL,NULL);
     36     if (err==0)
     37     {
     38         err=static_cast<int>(GetLastError());
     39     }
     40     else
     41     {
     42         err=0;
     43     }
     44     return err;
     45 #else
     46     setlocale(LC_ALL,"");
     47     int err=wcstombs(dest,src,destCount);
     48     setlocale(LC_ALL,"C");
     49     return err;
     50 #endif
     51 }
     52 int CStringAToCStringW(const CStringA& src,CStringW *dest)
     53 {
     54     int length;
     55 #ifdef WIN32
     56     length=MultiByteToWideChar(CP_ACP,0,src,-1,NULL,0)+1;
     57 #else
     58     length=mbstowcs(NULL,src,0)+1;
     59 #endif // WIN32
     60     wchar_t *destbuffer=new wchar_t[length];
     61     int err=ANSIToUnicode(src,src.GetLength(),destbuffer,length);
     62     dest->Format(L"%s",destbuffer);
     63     delete[] destbuffer;
     64     return err;
     65 }
     66 int CStringWToCStringA(const CStringW& src,CStringA *dest)
     67 {
     68     int length;
     69 #ifdef WIN32
     70     length=WideCharToMultiByte(CP_ACP,0,src,-1,NULL,0,NULL,NULL)+1;
     71 #else
     72     length=wcstombs(NULL,src,0)*2+1;
     73 #endif // WIN32
     74     char *destbuffer=new char[length];
     75     int err=UnicodeToANSI(src,src.GetLength(),destbuffer,length);
     76     dest->Format("%s",destbuffer);
     77     delete[] destbuffer;
     78     return err;
     79 }
     80 //TODO: 应该先实现标准的,再使用非标准的调用标准,这里懒得修改了
     81 int string_to_wstring(const string& src,wstring *dest)
     82 {
     83    CStringW destbuffer;
     84    int err=CStringAToCStringW(src.c_str(),&destbuffer);
     85    dest->assign(destbuffer.GetString());
     86    destbuffer.ReleaseBuffer();
     87    return err;
     88 }
     89 int wstring_to_string(const wstring& src,string *dest)
     90 {
     91     CStringA destbuffer;
     92     int err=CStringWToCStringA(src.c_str(),&destbuffer);
     93     dest->assign(destbuffer.GetString());
     94     destbuffer.ReleaseBuffer();
     95     return err;
     96 }
     97 
     98 //TODO: 完善错误处理
     99 int GetUniqueName(const TCHAR *prefix,TCHAR *out,int outCount)
    100 {
    101     int errcode=0;
    102     TCHAR tszTemplate[MAX_PATH]={0};
    103     errcode=_tcscat_s(tszTemplate,MAX_PATH*sizeof(TCHAR),_T("XXXXXX"));
    104     assert(outCount >= _countof(tszTemplate));
    105     errcode=_tmktemp_s(tszTemplate);
    106     errcode=_tcscpy_s(out,outCount*sizeof(TCHAR),tszTemplate);
    107     return errcode;
    108 }
    109 
    110 CString GetIPFromDWORD( const DWORD& dw )
    111 {
    112     WORD hw=HIWORD(dw);
    113     WORD lw=LOWORD(dw);
    114     BYTE ip1stSection=HIBYTE(hw);
    115     BYTE ip2ndSection=LOBYTE(hw);
    116     BYTE ip3rdSection=HIBYTE(lw);
    117     BYTE ip4thSection=LOBYTE(lw);
    118     CString result;
    119     result.Format(_T("%d.%d.%d.%d"),ip1stSection,ip2ndSection,ip3rdSection,
    120         ip4thSection);
    121     return result;
    122 }
    123 
    124 DWORD MakeIPToDWORD( const CString& ip )
    125 {
    126     CString ipSections[4];
    127     CString temp;
    128     int pos=0,i=0;
    129     temp=ip.Tokenize(_T("."),pos);
    130     while (temp!=_T(""))
    131     {
    132         VERIFY(i<4);
    133         ipSections[i++]=temp;
    134         temp=ip.Tokenize(_T("."),pos);
    135     }
    136     BYTE ip1stSection=_ttoi(ipSections[0].GetString());
    137     BYTE ip2ndSection=_ttoi(ipSections[1].GetString());
    138     BYTE ip3rdSection=_ttoi(ipSections[2].GetString());
    139     BYTE ip4thSection=_ttoi(ipSections[3].GetString());
    140     //注意高低位顺序
    141     WORD hw=MAKEWORD(ip2ndSection,ip1stSection);
    142     WORD lw=MAKEWORD(ip4thSection,ip3rdSection);
    143     DWORD result=MAKELONG(lw,hw);
    144 
    145     return result;
    146 }

    这几天写MFC程序,感觉最麻烦的就是unicode和ansi的转换。

    C++最令人的讨厌的特性之一就是不缺省支持unicode,最讨厌的特性之二是没有好的GUI框架。

    如果可以的话,还是直接用Qt最简单。C++的哲学确实偏向学院派,不管是ace,boost还是poco,甚至stl,单独拿出来学习,感觉都很惊艳,

    但是在工业项目中间使用,就感觉各种别扭……

  • 相关阅读:
    LAMP搭建示例
    MySQL主从
    list多字段去重
    mysql按照某一个条件进行分组统计,同时又要保证一个相同字段的数据只统计一次
    sentinel自定义异常处理
    sentinel规则持久化
    zookeeper
    shiro
    iframe之间传递参数
    自定义标签
  • 原文地址:https://www.cnblogs.com/livewithnorest/p/3060311.html
Copyright © 2011-2022 走看看