SourceForge.jp

dkutilINIManager.h

説明を見る。
00001 
00007 #ifndef _dkutilINIManager__h_
00008 #define _dkutilINIManager__h_
00009 
00010 #include <dkutil/include/dkutilBoostPolicy.h>
00011 #include "dKingyoMacro.h"
00012 #include "dkutilDefined.h"
00013 //#include "dKingyoUtilClass.h"
00014 #include "dkutilMap.h"
00015 #include "dkutilString.h"
00016 #include "dkutilParser.h"
00017 #include "dkutilOutput.h"
00018 #include "dkutilFileSystem.h"
00019 #include "dkutilOS.h"
00020 
00021 
00022 namespace dkutil{
00023 namespace policy{
00027 class ini_semantic_action {
00028 public: 
00029 struct DATA_TYPE{
00030     //boost::any Any;
00031     //std::string Data;
00032     dkutil::GeneralPurposeVariable Data;
00033 };
00034 typedef dkutil::map_ex<std::string,DATA_TYPE> KEY_MAP;
00035 typedef KEY_MAP::DATA_TYPE KEY_DATA;
00036 typedef KEY_MAP::const_iterator const_key_iterator;
00037 //struct SECTION_DATA{
00038 //  KEY_MAP mMap;
00039 //};
00040 typedef dkutil::map_ex<std::string,KEY_MAP> SECTION_MAP;
00041 //typedef SECTION_MAP::const_iterator const_iterator;
00042 typedef SECTION_MAP::DATA_TYPE SECTION_DATA;
00043 typedef SECTION_MAP::const_iterator const_section_iterator;
00044 
00045 struct ini_semantic_action_base{
00046     std::string& mStr;
00047     SECTION_MAP& mMap;
00048     ini_semantic_action_base(std::string &get,SECTION_MAP &section_map) : 
00049         mStr(get) ,mMap(section_map) {}
00050     
00051 };
00052 struct ini_section_push : public ini_semantic_action_base{
00053     ini_section_push(std::string &get,SECTION_MAP &section_map) : 
00054         ini_semantic_action_base(get,section_map){}
00055 
00056 
00057   void operator()(char c) const { // const が重要
00058         mStr += c;
00059 
00060   }
00061 };
00062 struct ini_key_push: public ini_semantic_action_base{
00063     ini_key_push(std::string &get,SECTION_MAP &section_map) : 
00064         ini_semantic_action_base(get,section_map){}
00065 
00066     //template<class IteratorT>
00067   void operator()(char c) const { // const が重要
00068         mStr += c;
00069 
00070   }
00071 };
00072 struct ini_param_push: public ini_semantic_action_base{
00073     ini_param_push(std::string &get,SECTION_MAP &section_map) : 
00074         ini_semantic_action_base(get,section_map){}
00075 
00076 
00077     //template<class IteratorT>
00078   /*void operator()(IteratorT first, IteratorT last) const { // const が重要
00079         mStr += (*first);
00080 
00081   }*/
00082     void operator()(char c) const { // const が重要
00083         mStr += c;
00084   }
00085 
00086 };
00087 
00088 struct ini_begin_section: public ini_semantic_action_base{
00089     ini_begin_section(std::string &get,SECTION_MAP &section_map) : 
00090         ini_semantic_action_base(get,section_map){}
00091     
00092     //template<class IteratorT>
00093   /*void operator()(IteratorT first, IteratorT last) const { // const が重要
00094         mStr.clear();
00095         mStr += (*first);
00096 
00097   }*/
00098     void operator()(char c) const { // const が重要
00099         mStr.clear();
00100         mStr += c;
00101 
00102   }
00103 
00104 };
00105 struct ini_begin_key: public ini_semantic_action_base{
00106     ini_begin_key(std::string &get,SECTION_MAP &section_map) : 
00107         ini_semantic_action_base(get,section_map){}
00108     template<class IteratorT>
00109   void operator()(IteratorT first, IteratorT last) const { // const が重要
00110         mStr.clear();
00111         mStr += (*first);
00112 
00113   }
00114 
00115 };
00116 struct ini_begin_param: public ini_semantic_action_base{
00117     ini_begin_param(std::string &get,SECTION_MAP &section_map) : 
00118         ini_semantic_action_base(get,section_map){}
00119     template<class IteratorT>
00120   void operator()(IteratorT first, IteratorT last) const { // const が重要
00121         mStr.clear();
00122         mStr += (*first);
00123 
00124   }
00125 
00126 };
00127 
00128 struct ini_section_set{
00129     SECTION_DATA &mData;
00130     std::string &mStr;
00131     SECTION_MAP &mMap;
00132     ini_section_set(std::string &Str,SECTION_DATA &getData,SECTION_MAP &section_map) : 
00133     mStr(Str) , mData(getData),mMap(section_map)    {}
00134 
00135 
00136     template<class IteratorT>
00137   void operator()(IteratorT first, IteratorT last) const { // const が重要
00138         mData.first = mStr;
00139   }
00140 };
00141 struct ini_key_set{
00142     KEY_DATA &mData;
00143     std::string &mStr;
00144     SECTION_MAP &mMap;
00145     ini_key_set(std::string &Str,KEY_DATA &getData,SECTION_MAP &section_map) : 
00146     mStr(Str) , mData(getData),mMap(section_map)    {}
00147     template<class IteratorT>
00148   void operator()(IteratorT first, IteratorT last) const { // const が重要
00149         mData.first = mStr;
00150   }
00151 };
00152 
00153 struct ini_param_set{
00154     KEY_DATA &mData;
00155     SECTION_DATA &mSectionData;
00156     std::string &mStr;
00157     SECTION_MAP &mMap;
00158     ini_param_set(std::string &Str,SECTION_DATA &getSection,KEY_DATA &getData,SECTION_MAP &section_map) : 
00159     mStr(Str) , mData(getData),mMap(section_map)    ,mSectionData(getSection){}
00160 
00161     template<class IteratorT>
00162   void operator()(IteratorT first, IteratorT last) const { // const が重要
00163         dkutil::GeneralPurposeVariable gp;
00164         if(!mStr.empty()){
00165             if(false==private_::ParsedStringToGeneralPurposeVariable(mStr.c_str(),&gp)){
00166                 DKUTIL_TRUE_ASSERT("UNKNOWN ERROR");
00167             }
00168             if(gp.isString()){
00169                 //ダブルクォーテーション削除
00170                 if(*(gp.mstr.begin()) == '"'){
00171                     gp.mstr.erase(gp.mstr.begin());
00172                     if(*(gp.mstr.end() - 1) == '"'){
00173                         gp.mstr.erase((gp.mstr.end() - 1));
00174                     }
00175                 }
00176             }
00177         }else{
00178             gp = mStr;
00179         }
00180         
00181         mData.second.Data = gp;
00182         if(false==mSectionData.second.rb_insert(mData)){
00183             DKUTIL_TRUE_ASSERT("UNKNOWN ERROR");
00184         }
00185         
00186         
00187         if(false==mMap.rb_insert(mSectionData))
00188         {
00189             SECTION_MAP::iterator it = mMap.find(mSectionData.first);
00190             if(it == mMap.end()){
00191                 DKUTIL_TRUE_ASSERT("UNKNOWN ERROR");
00192             }
00193             if(false==(*it).second.isInserted(
00194                 (*it).second.insert(mData)
00195                 ))
00196             {
00197                 DKUTIL_TRUE_ASSERT("キーが重複しているのか!?");
00198             }
00199         }
00200         //削除処理
00201         mSectionData.second.clear();
00202         mStr.clear();
00203   }
00204 };
00205 
00206 };//end of ini_semantic_action 
00207 
00208 
00209 }//end of policy namespace
00210 
00211 
00215 //template<class POLICY=policy::ini_semantic_action >
00216 class INIManager{
00217 public:
00218     typedef policy::ini_semantic_action POLICY ;
00219 
00220 
00221     typedef boost::spirit::file_iterator<char> file_iterator;
00222     typedef POLICY semantic_action;
00223     
00224 
00226     struct ini_parser : public boost::spirit::grammar<ini_parser> {
00227         typedef semantic_action sa;
00228 
00229         std::string &rsection;
00230         std::string &rkey;
00231         std::string &rparam;
00232         //std::string SectionStr;
00233         //std::string KeyStr;
00234         //std::string ParamStr;
00235         sa::SECTION_DATA &mSectionData;
00236         sa::KEY_DATA &mKeyData;
00237 
00238         sa::SECTION_MAP &mMap;
00239         const sa::SECTION_MAP &database()const{return mMap;}
00240         sa::SECTION_MAP &database(){return mMap;}
00241         ini_parser(sa::SECTION_MAP &getMap,
00242             std::string &section,std::string &key,std::string &param,
00243             sa::SECTION_DATA &section_data,sa::KEY_DATA &key_data) : 
00244         mMap(getMap) , rsection(section) ,rkey(key) , rparam(param) ,
00245         mSectionData(section_data),mKeyData(key_data){}
00246 
00247         template<typename S> struct definition {
00248             
00249             boost::spirit::rule<S> key_name_r, param_r , section_name_r;
00250             boost::spirit::rule<S> ini, section, key;
00251 
00252             definition(const ini_parser& self)
00253             {
00254                 using namespace boost::spirit;
00255                 
00256                 param_r = *(print_p[sa::ini_param_push(self.rparam,self.mMap)]);
00257                 
00258                 key_name_r      = (alpha_p[sa::ini_begin_section(self.rkey,self.mMap)] | 
00259                     ch_p('_')[sa::ini_begin_section(self.rkey,self.mMap)]) >> 
00260                     *( (alnum_p[sa::ini_section_push(self.rkey,self.mMap)] | 
00261                         ch_p('_')[sa::ini_section_push(self.rkey,self.mMap)])
00262                     );
00263                 section_name_r = (alpha_p[sa::ini_begin_section(self.rsection,self.mMap)] | 
00264                     ch_p('_')[sa::ini_begin_section(self.rsection,self.mMap)]) >> 
00265                     *( (alnum_p[sa::ini_section_push(self.rsection,self.mMap)] | 
00266                         ch_p('_')[sa::ini_section_push(self.rsection,self.mMap)])
00267                     );
00268                 
00269                 section     = '[' >> section_name_r >> ']' >> 
00270                     eps_p[sa::ini_section_set(self.rsection,self.mSectionData,self.mMap)] >>
00271                     +space_p >> *(key >> +space_p);
00272                 
00273                 key         = key_name_r[sa::ini_key_set(self.rkey,self.mKeyData,self.mMap)] >>
00274                     *space_p >> '=' >> *space_p >>
00275                     param_r[sa::ini_param_set(self.rparam,self.mSectionData,self.mKeyData,self.mMap)];
00276                 ini         = *space_p >> *section >> *space_p;
00277                 /*
00278                 param_r = *(print_p[&AckString]);
00279                 name_r      = (alpha_p[&BeginName] | ch_p('_')[&BeginName]) >> 
00280                     *( (alnum_p[&AckName] | ch_p('_')[&AckName]) ) >>
00281                     eps_p[&EndName];
00282                 section     = '[' >> name_r >> ']' >> 
00283                     eps_p[&MOV_name_section] >>
00284                     +space_p >> *(key >> +space_p);
00285                 key         = name_r[&MOV_name_key] >> *space_p >> '=' >> *space_p >>
00286                     param_r[&AddKeyString];
00287                 ini         = *space_p >> *section >> *space_p;
00288                 */
00289             }
00290 
00291             // 開始記号を定義
00292             const boost::spirit::rule<S>& start() const { return ini; }
00293 
00294         };
00295 
00296     };
00297     typedef semantic_action::const_section_iterator const_section_iterator;
00298     typedef semantic_action::const_key_iterator const_key_iterator;
00299     typedef boost::spirit::parse_info<file_iterator> parse_result;
00300     typedef boost::compressed_pair<const_key_iterator,bool> find_key_result;
00301     //typedef semantic_action::
00302 private:
00303     
00304     std::string mFileName;
00305 
00306     std::string rsection;
00307     std::string rkey;
00308     std::string rparam;
00309 
00310     semantic_action::SECTION_DATA mSectionData;
00311     semantic_action::KEY_DATA mKeyData;
00312 
00313     semantic_action::SECTION_MAP mMap;
00314 
00316     parse_result Parsing(file_iterator &it){
00317         namespace bs = boost::spirit;
00318         ini_parser mINI(mMap,rsection,rkey,rparam,mSectionData,mKeyData);
00319         file_iterator end_it = it.make_end();
00320         bs::parse_info<file_iterator> r = bs::parse(it,end_it,mINI);
00321 
00322         return r;
00323     }
00324 
00325 
00326 public:
00327     INIManager(const char *filename=NULL){
00328         if(filename){
00329             mFileName = filename;
00330         }
00331     }
00332     virtual ~INIManager(){}
00333     bool reset(const char *filename,parse_result *result_ptr=NULL){
00334         if(FileExist(filename)==false) return false;
00335         mFileName = filename;
00336         mMap.clear();
00337         file_iterator f(filename);
00338         parse_result r = Parsing(f);
00339         if(result_ptr){
00340             *result_ptr = r; 
00341         }
00342         if(r.full){ // 入力された文字列が全て解析されていたらOK
00343             return true;
00344         }else{  // 入力された文字列が全て解析されてないならエラーとみなす
00345             //assert(false);
00346             return false;
00347         }
00348     }
00349 
00350     bool empty()const{  return mMap.empty();}
00351     const char *name()const{ return mFileName.c_str();}
00352     void clear(){mFileName.clear();mMap.clear();}
00353     const_section_iterator begin()const{return mMap.begin();}
00354     const_section_iterator end()const{return mMap.end();}
00355     const_section_iterator find_section(const char *section_name){
00356         return mMap.find(section_name);
00357     }
00358     /*
00359     find_key_result find_key(const char *section_name,const char *key_name){
00360         find_key_result result(;
00361         //result.first;
00362         const_section_iterator it = find_section(section_name);
00363         if(it == end()){ result.second = false;return result;}
00364         result.first = (*it).second.find(key_name);
00365         if(result.first == (*it).second.end()){
00366             result.second = false;
00367             return result;
00368         }
00369         result.second = true;
00370         return result;
00371     }
00372     */
00373     const_key_iterator find_key_from_found_section(const_section_iterator it,
00374         const char *key_name)
00375     {
00376         if(it == mMap.end()) throw std::runtime_error("find_key_from_found_section invalid argument");
00377         return it->second.find(key_name);
00378     }
00379 
00380 
00381 };
00382 
00383 
00384 
00385 
00386 
00387 
00396 class inifile_operator{
00397 //# define ini_exception(s) std::runtime_error("ini_operator::" + s);
00398 
00399     std::string mFileName;
00401     void CheckException(){
00402         if(mFileName.empty())
00403         {
00404             //あー、ファイル名が指定されてねぇなぁ
00405             throw std::runtime_error("ini_operator::... error / not defined filename");
00406         }
00407     }
00409     bool search_tab(const char* str){
00410         char c=1;
00411         bool result=false;
00412         for(size_t i=0;c!=UINT_MAX || c=='\0';i++){
00413             
00414             if(str[i]=='\0' && '\0'==c){
00415                 break;
00416             }else if(str[i]=='\t'){
00417                 result = true;
00418                 break;
00419             }
00420             c = str[i];
00421         }
00422         return result;
00423     }
00424 
00425         
00426 
00427 public:
00428     inifile_operator(const char *filename){
00429         if(filename){
00430             reset(filename);
00431         }
00432     }
00433     virtual ~inifile_operator(){}
00434     bool reset(const char *filename){
00435         /*if(false==CheckWin9x(filename)){
00436             return false;
00437         }*/
00438         mFileName = filename;
00439     }
00445     int write_section(LPCTSTR section_name,LPCTSTR data){
00446         CheckException();
00447         if(isOS9x()){
00448             //MSDNには書いていないけど、信用できないのでいちおうチェック。
00449             if(true==search_tab(data)){
00450                 return edk_ArgumentException;
00451             }
00452         }
00453         if(false==(0 != WritePrivateProfileSection(
00454             section_name,// セクション名へのポインタ
00455             data,// 書き込むデータへのポインタ
00456             mFileName.c_str()// ファイル名へのポインタ
00457             ))){
00458             return edk_FAILED;
00459         }
00460         return edk_SUCCEEDED;
00461     }
00462     int write_string(LPCTSTR section_name,LPCTSTR key_name,LPCTSTR str){
00463         CheckException();
00464         if(isOS9x()){
00465             if(true==search_tab(str)){
00466                 return edk_ArgumentException;
00467             }
00468         }
00469         if(0==WriteProfileString(
00470             section_name,// セクション名へのポインタ
00471             key_name,// キー名へのポインタ
00472             str// 書き込むデータへのポインタ
00473             )){
00474             return edk_FAILED;
00475         }
00476         return edk_SUCCEEDED;
00477     }
00478 
00479 
00480 
00481 
00483     bool delete_section( const char *SectionName )
00484     {
00485         CheckException();
00486         return ( 0 != WritePrivateProfileString( SectionName, NULL, NULL, mFileName.c_str() ));
00487     }
00489     bool delete_key( const char *SectionName, const char *KeyName)
00490     {   
00491         CheckException();
00492         return (0 != WritePrivateProfileString( SectionName, KeyName,
00493             NULL, mFileName.c_str() ));
00494     }
00496     bool exist( const char *SectionName, const char *KeyName )
00497     {
00498         CheckException(); ;
00499         // 指定したキーが見つからない場合、
00500         //関数 GetPrivateProfileInt() は1回目の呼び出しで0を、
00501         //2回目の呼び出しで1を返す。
00502         return (
00503             GetPrivateProfileInt(
00504                 SectionName, KeyName, 0, mFileName.c_str() 
00505                 ) ==    GetPrivateProfileInt(
00506             SectionName, KeyName, 1, mFileName.c_str())
00507             );
00508     }
00517     static int LoadSectionLogic(LPCTSTR SectionName,
00518                         LPTSTR Buffer,DWORD Size,
00519                         LPCTSTR FileName)
00520     {
00521         DWORD r;
00522         if(false==isOS9x()){ return edk_FAILED;}
00523         r = GetPrivateProfileSection(SectionName,Buffer,Size,FileName);
00524         if(r == Size - 2){  return edk_BufferOverFlow;}     
00525         return edk_SUCCEEDED;
00526     }
00527 //# undef ini_exception
00528 };
00529 
00530 
00531 }//end of dkutil namespace
00532 
00533 
00534 #endif//end of include once
00535 

dkutil 1.02リリース前 d金魚専用マニュアルバージョンに対してSun Dec 28 21:23:08 2003に生成されました。 doxygen 1.3.5