iniparser.cpp 6.4 KB

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