在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 = 'r';
12 const char IniDoc::new_line = 'n';
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
原文链接: https://www.cnblogs.com/kanite/p/9182640.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/275986
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!