#include <iostream>
#include <string>
#include <unordered_map>
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/ini_parser.hpp"
enum {
STRING = 1,
INT = 2,
ARRAY = 3,
DATE = 4,
DATETIME = 5
};
struct ConfigField {
enum class Type {
_STRING,
_INT,
_BOOLEAN
};
const Type type;
void *value;
bool encrypt;
const std::string default_value;
};
#define CONFIG_FIELD(key, type, value, encrypt, default_value) \
{key, ConfigField{ConfigField::Type::_ ##type, value, encrypt, #default_value}}
class Configure : public boost::noncopyable {
public:
inline static Configure &instance() {
static Configure obj;
return obj;
}
bool parse_config(const char *ini_path) {
boost::property_tree::ptree config_tree;
try {
boost::property_tree::ini_parser::read_ini(ini_path,config_tree);
}
catch(boost::property_tree::ini_parser_error &ex) {
std::cerr << "parse configure exception = " <<ex.what() << std::endl;
return false;
}
catch (...) {
std::cerr << "parse configure exception = unknow expection." << std::endl;
return false;
}
for(auto &config_field_map : config_field_map_) {
auto &config_field_key = config_field_map.first;
auto &config_field = config_field_map.second;
switch (config_field.type) {
case ConfigField::Type::_STRING:
std::string *value = static_cast<std::string *>(config_field.value);
try {
*value = config_tree.get<std::string>(config_field_key);
std::cout << "key = " << config_field_key << " value = " << *value << std::endl;
}
catch (boost::property_tree::ini_parser_error &ex) {
std::cerr << "parse configure field exception = " <<ex.what() << std::endl;
return false;
}
catch (...) {
std::cerr << "parse configure field exception = unknow expection." << std::endl;
return false;
}
if (true == encrypt_ && true == config_field.encrypt && false == value->empty()) {
// todo encrypt value
}
break;
}
}
return true;
}
void set_encrypt(bool encrypt = true) {
encrypt_ = encrypt;
}
class Global {
public:
std::string log_file_;
};
class Server {
public:
std::string ip_;
};
private:
Configure() {
encrypt_ = false;
config_field_map_ = {
CONFIG_FIELD("global.log_file", STRING, &global_.log_file_, false, "./test.log"),
CONFIG_FIELD("server.ip", STRING, &server_.ip_, false, "127.0.0.1")
};
}
private:
bool encrypt_;
Global global_;
Server server_;
std::unordered_map<std::string, ConfigField>config_field_map_;
};
int main() {
if (false == Configure::instance().parse_config("./test.ini")) {
return -1;
}

return 0;
}

test.ini

[global]
log_file=12
[server]
ip=123