inifile.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. #ifndef _INIFILE_CPP
  2. #define _INIFILE_CPP
  3. #include "inifile.h"
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. namespace inifile
  8. {
  9. int INI_BUF_SIZE = 2048;
  10. IniFile::IniFile()
  11. {
  12. flags_.push_back("#");
  13. flags_.push_back(";");
  14. }
  15. bool IniFile::parse(const string &content, string &key, string &value, char c/*= '='*/)
  16. {
  17. int i = 0;
  18. int len = content.length();
  19. while (i < len && content[i] != c) {
  20. ++i;
  21. }
  22. if (i >= 0 && i < len) {
  23. key = string(content.c_str(), i);
  24. value = string(content.c_str() + i + 1, len - i - 1);
  25. trim(key);
  26. trim(value);
  27. return true;
  28. }
  29. return false;
  30. }
  31. int IniFile::getline(string &str, FILE *fp)
  32. {
  33. int plen = 0;
  34. int buf_size = INI_BUF_SIZE * sizeof(char);
  35. char *buf = (char *) malloc(buf_size);
  36. char *pbuf = NULL;
  37. char *p = buf;
  38. if (buf == NULL) {
  39. fprintf(stderr, "no enough memory!exit!\n");
  40. exit(-1);
  41. }
  42. memset(buf, 0, buf_size);
  43. int total_size = buf_size;
  44. while (fgets(p, buf_size, fp) != NULL) {
  45. plen = strlen(p);
  46. if (plen > 0 && p[plen - 1] != '\n' && !feof(fp)) {
  47. total_size = strlen(buf) + buf_size;
  48. pbuf = (char *)realloc(buf, total_size);
  49. if (pbuf == NULL) {
  50. free(buf);
  51. fprintf(stderr, "no enough memory!exit!\n");
  52. exit(-1);
  53. }
  54. buf = pbuf;
  55. p = buf + strlen(buf);
  56. continue;
  57. } else {
  58. break;
  59. }
  60. }
  61. str = buf;
  62. free(buf);
  63. buf = NULL;
  64. return str.length();
  65. }
  66. int IniFile::load(const string &filename)
  67. {
  68. release();
  69. fname_ = filename;
  70. IniSection *section = NULL;
  71. FILE *fp = fopen(filename.c_str(), "r");
  72. if (fp == NULL) {
  73. return -1;
  74. }
  75. string line;
  76. string comment;
  77. //增加默认段
  78. section = new IniSection();
  79. sections_[""] = section;
  80. while (getline(line, fp) > 0) {
  81. trimright(line, '\n');
  82. trimright(line, '\r');
  83. trim(line);
  84. if (!isComment(line)) {
  85. /* 针对 “value=1 #测试” 这种后面有注释的语句
  86. * 重新分割line,并添加注释到commnet
  87. * 注意:这种情况保存后会变成
  88. * #测试
  89. * value=1
  90. * */
  91. string subline;
  92. string tmp = line;
  93. for (size_t i = 0; i < flags_.size(); ++i) {
  94. subline = line.substr(0, line.find(flags_[i]));
  95. line = subline;
  96. }
  97. comment += tmp.substr(line.length());
  98. }
  99. trim(line);
  100. if (line.length() <= 0) {
  101. continue;
  102. }
  103. if (line[0] == '[') {
  104. section = NULL;
  105. int index = line.find_first_of(']');
  106. if (index == -1) {
  107. fclose(fp);
  108. fprintf(stderr, "没有找到匹配的]\n");
  109. return -1;
  110. }
  111. int len = index - 1;
  112. if (len <= 0) {
  113. fprintf(stderr, "段为空\n");
  114. continue;
  115. }
  116. string s(line, 1, len);
  117. if (getSection(s.c_str()) != NULL) {
  118. fclose(fp);
  119. fprintf(stderr, "此段已存在:%s\n", s.c_str());
  120. return -1;
  121. }
  122. section = new IniSection();
  123. sections_[s] = section;
  124. section->name = s;
  125. section->comment = comment;
  126. comment = "";
  127. } else if (isComment(line)) {
  128. if (comment != "") {
  129. comment += delim + line ;
  130. } else {
  131. comment = line;
  132. }
  133. } else {
  134. string key, value;
  135. if (parse(line, key, value)) {
  136. IniItem item;
  137. item.key = key;
  138. item.value = value;
  139. item.comment = comment;
  140. section->items.push_back(item);
  141. } else {
  142. fprintf(stderr, "解析参数失败[%s]\n", line.c_str());
  143. }
  144. comment = "";
  145. }
  146. }
  147. fclose(fp);
  148. return 0;
  149. }
  150. int IniFile::save()
  151. {
  152. return saveas(fname_);
  153. }
  154. int IniFile::saveas(const string &filename)
  155. {
  156. string data = "";
  157. for (iterator sect = sections_.begin(); sect != sections_.end(); ++sect) {
  158. if (sect->second->comment != "") {
  159. data += sect->second->comment;
  160. data += delim;
  161. }
  162. if (sect->first != "") {
  163. data += string("[") + sect->first + string("]");
  164. data += delim;
  165. }
  166. for (IniSection::iterator item = sect->second->items.begin(); item != sect->second->items.end(); ++item) {
  167. if (item->comment != "") {
  168. data += item->comment;
  169. data += delim;
  170. }
  171. data += item->key + "=" + item->value;
  172. data += delim;
  173. }
  174. }
  175. FILE *fp = fopen(filename.c_str(), "w");
  176. fwrite(data.c_str(), 1, data.length(), fp);
  177. fclose(fp);
  178. return 0;
  179. }
  180. IniSection *IniFile::getSection(const string &section /*=""*/)
  181. {
  182. iterator it = sections_.find(section);
  183. if (it != sections_.end()) {
  184. return it->second;
  185. }
  186. return NULL;
  187. }
  188. string IniFile::getStringValue(const string &section, const string &key, int &ret)
  189. {
  190. string value, comment;
  191. ret = getValue(section, key, value, comment);
  192. return value;
  193. }
  194. int IniFile::getIntValue(const string &section, const string &key, int &ret)
  195. {
  196. string value, comment;
  197. ret = getValue(section, key, value, comment);
  198. return atoi(value.c_str());
  199. }
  200. double IniFile::getDoubleValue(const string &section, const string &key, int &ret)
  201. {
  202. string value, comment;
  203. ret = getValue(section, key, value, comment);
  204. return atof(value.c_str());
  205. }
  206. int IniFile::getValue(const string &section, const string &key, string &value)
  207. {
  208. string comment;
  209. return getValue(section, key, value, comment);
  210. }
  211. int IniFile::getValue(const string &section, const string &key, string &value, string &comment)
  212. {
  213. IniSection *sect = getSection(section);
  214. if (sect != NULL) {
  215. for (IniSection::iterator it = sect->begin(); it != sect->end(); ++it) {
  216. if (it->key == key) {
  217. value = it->value;
  218. comment = it->comment;
  219. return RET_OK;
  220. }
  221. }
  222. }
  223. return RET_ERR;
  224. }
  225. int IniFile::getValues(const string &section, const string &key, vector<string> &values)
  226. {
  227. vector<string> comments;
  228. return getValues(section, key, values, comments);
  229. }
  230. int IniFile::getValues(const string &section, const string &key,
  231. vector<string> &values, vector<string> &comments)
  232. {
  233. string value, comment;
  234. values.clear();
  235. comments.clear();
  236. IniSection *sect = getSection(section);
  237. if (sect != NULL) {
  238. for (IniSection::iterator it = sect->begin(); it != sect->end(); ++it) {
  239. if (it->key == key) {
  240. value = it->value;
  241. comment = it->comment;
  242. values.push_back(value);
  243. comments.push_back(comment);
  244. }
  245. }
  246. }
  247. return (values.size() ? RET_OK : RET_ERR);
  248. }
  249. bool IniFile::hasSection(const string &section)
  250. {
  251. return (getSection(section) != NULL);
  252. }
  253. bool IniFile::hasKey(const string &section, const string &key)
  254. {
  255. IniSection *sect = getSection(section);
  256. if (sect != NULL) {
  257. for (IniSection::iterator it = sect->begin(); it != sect->end(); ++it) {
  258. if (it->key == key) {
  259. return true;
  260. }
  261. }
  262. }
  263. return false;
  264. }
  265. int IniFile::getSectionComment(const string &section, string &comment)
  266. {
  267. comment = "";
  268. IniSection *sect = getSection(section);
  269. if (sect != NULL) {
  270. comment = sect->comment;
  271. return RET_OK;
  272. }
  273. return RET_ERR;
  274. }
  275. int IniFile::setSectionComment(const string &section, const string &comment)
  276. {
  277. IniSection *sect = getSection(section);
  278. if (sect != NULL) {
  279. sect->comment = comment;
  280. return RET_OK;
  281. }
  282. return RET_ERR;
  283. }
  284. int IniFile::setValue(const string &section, const string &key,
  285. const string &value, const string &comment /*=""*/)
  286. {
  287. IniSection *sect = getSection(section);
  288. string comt = comment;
  289. if (comt != "") {
  290. comt = flags_[0] + comt;
  291. }
  292. if (sect == NULL) {
  293. sect = new IniSection();
  294. if (sect == NULL) {
  295. fprintf(stderr, "no enough memory!\n");
  296. exit(-1);
  297. }
  298. sect->name = section;
  299. sections_[section] = sect;
  300. }
  301. for (IniSection::iterator it = sect->begin(); it != sect->end(); ++it) {
  302. if (it->key == key) {
  303. it->value = value;
  304. it->comment = comt;
  305. return RET_OK;
  306. }
  307. }
  308. //not found key
  309. IniItem item;
  310. item.key = key;
  311. item.value = value;
  312. item.comment = comt;
  313. sect->items.push_back(item);
  314. return RET_OK;
  315. }
  316. void IniFile::getCommentFlags(vector<string> &flags)
  317. {
  318. flags = flags_;
  319. }
  320. void IniFile::setCommentFlags(const vector<string> &flags)
  321. {
  322. flags_ = flags;
  323. }
  324. void IniFile::deleteSection(const string &section)
  325. {
  326. IniSection *sect = getSection(section);
  327. if (sect != NULL) {
  328. sections_.erase(section);
  329. delete sect;
  330. }
  331. }
  332. void IniFile::deleteKey(const string &section, const string &key)
  333. {
  334. IniSection *sect = getSection(section);
  335. if (sect != NULL) {
  336. for (IniSection::iterator it = sect->begin(); it != sect->end(); ++it) {
  337. if (it->key == key) {
  338. sect->items.erase(it);
  339. break;
  340. }
  341. }
  342. }
  343. }
  344. void IniFile::release()
  345. {
  346. fname_ = "";
  347. for (iterator i = sections_.begin(); i != sections_.end(); ++i) {
  348. delete i->second;
  349. }
  350. sections_.clear();
  351. }
  352. bool IniFile::isComment(const string &str)
  353. {
  354. bool ret = false;
  355. for (size_t i = 0; i < flags_.size(); ++i) {
  356. size_t k = 0;
  357. if (str.length() < flags_[i].length()) {
  358. continue;
  359. }
  360. for (k = 0; k < flags_[i].length(); ++k) {
  361. if (str[k] != flags_[i][k]) {
  362. break;
  363. }
  364. }
  365. if (k == flags_[i].length()) {
  366. ret = true;
  367. break;
  368. }
  369. }
  370. return ret;
  371. }
  372. //for debug
  373. void IniFile::print()
  374. {
  375. printf("filename:[%s]\n", fname_.c_str());
  376. printf("flags_:[");
  377. for (size_t i = 0; i < flags_.size(); ++i) {
  378. printf(" %s ", flags_[i].c_str());
  379. }
  380. printf("]\n");
  381. for (iterator it = sections_.begin(); it != sections_.end(); ++it) {
  382. printf("section:[%s]\n", it->first.c_str());
  383. printf("comment:[%s]\n", it->second->comment.c_str());
  384. for (IniSection::iterator i = it->second->items.begin(); i != it->second->items.end(); ++i) {
  385. printf(" comment:%s\n", i->comment.c_str());
  386. printf(" parm :%s=%s\n", i->key.c_str(), i->value.c_str());
  387. }
  388. }
  389. }
  390. void IniFile::trimleft(string &str, char c/*=' '*/)
  391. {
  392. //trim head
  393. int len = str.length();
  394. int i = 0;
  395. while (str[i] == c && str[i] != '\0') {
  396. i++;
  397. }
  398. if (i != 0) {
  399. str = string(str, i, len - i);
  400. }
  401. }
  402. void IniFile::trimright(string &str, char c/*=' '*/)
  403. {
  404. //trim tail
  405. int i = 0;
  406. int len = str.length();
  407. for (i = len - 1; i >= 0; --i) {
  408. if (str[i] != c) {
  409. break;
  410. }
  411. }
  412. str = string(str, 0, i + 1);
  413. }
  414. void IniFile::trim(string &str)
  415. {
  416. //trim head
  417. int len = str.length();
  418. int i = 0;
  419. while (isspace(str[i]) && str[i] != '\0') {
  420. i++;
  421. }
  422. if (i != 0) {
  423. str = string(str, i, len - i);
  424. }
  425. //trim tail
  426. len = str.length();
  427. for (i = len - 1; i >= 0; --i) {
  428. if (!isspace(str[i])) {
  429. break;
  430. }
  431. }
  432. str = string(str, 0, i + 1);
  433. }
  434. }
  435. #endif