#include <string>
#include <map>
#include <algorithm>
#ifdef _WIN32
#pragma warning(disable:4996)
#include <windows.h>
#include <io.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi")
#endif
#define RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/reader.h"
#include "rapidjson/prettywriter.h"
using rapidjson::Document;
using rapidjson::StringBuffer;
using rapidjson::PrettyWriter;
using rapidjson::Value;
std::string readFileContent(const std::string &filename, bool isBinary, size_t limitSize, size_t beginIndex)
{
FILE *f = fopen(filename.c_str(), "rb");
if (f == NULL)
{
return "";
}
size_t fileLen = 0;
fseek(f, 0, SEEK_SET);
fileLen = ftell(f);
fseek(f, 0, SEEK_END);
fileLen = ftell(f) - fileLen;
if (fileLen >= 3 && !isBinary && beginIndex == 0)
{
char buff[3];
fread(buff, 1, 3, f);
if ((unsigned char)buff[0] == 0xef
&& (unsigned char)buff[1] == 0xbb
&& (unsigned char)buff[2] == 0xbf)
{
beginIndex = 3;
}
}
if (beginIndex >= fileLen)
{
fclose(f);
return "";
}
if (limitSize > fileLen - beginIndex)
{
limitSize = fileLen - beginIndex;
}
fseek(f, (long)beginIndex, SEEK_SET);
std::string ret;
ret.resize(limitSize, '\0');
size_t readLen = fread(&ret[0], 1, limitSize, f);
fclose(f);
if (readLen < limitSize)
{
return ret.substr(0, readLen);
}
return std::move(ret);
}
size_t writeFileContent(const std::string &filename, const char *buff, size_t buffLen, bool isAppend)
{
std::string mod = "ab+";
if (!isAppend)
{
mod = "wb+";
}
FILE *f = fopen(filename.c_str(), mod.c_str());
if (f == NULL)
{
return 0;
}
size_t writeLen = fwrite(buff, 1, buffLen, f);
fclose(f);
return writeLen;
}
bool accessFile(const std::string &pathfile)
{
#ifdef _WIN32
return ::_access(pathfile.c_str(), 0) == 0;
#else
return ::access(pathfile.c_str(), F_OK) == 0;
#endif
}
bool isDirectory(const std::string & path)
{
#ifdef _WIN32
return PathIsDirectoryA(path.c_str()) ? true : false;
#else
DIR * pdir = opendir(path.c_str());
if (pdir == NULL)
{
return false;
}
else
{
closedir(pdir);
pdir = NULL;
return true;
}
#endif
}
bool createDirectory(std::string path)
{
if (path.empty()) return false;
std::string sub;
for (std::string::iterator iter = path.begin(); iter != path.end(); ++iter)
{
if (*iter == '\\') { *iter = '/'; }
}
if (path.at(path.length() - 1) != '/') { path.append("/"); }
std::string::size_type pos = path.find('/');
while (pos != std::string::npos)
{
std::string cur = path.substr(0, pos - 0);
if (cur.length() > 0 && !isDirectory(cur))
{
bool ret = false;
#ifdef WIN32
ret = CreateDirectoryA(cur.c_str(), NULL) ? true : false;
#else
ret = (mkdir(cur.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
#endif
if (!ret)
{
return false;
}
}
pos = path.find('/', pos + 1);
}
return true;
}
std::string g_config_file_name="./config/config";
void setConfigFile(const std::string &file_name)
{
g_config_file_name = file_name;
auto ret = g_config_file_name;
std::for_each(ret.begin(), ret.end(), [](char &ch) { if (ch == '\\') ch = '/'; });
auto pos=ret.find_last_of('/');
auto path = ret.substr(0, pos);
if (!isDirectory(path))createDirectory(path);
}
std::string getConfig(const std::string &key)
{
std::string content = readFileContent(g_config_file_name, false, 1024 * 1024, 0);
if (content == "")return "";
Document doc;
doc.Parse(content);
if (doc.HasParseError())return "";
std::map<std::string, std::string> params;
if (doc.HasMember("config") && doc["config"].IsArray())
{
for (auto &p : doc["config"].GetArray())
{
params.insert(std::make_pair(p["name"].GetString(), p["value"].GetString()));
}
if (params.find(key) != params.end())return params[key];
else return "";
}
else return "";
}
void setConfig(const std::string &key, const std::string &value)
{
auto ret = g_config_file_name;
std::for_each(ret.begin(), ret.end(), [](char &ch) { if (ch == '\\') ch = '/'; });
auto pos = ret.find_last_of('/');
auto path = ret.substr(0, pos);
if (!isDirectory(path))createDirectory(path);
std::string content = readFileContent(g_config_file_name, false, 1024 * 1024, 0);
Document doc;
doc.Parse(content);
if (content == "" || doc.HasParseError())
{
//新建
Document doc_new(rapidjson::kObjectType);
Value v(rapidjson::kArrayType);
Value tmp(rapidjson::kObjectType);
tmp.AddMember("name", key, doc.GetAllocator());
tmp.AddMember("value", value, doc.GetAllocator());
v.PushBack(tmp, doc.GetAllocator());
doc_new.AddMember("config", v, doc.GetAllocator());
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
doc_new.Accept(writer);
std::string res(buffer.GetString());
writeFileContent(g_config_file_name, res.data(), res.size(), false);
}
else
{
std::map<std::string, std::string> params;
if (doc.HasMember("config") && doc["config"].IsArray())
{
for (auto &p : doc["config"].GetArray())
{
params.insert(std::make_pair(p["name"].GetString(), p["value"].GetString()));
}
}
params[key] = value;
Document doc_new(rapidjson::kObjectType);
Value v(rapidjson::kArrayType);
for (const auto &p : params) {
Value tmp(rapidjson::kObjectType);
tmp.AddMember("name", p.first, doc.GetAllocator());
tmp.AddMember("value", p.second, doc.GetAllocator());
v.PushBack(tmp, doc.GetAllocator());
}
doc_new.AddMember("config", v, doc.GetAllocator());
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
doc_new.Accept(writer);
std::string res(buffer.GetString());
writeFileContent(g_config_file_name, res.data(), res.size(), false);
}
}
#pragma once
#ifndef _LIB_CONFIG_H_
#define _LIB_CONFIG_H_
#include <string>
void setConfigFile(const std::string &file_name);
std::string getConfig(const std::string &key);
void setConfig(const std::string &key, const std::string &value);
#endif // _LIB_CONFIG_H_