iniparser.cpp 5.8 KB

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