INI.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //
  2. // Created by xcbosa on 2023/1/30.
  3. //
  4. #include "INI.h"
  5. #include "utils.h"
  6. namespace xc {
  7. namespace utils {
  8. static vector<string> split(const string& str, const string& delim) {
  9. vector<string> res;
  10. if ("" == str) return res;
  11. char * strs = new char[str.length() + 1];
  12. strcpy(strs, str.c_str());
  13. char * d = new char[delim.length() + 1];
  14. strcpy(d, delim.c_str());
  15. char *p = strtok(strs, d);
  16. while(p) {
  17. string s = p;
  18. res.push_back(s);
  19. p = strtok(NULL, d);
  20. }
  21. return res;
  22. }
  23. static string& replace_all(string& src, const string& old_value, const string& new_value) {
  24. for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) {
  25. if ((pos = src.find(old_value, pos)) != string::npos) {
  26. src.replace(pos, old_value.length(), new_value);
  27. }
  28. else break;
  29. }
  30. return src;
  31. }
  32. static std::string& trim(std::string &s) {
  33. if (s.empty()) { return s; }
  34. s.erase(0,s.find_first_not_of(" "));
  35. s.erase(s.find_last_not_of(" ") + 1);
  36. return s;
  37. }
  38. INISection::INISection(): title(), data() { }
  39. INISection::INISection(string title, map<string, string> data): title(title), data(data) { }
  40. string INISection::get(string key) {
  41. return this->data[key];
  42. }
  43. bool INISection::has(string key) {
  44. return this->data.count(key) == 1;
  45. }
  46. void INISection::set(string key, string value) {
  47. this->data[key] = value;
  48. }
  49. string INISection::getTitle() {
  50. return this->title;
  51. }
  52. void INISection::setTitle(string title) {
  53. this->title = title;
  54. }
  55. INI::INI(): data() { }
  56. INI::INI(string str) {
  57. vector<string> lines = split(str, "\n");
  58. string sectionName = "";
  59. map<string, string> currentSection;
  60. for (string it : lines) {
  61. string line = it;
  62. replace_all(line, "\r", "");
  63. if (line.length() == 0) { continue; }
  64. if (line[0] == '[') {
  65. if (sectionName.length() > 0 || !currentSection.empty()) {
  66. this->data.push_back(INISection(sectionName, currentSection));
  67. sectionName.clear();
  68. currentSection.clear();
  69. }
  70. ostringstream oss;
  71. for (string::iterator it = line.begin() + 1; it != line.end() && *it != ']'; it++) {
  72. oss << *it;
  73. }
  74. sectionName = oss.str();
  75. continue;
  76. }
  77. ostringstream left, right;
  78. bool isRight = false;
  79. for (int i = 0; i < line.length(); i++) {
  80. if (isRight) {
  81. right << line[i];
  82. continue;
  83. }
  84. if (line[i] == '=') {
  85. isRight = true;
  86. continue;
  87. }
  88. left << line[i];
  89. }
  90. string leftStr = left.str();
  91. string rightStr = right.str();
  92. trim(leftStr);
  93. trim(rightStr);
  94. currentSection[leftStr] = rightStr;
  95. }
  96. if (sectionName.length() > 0 || !currentSection.empty()) {
  97. this->data.push_back(INISection(sectionName, currentSection));
  98. sectionName.clear();
  99. currentSection.clear();
  100. }
  101. }
  102. INI::INI(vector<INISection> data): data(data) { }
  103. INI readFromFile(string filePath) {
  104. return INI(contentsOfTextFile(filePath));
  105. }
  106. bool INI::has(string header) {
  107. return this->get(header) != nullptr;
  108. }
  109. INISection* INI::get(string header) {
  110. for (auto it = this->data.begin(); it != this->data.end(); it++) {
  111. if (it->title == header) {
  112. return &*it;
  113. }
  114. }
  115. return nullptr;
  116. }
  117. INISection *INI::getMust(string header) {
  118. INISection *section = this->get(header);
  119. if (section == nullptr) {
  120. this->data.push_back(INISection(header, map<string, string>()));
  121. return this->getMust(header);
  122. }
  123. return section;
  124. }
  125. void INI::remove(string header) {
  126. std::remove_if(this->data.begin(), this->data.end(), [&header](auto it) {
  127. return it.title == header;
  128. });
  129. }
  130. string INI::getINIString() {
  131. ostringstream oss;
  132. for (INISection section : this->data) {
  133. oss << '[';
  134. oss << section.title;
  135. oss << "]\n";
  136. for (auto it : section.data) {
  137. oss << it.first;
  138. oss << " = ";
  139. oss << it.second;
  140. oss << '\n';
  141. }
  142. oss << '\n';
  143. }
  144. return oss.str();
  145. }
  146. INIFile::INIFile(string filePath): INI(contentsOfTextFile(filePath)) {
  147. this->filePath = filePath;
  148. }
  149. void INIFile::save() {
  150. saveTextFile(this->filePath, this->getINIString());
  151. }
  152. } // xc
  153. } // utils