#pragma once
#include <fstream>
#include <functional>
#include <string>
#include <unordered_map>
namespace Config {
class Ini {
public:
void Dump(std::function<void(const std::string&, const std::string&, const std::string&)> deal) {
auto iter = cfg_.begin();
while (iter != cfg_.end()) {
auto kv_iter = iter->second.begin();
while (kv_iter != iter->second.end()) {
deal(iter->first, kv_iter->first, kv_iter->second);
++kv_iter;
}
++iter;
}
}
bool Load(std::string file_name) {
if (file_name == "") return false;
std::ifstream in;
std::string line;
in.open(file_name.c_str());
if (not in.is_open()) return false;
while (getline(in, line)) {
std::string section, key, value;
if (not parseLine(line, section, key, value)) {
continue;
}
setSectionKeyValue(section, key, value);
}
return true;
}
void GetStrValue(const std::string& section, const std::string& key, std::string& value, std::string default_value) {
value = default_value;
if (cfg_.find(section) == cfg_.end()) {
return;
}
if (cfg_[section].find(key) == cfg_[section].end()) {
return;
}
value = cfg_[section][key];
}
void GetIntValue(const std::string& section, const std::string& key, int64_t& value, int64_t default_value) {
value = default_value;
if (cfg_.find(section) == cfg_.end()) {
return;
}
if (cfg_[section].find(key) == cfg_[section].end()) {
return;
}
value = atol(cfg_[section][key].c_str());
}
private:
void ltrim(std::string& str) {
if (str.empty()) return;
size_t len = 0;
char* temp = (char*)str.c_str();
while (*temp && isblank(*temp)) {
++len;
++temp;
}
if (len > 0) str.erase(0, len);
}
void rtrim(std::string& str) {
if (str.empty()) return;
size_t len = str.length();
size_t pos = len;
while (pos > 0) {
if (not isblank(str[pos - 1])) {
break;
}
--pos;
}
if (pos != len) str.erase(pos);
}
void trim(std::string& str) {
ltrim(str);
rtrim(str);
}
void setSectionKeyValue(std::string& section, std::string& key, std::string& value) {
if (cfg_.find(section) == cfg_.end()) {
std::unordered_map<std::string, std::string> kv_map;
cfg_[section] = kv_map;
}
if (key != "" && value != "") cfg_[section][key] = value;
}
bool parseLine(std::string& line, std::string& section, std::string& key, std::string& value) {
static std::string cur_section = "";
std::string nodes[2] = {"#", ";"}; //去掉注释的内容
for (int i = 0; i < 2; ++i) {
std::string::size_type pos = line.find(nodes[i]);
if (pos != std::string::npos) line.erase(pos);
}
trim(line);
if (line == "") return false;
if (line[0] == '[' && line[line.size() - 1] == ']') {
section = line.substr(1, line.size() - 2);
trim(section);
cur_section = section;
return false;
}
if (cur_section == "") return false;
bool is_key = true;
for (size_t i = 0; i < line.size(); ++i) {
if (line[i] == '=') {
is_key = false;
continue;
}
if (is_key) {
key += line[i];
} else {
value += line[i];
}
}
section = cur_section;
trim(key);
trim(value);
return true;
}
private:
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> cfg_;
}; // ini格式配置文件的读取
} // namespace Config
|