zoukankan      html  css  js  c++  java
  • C++ ini解析器

      在gitee上找到的一个很好用的ini文件解析器,纯C++代码,移植方便。

      项目地址:https://gitee.com/sollyu/IniParser

      稍微修改了下,去掉了Windows平台相关定义,改了下类名称。

      头文件:

     1 #ifndef INIPARSER_H
     2 #define INIPARSER_H
     3 
     4 
     5 #include <map>
     6 #include <string>
     7 #include <string.h>
     8 
     9 class IniDoc
    10 {
    11 public:
    12     struct IgnoreCaseLT
    13     {
    14         bool operator()(const std::string& lhs, const std::string& rhs) const
    15         {
    16             return strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
    17         }
    18     };
    19 
    20 public:
    21     typedef std::map<std::string, std::string, IgnoreCaseLT> KeyMap;
    22     typedef std::map<std::string, KeyMap,      IgnoreCaseLT> SectionMap;
    23     typedef KeyMap::iterator     KeyIterator;
    24     typedef SectionMap::iterator SectionIterator;
    25 
    26 public:
    27     // 默认的构造函数和析构函数
    28     IniDoc();
    29     ~IniDoc();
    30 
    31     // 构造函数 - 加载文件
    32     IniDoc(const std::string& file_name);
    33 
    34     // 加载一个ini文件, 如果之前的文件被修改, 那么之前的ini文件将会被保持。
    35     bool load(const std::string& file_name);
    36 
    37     // 从字符串中作为ini文件加载
    38     bool loadString(const std::string& str);
    39 
    40     // 保持到加载ini位置
    41     bool save();
    42 
    43     // 另存为一个和加载路径不一样的文件中
    44     bool saveAs(const std::string& file_name);
    45 
    46     // 返回ini是否被修改, 或者他最后一次操作是保存
    47     bool isModified() const { return m_modified; }
    48 
    49 public:    // high level member function.
    50 
    51     // 下面的成员函数是从Section中获得一些值
    52     long getInteger(const std::string& section, const std::string& key, long def_val);
    53     float getFloat(const std::string& section, const std::string& key, float def_val);
    54     long getStruct(const std::string& section, const std::string& key, void* buffer, long size);
    55     long getString(const std::string&  section, const std::string& key, const std::string& def_val, std::string& buffer);
    56     const std::string getString(const std::string&  section, const std::string& key, const std::string& def_val);
    57 
    58     void setInteger(const std::string& section, const std::string& key, long value);
    59     void setFloat(const std::string& section, const std::string& key, float value);
    60     void setStruct(const std::string& section, const std::string& key, const void* buffer, long size);
    61     void setString(const std::string& section, const std::string& key, const std::string& value);
    62 
    63 public:
    64     bool delSection( const std::string& section );
    65     bool delKey( const std::string& section, const std::string& key );
    66 
    67 public:
    68     // 返回一个section的map键值对
    69     const KeyMap& getSection(const std::string& section) const;
    70 
    71     // 返回整个ini的Sections
    72     const SectionMap& getIni() const { return m_map; }
    73 
    74 private:
    75     void saveBeforeLoad();
    76     const char* key_value(const std::string& section, const std::string& key);
    77 
    78 private:
    79     // 禁止复制构造函数和赋值操作符。
    80     IniDoc(const IniDoc& copy);
    81     IniDoc& operator=(const IniDoc& rhs);
    82 
    83 private:
    84     static const KeyMap ms_emptySection;
    85     static const char   left_tag       ;
    86     static const char   right_tag      ;
    87     static const char   equal          ;
    88     static const char   cr             ;
    89     static const char   new_line       ;
    90     static const char*  empty_str      ;
    91     static const int    BUFFER_LEN     ;
    92 
    93     SectionMap  m_map;
    94     std::string m_file_name;
    95     bool        m_modified;
    96 };
    97 
    98 #endif // INIPARSER_H
    View Code

      源文件:

      1 #include "IniDoc.h"
      2 
      3 #include <fstream>
      4 #include <strstream>
      5 
      6 using namespace std;
      7 
      8 const char  IniDoc::left_tag   = '[' ;
      9 const char  IniDoc::right_tag  = ']' ;
     10 const char  IniDoc::equal      = '=' ;
     11 const char  IniDoc::cr         = '
    ';
     12 const char  IniDoc::new_line   = '
    ';
     13 const char* IniDoc::empty_str  = ""  ;
     14 const int   IniDoc::BUFFER_LEN = 255 ;
     15 
     16 const IniDoc::KeyMap IniDoc::ms_emptySection;
     17 
     18 IniDoc::IniDoc() : m_modified(false)
     19 {
     20 
     21 }
     22 
     23 IniDoc::IniDoc(const std::string& file_name) : m_modified(false)
     24 {
     25     load(file_name);
     26 }
     27 
     28 IniDoc::~IniDoc()
     29 {
     30     if(m_modified)
     31         save();
     32 }
     33 
     34 void IniDoc::saveBeforeLoad()
     35 {
     36     if(m_modified)
     37         save();
     38 
     39     m_file_name.resize(0);
     40 
     41     m_map.clear();
     42 
     43     m_modified = false;
     44 }
     45 
     46 const char* IniDoc::key_value(const std::string& section, const std::string& key)
     47 {
     48     SectionIterator itSection = m_map.find(section);
     49     if(m_map.end() != itSection)
     50     {
     51         KeyIterator itKey = itSection->second.find(key);
     52         if(itKey != itSection->second.end())
     53             return itKey->second.c_str();
     54     }
     55 
     56     return 0;
     57 }
     58 
     59 bool IniDoc::load(const std::string& file_name)
     60 {
     61     saveBeforeLoad();
     62 
     63     ifstream file(file_name);
     64     if(!file)
     65         return false;
     66 
     67     file.seekg(0, ios::end);
     68     long len = file.tellg();
     69     if(len < 0)
     70         return false;
     71 
     72 
     73     char* buffer = new char[len + 1];
     74     if(0 == buffer)
     75         return false;
     76 
     77 
     78     file.seekg(0, ios::beg);
     79     file.read(buffer, len);
     80 
     81     buffer[len = file.gcount()] = 0;
     82 
     83     loadString(buffer);
     84     m_file_name = file_name;
     85 
     86     delete[] buffer;
     87 
     88     return true;
     89 }
     90 
     91 bool IniDoc::loadString(const std::string& str)
     92 {
     93     saveBeforeLoad();
     94 
     95     unsigned long length = str.size();
     96 
     97     if (str.size() == 0)
     98         return false;
     99 
    100     enum status
    101     {
    102         after_left_tag,
    103         after_section_name,
    104         after_section_name_ws,
    105         after_key_name,
    106         after_key_name_ws,
    107         after_equal,
    108         start
    109     };
    110 
    111     string section;                       // 当前 section.
    112     string key;                           // 当前 key.
    113     status sta          = start;          // 解析状态.
    114     const char* p       = str.c_str();    // 当前解析字符串的位置.
    115     const char* beg     = p;              // 当前元素的开始.
    116     const char* last_ws = p;              // 最后一个空格字符.
    117 
    118     for(; length; ++p, --length)
    119     {
    120         if(new_line == *p)
    121         {
    122             if(after_equal == sta)
    123             {
    124                 if(cr == *(p - 1))
    125                     --p;
    126 
    127                 m_map[section][key] = string(beg, p - beg);
    128 
    129                 if(cr == *p)
    130                     ++p;
    131             }
    132             sta = start;
    133         }
    134         else
    135         {
    136             switch(sta)
    137             {
    138             case after_left_tag:
    139                 if(right_tag == *p)
    140                 {
    141                     sta     = start;
    142                     section = empty_str; // empty section name.
    143                 }
    144                 else if(!isspace((unsigned char)*p))
    145                 {
    146                     sta = after_section_name;
    147                     beg = p;
    148                 }
    149                 break;
    150             case after_section_name:
    151                 if(right_tag == *p)
    152                 {
    153                     sta     = start;
    154                     section = string(beg, p - beg);
    155                 }
    156                 else if(isspace((unsigned char)*p))
    157                 {
    158                     sta     = after_section_name_ws;
    159                     last_ws = p;
    160                 }
    161                 break;
    162             case after_section_name_ws:
    163                 if(right_tag == *p)
    164                 {
    165                     sta     = start;
    166                     section = string(beg, last_ws - beg);
    167                 }
    168                 else if(!isspace((unsigned char)*p))
    169                 {
    170                     sta = after_section_name;
    171                 }
    172                 break;
    173             case after_key_name:
    174                 if(equal == *p)
    175                 {
    176                     sta = after_equal;
    177                     key = string(beg, p - beg);
    178                     beg = p + 1;
    179                 }
    180                 else if(isspace((unsigned char)*p))
    181                 {
    182                     sta     = after_key_name_ws;
    183                     last_ws = p;
    184                 }
    185                 break;
    186             case after_key_name_ws:
    187                 if(equal == *p)
    188                 {
    189                     sta = after_equal;
    190                     key = string(beg, last_ws - beg);
    191                     beg = p + 1;
    192                 }
    193                 else if(!isspace((unsigned char)*p))
    194                 {
    195                     sta = after_key_name;
    196                 }
    197                 break;
    198             case start:
    199                 if(left_tag == *p)
    200                 {
    201                     sta = after_left_tag;
    202                 }
    203                 else if(equal == *p)
    204                 {
    205                     key = empty_str;  // an empty key.
    206                     sta = after_equal;
    207                     beg = p + 1;
    208                 }
    209                 else if(!isspace((unsigned char)*p))
    210                 {
    211                     sta = after_key_name;
    212                     beg = p;
    213                 }
    214                 break;
    215             }
    216         }
    217     }
    218 
    219     if(after_equal == sta)
    220         m_map[section][key] = string(beg, p - beg);
    221 
    222     return true;
    223 }
    224 
    225 bool IniDoc::save()
    226 {
    227     if(0==m_file_name.c_str() || 0==m_file_name[0])
    228         return false;    // file name invalid
    229 
    230     ofstream file(m_file_name.c_str());
    231     if(!file)
    232         return false;
    233 
    234     for(SectionMap::iterator itApp=m_map.begin(); itApp!=m_map.end(); ++itApp)
    235     {
    236         file << left_tag << itApp->first << right_tag << endl;
    237 
    238         for(KeyMap::iterator itKey=itApp->second.begin(); itKey!=itApp->second.end(); ++itKey)
    239             file << itKey->first << equal << itKey->second << endl;
    240 
    241         file << endl;
    242     }
    243     m_modified = false;
    244 
    245     return true;
    246 }
    247 
    248 bool IniDoc::saveAs(const std::string& file_name)
    249 {
    250     string old_file_name = m_file_name;
    251     m_file_name = file_name;
    252 
    253     if(save())
    254         return true;
    255 
    256     m_file_name = old_file_name;
    257     return false;
    258 }
    259 
    260 long IniDoc::getInteger(const std::string& section, const std::string& key, long def_val)
    261 {
    262     istrstream(key_value(section, key)) >> def_val;
    263     return def_val;
    264 }
    265 
    266 float IniDoc::getFloat(const std::string& section, const std::string& key, float def_val)
    267 {
    268     istrstream(key_value(section, key)) >> def_val;
    269     return def_val;
    270 }
    271 
    272 long IniDoc::getStruct(const std::string& section, const std::string& key_, void* buffer, long size)
    273 {
    274     std::string key = key_value(section, key_);
    275 
    276     if (key.size() == 0)
    277         return 0;
    278 
    279     const char* p        = key.c_str();
    280     char*       dst      = (char*)buffer;
    281     long        read_len = 0;
    282     char        value;
    283 
    284     while(*p && read_len<size)
    285     {
    286         switch(*p)
    287         {
    288         case '0': case '1': case '2': case '3': case '4':
    289         case '5': case '6': case '7': case '8': case '9':
    290             value = *p - '0';
    291             break;
    292         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    293             value = *p - 'a' + 10;
    294             break;
    295         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    296             value = *p - 'A' + 10;
    297             break;
    298         default:
    299             return read_len;
    300         }
    301 
    302 
    303         if(0 == (p - key.c_str())%2)
    304             *(dst + read_len) = value << 4;
    305         else
    306             *(dst + read_len) = (*(dst + read_len) & 0xf0) + value;
    307 
    308 
    309         if(0 == (++p - key.c_str())%2)
    310             ++read_len;
    311     }
    312 
    313     return read_len;
    314 }
    315 
    316 long IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val, std::string& dst_str)
    317 {
    318     std::string key = key_value(section, key_);
    319     dst_str = key.length() ? key : def_val;
    320     return dst_str.length();
    321 }
    322 
    323 const std::string IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val)
    324 {
    325     std::string key = key_value(section, key_);
    326     if(key.length() == 0)
    327         key = def_val;
    328 
    329     return key;
    330 }
    331 
    332 void IniDoc::setInteger(const std::string& section, const std::string& key, long value)
    333 {
    334     char buffer[BUFFER_LEN + 1];
    335     ostrstream ostr(buffer, BUFFER_LEN);
    336     ostr << value;
    337     buffer[ostr.pcount()] = 0;
    338     setString(section, key, buffer);
    339 }
    340 
    341 void IniDoc::setFloat(const std::string& section, const std::string& key, float value)
    342 {
    343     char buffer[BUFFER_LEN + 1];
    344     ostrstream ostr(buffer, BUFFER_LEN);
    345     ostr << value;
    346     buffer[ostr.pcount()] = 0;
    347     setString(section, key, buffer);
    348 }
    349 
    350 inline char bin2hex(char bin)
    351 {
    352     return bin<10 ? bin+'0' : bin-10+'A';
    353 }
    354 
    355 void IniDoc::setStruct(const std::string& section, const std::string& key, const void* buffer, long size)
    356 {
    357     char* dst = new char[size*2 + 1];
    358     if(dst)
    359     {
    360         const char* src = (const char*)buffer;
    361         long i=0;
    362         for(i=0; i<size; ++i)
    363         {
    364             dst[i << 1]       = bin2hex((src[i] >> 4) & 0x0f );
    365             dst[(i << 1) + 1] = bin2hex(src[i] & 0x0f);
    366         }
    367 
    368         dst[i << 1] = 0;
    369         setString(section, key, dst);
    370 
    371         delete[] dst;
    372     }
    373 }
    374 
    375 void IniDoc::setString(const std::string& section, const std::string& key, const std::string& value)
    376 {
    377     m_map[section][key] = value;
    378     m_modified = true;
    379 }
    380 
    381 bool IniDoc::delSection( const std::string& section )
    382 {
    383     SectionIterator itSection = m_map.find(section);
    384     if(m_map.end() != itSection)
    385     {
    386         m_map.erase(itSection);
    387         return true;
    388     }
    389     return false;
    390 }
    391 
    392 bool IniDoc::delKey( const std::string& section, const std::string& key )
    393 {
    394     SectionIterator itSection = m_map.find(section);
    395     if(m_map.end() != itSection)
    396     {
    397         KeyIterator itKey = itSection->second.find(key);
    398         if(itKey != itSection->second.end())
    399         {
    400             itSection->second.erase(itKey);
    401             return true;
    402         }
    403     }
    404     return false;
    405 }
    406 
    407 const IniDoc::KeyMap& IniDoc::getSection(const std::string& section) const
    408 {
    409     SectionMap::const_iterator itApp = m_map.find(section);
    410     return m_map.end()==itApp ? ms_emptySection : itApp->second;
    411 }
    View Code

      

  • 相关阅读:
    centOS操作磁盘(命令行)
    TCP学习记录
    公务员考试考什么
    从动物科学到乐队鼓手,腾讯技术小哥的开源人生
    HarmonyOS实战—实现相亲APP
    oracle 以某个字符拆分成多行
    微信小程序预览 word、excel、ppt、pdf 等文件
    微信小程序相关问题排查技巧
    html 保留空格
    (转载)currentColor 让 CSS 更简短
  • 原文地址:https://www.cnblogs.com/kanite/p/9182640.html
Copyright © 2011-2022 走看看