iniparser.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #include "iniparser.h"
  2. #include "hdef.h"
  3. #include "herr.h"
  4. #include "hstring.h"
  5. #include "hfile.h"
  6. #include "hbase.h"
  7. #include <sstream>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. IniParser::IniParser() {
  12. _comment = DEFAULT_INI_COMMENT;
  13. _delim = DEFAULT_INI_DELIM;
  14. root_ = NULL;
  15. }
  16. IniParser::~IniParser() {
  17. Unload();
  18. }
  19. int IniParser::Unload() {
  20. SAFE_DELETE(root_);
  21. return 0;
  22. }
  23. int IniParser::Reload() {
  24. return LoadFromFile(_filepath.c_str());
  25. }
  26. int IniParser::LoadFromFile(const char* filepath) {
  27. _filepath = filepath;
  28. HFile file;
  29. if (file.open(filepath, "r") != 0) {
  30. return ERR_OPEN_FILE;
  31. }
  32. std::string str;
  33. file.readall(str);
  34. return LoadFromMem(str.c_str());
  35. }
  36. int IniParser::LoadFromMem(const char* data) {
  37. Unload();
  38. root_ = new IniNode;
  39. root_->type = IniNode::INI_NODE_TYPE_ROOT;
  40. std::stringstream ss;
  41. ss << data;
  42. std::string strLine;
  43. int line = 0;
  44. string::size_type pos;
  45. string content;
  46. string comment;
  47. string strDiv;
  48. IniNode* pScopeNode = root_;
  49. IniNode* pNewNode = NULL;
  50. while (std::getline(ss, strLine)) {
  51. ++line;
  52. content = trimL(strLine);
  53. if (content.length() == 0) {
  54. // blank line
  55. strDiv += '\n';
  56. continue;
  57. }
  58. // trim_comment
  59. comment = "";
  60. pos = content.find_first_of(_comment);
  61. if (pos != string::npos) {
  62. comment = content.substr(pos);
  63. content = content.substr(0, pos);
  64. }
  65. content = trimR(content);
  66. if (content.length() == 0) {
  67. strDiv += strLine;
  68. strDiv += '\n';
  69. continue;
  70. } else if (strDiv.length() != 0) {
  71. IniNode* pNode = new IniNode;
  72. pNode->type = IniNode::INI_NODE_TYPE_DIV;
  73. pNode->label = strDiv;
  74. pScopeNode->Add(pNode);
  75. strDiv = "";
  76. }
  77. if (content[0] == '[') {
  78. if (content[content.length()-1] == ']') {
  79. // section
  80. content = trim(content.substr(1, content.length()-2));
  81. pNewNode = new IniNode;
  82. pNewNode->type = IniNode::INI_NODE_TYPE_SECTION;
  83. pNewNode->label = content;
  84. root_->Add(pNewNode);
  85. pScopeNode = pNewNode;
  86. } else {
  87. // hlogw("format error, line:%d", line);
  88. continue; // ignore
  89. }
  90. } else {
  91. pos = content.find_first_of(_delim);
  92. if (pos != string::npos) {
  93. // key-value
  94. pNewNode = new IniNode;
  95. pNewNode->type = IniNode::INI_NODE_TYPE_KEY_VALUE;
  96. pNewNode->label = trim(content.substr(0, pos));
  97. pNewNode->value = trim(content.substr(pos+_delim.length()));
  98. pScopeNode->Add(pNewNode);
  99. } else {
  100. // hlogw("format error, line:%d", line);
  101. continue; // ignore
  102. }
  103. }
  104. if (comment.length() != 0) {
  105. // tail_comment
  106. IniNode* pNode = new IniNode;
  107. pNode->type = IniNode::INI_NODE_TYPE_SPAN;
  108. pNode->label = comment;
  109. pNewNode->Add(pNode);
  110. comment = "";
  111. }
  112. }
  113. // file end comment
  114. if (strDiv.length() != 0) {
  115. IniNode* pNode = new IniNode;
  116. pNode->type = IniNode::INI_NODE_TYPE_DIV;
  117. pNode->label = strDiv;
  118. root_->Add(pNode);
  119. }
  120. return 0;
  121. }
  122. void IniParser::DumpString(IniNode* pNode, string& str) {
  123. if (pNode == NULL) return;
  124. if (pNode->type != IniNode::INI_NODE_TYPE_SPAN) {
  125. if (str.length() > 0 && str[str.length()-1] != '\n') {
  126. str += '\n';
  127. }
  128. }
  129. switch (pNode->type) {
  130. case IniNode::INI_NODE_TYPE_SECTION: {
  131. str += '[';
  132. str += pNode->label;
  133. str += ']';
  134. }
  135. break;
  136. case IniNode::INI_NODE_TYPE_KEY_VALUE: {
  137. str += asprintf("%s %s %s", pNode->label.c_str(), _delim.c_str(), pNode->value.c_str());
  138. }
  139. break;
  140. case IniNode::INI_NODE_TYPE_DIV: {
  141. str += pNode->label;
  142. }
  143. break;
  144. case IniNode::INI_NODE_TYPE_SPAN: {
  145. str += '\t';
  146. str += pNode->label;
  147. }
  148. break;
  149. default:
  150. break;
  151. }
  152. for (auto p : pNode->children) {
  153. DumpString(p, str);
  154. }
  155. }
  156. string IniParser::DumpString() {
  157. string str;
  158. DumpString(root_, str);
  159. return str;
  160. }
  161. int IniParser::Save() {
  162. return SaveAs(_filepath.c_str());
  163. }
  164. int IniParser::SaveAs(const char* filepath) {
  165. string str = DumpString();
  166. if (str.length() == 0) {
  167. return 0;
  168. }
  169. HFile file;
  170. if (file.open(filepath, "w") != 0) {
  171. return ERR_SAVE_FILE;
  172. }
  173. file.write(str.c_str(), str.length());
  174. return 0;
  175. }
  176. string IniParser::GetValue(const string& key, const string& section) {
  177. if (root_ == NULL) return "";
  178. IniNode* pSection = root_;
  179. if (section.length() != 0) {
  180. pSection = root_->Get(section, IniNode::INI_NODE_TYPE_SECTION);
  181. if (pSection == NULL) return "";
  182. }
  183. IniNode* pKV = pSection->Get(key, IniNode::INI_NODE_TYPE_KEY_VALUE);
  184. if (pKV == NULL) return "";
  185. return pKV->value;
  186. }
  187. void IniParser::SetValue(const string& key, const string& value, const string& section) {
  188. if (root_ == NULL) {
  189. root_ = new IniNode;
  190. }
  191. IniNode* pSection = root_;
  192. if (section.length() != 0) {
  193. pSection = root_->Get(section, IniNode::INI_NODE_TYPE_SECTION);
  194. if (pSection == NULL) {
  195. pSection = new IniNode;
  196. pSection->type = IniNode::INI_NODE_TYPE_SECTION;
  197. pSection->label = section;
  198. root_->Add(pSection);
  199. }
  200. }
  201. IniNode* pKV = pSection->Get(key, IniNode::INI_NODE_TYPE_KEY_VALUE);
  202. if (pKV == NULL) {
  203. pKV = new IniNode;
  204. pKV->type = IniNode::INI_NODE_TYPE_KEY_VALUE;
  205. pKV->label = key;
  206. pSection->Add(pKV);
  207. }
  208. pKV->value = value;
  209. }
  210. template<>
  211. bool IniParser::Get(const string& key, const string& section, bool defvalue) {
  212. string str = GetValue(key, section);
  213. return str.empty() ? defvalue : getboolean(str.c_str());
  214. }
  215. template<>
  216. int IniParser::Get(const string& key, const string& section, int defvalue) {
  217. string str = GetValue(key, section);
  218. return str.empty() ? defvalue : atoi(str.c_str());
  219. }
  220. template<>
  221. float IniParser::Get(const string& key, const string& section, float defvalue) {
  222. string str = GetValue(key, section);
  223. return str.empty() ? defvalue : atof(str.c_str());
  224. }
  225. template<>
  226. void IniParser::Set(const string& key, const bool& value, const string& section) {
  227. SetValue(key, value ? "true" : "false", section);
  228. }
  229. template<>
  230. void IniParser::Set(const string& key, const int& value, const string& section) {
  231. SetValue(key, asprintf("%d", value), section);
  232. }
  233. template<>
  234. void IniParser::Set(const string& key, const float& value, const string& section) {
  235. SetValue(key, asprintf("%f", value), section);
  236. }