オリジナルC++読み書きiniファイル
C++STLベースiniファイル解析クラス
GitHubリンク
GitHubリンク
/*
* @Description: ini
* @version:0.0.3 preview
* @Author: windSnowLi
* @LastEditors: windSnowLi
* @LastEditTime:2020/11/9
*/
#ifndef READWRITE_H_
#define READWRITE_H_
#include
// MSVC MingW, cstring string
#include
#include
#include
#include
#include
#include
#ifndef MAX_PATH
#define MAX_PATH 260
#endif // !MAX_PATH
namespace rwini {
enum class RwExceptionType {
RwiniException = 0, NotFoundKey = 1, NotFoundSection = 2, IniFormatError = 3, NullSectionOrKey = 4
};
class RwiniException :public std::exception {
protected:
std::string message;
public:
#ifdef _MSC_VER
virtual const char* what() const {
return message.c_str();
}
#elif __GNUC__
virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT
{
return message.c_str();
}
#endif // _MSC_VER||__BORLANDC__
virtual const rwini::RwExceptionType GetExceptionType() const {
return RwExceptionType::RwiniException;
}
};
class NotFoundKey : public RwiniException
{
public:
virtual const rwini::RwExceptionType GetExceptionType() const {
return RwExceptionType::NotFoundKey;
}
NotFoundKey() {
this->message = "Error : Key"; }
NotFoundKey(std::string str) {
this->message = "Error : " + str;
}
};
class NotFoundSection : public RwiniException
{
public:
virtual const rwini::RwExceptionType GetExceptionType() const {
return RwExceptionType::NotFoundSection;
}
NotFoundSection() {
this->message = "Error : Section"; }
NotFoundSection(std::string str) {
this->message = "Error : " + str;
}
};
class NullSectionOrKey : public RwiniException
{
public:
virtual const rwini::RwExceptionType GetExceptionType() const {
return RwExceptionType::NullSectionOrKey;
}
NullSectionOrKey(std::string str) {
this->message = "Error : " + str + " "; }
};
class IniFormatError : public RwiniException
{
public:
virtual const rwini::RwExceptionType GetExceptionType() const {
return RwExceptionType::IniFormatError;
}
IniFormatError() {
this->message = "Error : "; }
};
class ReadWriteini {
private:
//
char iniPath[MAX_PATH];
//[section [key,value] ]
std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>* iniContent = new std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>();
//
template <typename Type>
std::string TypeToString(Type str)
noexcept;
public:
// , ini
ReadWriteini(const char* inipath)
noexcept(false);
//
~ReadWriteini();
// [section [key,value] ]
template <typename Type1, typename Type2>
bool FindValue(const Type1& tempsection, const Type2& tempkey, char* value)
noexcept(false);;
template<typename Type1, typename Type2>
std::string FindValue(const Type1& tempsection, const Type2& tempkey)
noexcept(false);
// value
template <typename Type1, typename Type2, typename Type3>
bool SetValue(const Type1& tempsection, const Type2& tempkey, const Type3& value)
noexcept(false);
// key
template <typename Type1, typename Type2, typename Type3>
bool SetKey(const Type1& tempsection, const Type2& tempoldkey, const Type3& tempnewkey)
noexcept(false);
// section
template <typename Type1>
bool InsertSection(const Type1& tempsection);
// key
template <typename Type1, typename Type2, typename Type3>
bool InsertKey(const Type2& tempsection, const Type1& tempkey, const Type3& tempvalue)
noexcept(false);
template<typename Type1, typename Type2, typename Type3>
bool AutoInsertKey(const Type2& tempsection, const Type1& tempkey, const Type3& tempvalue)
noexcept(false);
// section
template <typename Type1>
bool DeleteSection(const Type1& tempsection)
noexcept(false);
// key
template <typename Type1, typename Type2>
bool DeleteKey(const Type1& tempsection, const Type2& tempkey);
// ini
bool Writeini();
// section key,
std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>::iterator
SeekSection(std::string temp_section)
noexcept(false);
std::unordered_map<std::string, std::vector<std::string>>::iterator
SeekKey(std::string temp_section, std::string temp_key)
noexcept(false);
};
}
#ifndef READWRITEINI_TEMPLATE_
#define READWRITEINI_TEMPLATE_
/*
* @name:TypeToString
* @describe:
* @param typename Type
* @return:string
*/
template<typename Type>
std::string rwini::ReadWriteini::TypeToString(Type str) noexcept
{
std::stringstream tempStrStream;
std::string goalStr;
tempStrStream << str;
goalStr = tempStrStream.str();
return goalStr;
}
/*
* @name:FindValue
* @describe: section key value
* @param const Type1& tempsection, const Type2& tempkey, char* value
* @return:bool
*/
template <typename Type1, typename Type2>
bool rwini::ReadWriteini::FindValue(const Type1& tempsection, const Type2& tempkey, char* value)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
value[0] = '\0';
std::unordered_map<std::string, std::vector<std::string>>::iterator tempiter;
try
{
tempiter = SeekKey(section, key);
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
const char* tempStr = tempiter->second.front().c_str();
memcpy(value, tempStr, sizeof(char) * strlen(tempStr));
value[strlen(tempStr) + 1] = '\0';
return true;
}
///
/// value std::string, section key NotFoundKey NotFoundSection
///
/// section
/// key
/// section
/// key
///
template <typename Type1, typename Type2>
std::string rwini::ReadWriteini::FindValue(const Type1& tempsection, const Type2& tempkey)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
std::unordered_map<std::string, std::vector<std::string>>::iterator tempiter;
try
{
tempiter = SeekKey(section, key);
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
return tempiter->second.front();
}
/*
* @name:SetValue
* @describe: section key value
* @param const Type1& tempsection, const Type2& tempkey, const Type3& tempvalue
* @return:bool
*/
template <typename Type1, typename Type2, typename Type3>
bool rwini::ReadWriteini::SetValue(const Type1& tempsection, const Type2& tempkey, const Type3& tempvalue)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
std::string value = TypeToString(tempvalue);
std::unordered_map<std::string, std::vector<std::string>>::iterator tempiter;
try
{
tempiter = SeekKey(section, key);
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
tempiter->second[0] = value;
return true;
}
/*
* @name:SetKey
* @describe: section key
* @param {const char*, const char*,const char*}
* @return:bool
*/
/*
*2020/6/11 ,
*/
template <typename Type1, typename Type2, typename Type3>
bool rwini::ReadWriteini::SetKey(const Type1& tempsection, const Type2& tempoldkey, const Type3& tempnewkey)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string oldkey = TypeToString(tempoldkey);
std::string newkey = TypeToString(tempnewkey);
if (newkey.empty()) {
throw* (new NullSectionOrKey("new key:" + newkey));
}
try
{
auto tempiter = SeekKey(section, oldkey);
const std::vector<std::string> tempvalue = tempiter->second;
auto iter = SeekSection(section);
iter->second.erase(tempiter);
iter->second.insert(std::make_pair(newkey, tempvalue));
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
return true;
}
/*
* @name:InsertSection
* @describe: section
* @param {const char*}
* @return:bool
*/
template <typename Type1>
bool rwini::ReadWriteini::InsertSection(const Type1& tempsection) noexcept(false)
{
//
std::string section = TypeToString(tempsection);
if (section.empty()) {
throw* (new NullSectionOrKey("section"));
}
iniContent->insert(std::make_pair(section, std::unordered_map<std::string, std::vector<std::string>>()));
return true;
}
/*
* @name:InsertKey
* @describe: Key
* @param const Type2& tempsection, const Type1& tempkey, const Type3& tempvalue
* @return:bool
*/
template <typename Type1, typename Type2, typename Type3>
bool rwini::ReadWriteini::InsertKey(const Type2& tempsection, const Type1& tempkey, const Type3& tempvalue)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
std::string value = TypeToString(tempvalue);
if (section.empty()) {
throw* (new NullSectionOrKey("section"));
}
if (key.empty()) {
throw* (new NullSectionOrKey("key"));
}
auto iter = iniContent->find(section);
if (iter == iniContent->end()) {
throw* (new NotFoundSection(" section:" + section));
}
std::shared_ptr<std::vector<std::string>> temp_value = std::make_shared< std::vector<std::string>>();
temp_value->push_back(value);
iter->second.insert(std::make_pair(key, *temp_value));
return true;
}
///
/// ,
///
/// section
/// key
/// value
/// section
/// key
/// value
///
template <typename Type1, typename Type2, typename Type3>
bool rwini::ReadWriteini::AutoInsertKey(const Type2& tempsection, const Type1& tempkey, const Type3& tempvalue)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
std::string value = TypeToString(tempvalue);
if (section.empty()) {
throw* (new NullSectionOrKey("section"));
}
if (key.empty()) {
throw* (new NullSectionOrKey("key"));
}
auto iter = iniContent->find(section);
if (iter == iniContent->end()) {
this->InsertSection(section);
}
iter = iniContent->find(section);
std::shared_ptr<std::vector<std::string>> temp_value = std::make_shared< std::vector<std::string>>();
temp_value->push_back(value);
iter->second.insert(std::make_pair(key, *temp_value));
return true;
}
/*
* @name:DeleteSection
* @describe: section
* @param const Type1& tempsection
* @return:bool
*/
/*
*2020/6/11 ,
*/
template <typename Type1>
bool rwini::ReadWriteini::DeleteSection(const Type1& tempsection)
noexcept(false)
{
//
std::string section = TypeToString(tempsection);
try
{
auto iter = SeekSection(section);
iniContent->erase(iter);
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
return true;
}
/*
* @name:DeleteKey
* @describe: Key
* @param {const char*}
* @return:bool
*/
template <typename Type1, typename Type2>
bool rwini::ReadWriteini::DeleteKey(const Type1& tempsection, const Type2& tempkey)
{
//
std::string section = TypeToString(tempsection);
std::string key = TypeToString(tempkey);
try
{
auto iter = SeekSection(section);
auto tempiter = iter->second.find(key);
iter->second.erase(tempiter);
}
catch (const rwini::NullSectionOrKey& e)
{
throw e;
}
catch (const rwini::NotFoundSection& e)
{
throw e;
}
catch (const rwini::NotFoundKey& e)
{
throw e;
}
return true;
}
#endif // !READWRITEINI_TEMPLATE_
#ifndef READWRITEINI_REALIZE_
#define READWRITEINI_REALIZE_
/*
* @name:
* @describe:
* @param {char*}
* @return:
*/
rwini::ReadWriteini::ReadWriteini(const char* inipath) noexcept(false) {
memset(iniPath, '\0', sizeof(char) * MAX_PATH);
memcpy(iniPath, inipath, sizeof(char) * strlen(inipath));
std::ifstream iniFile;
iniFile.open(iniPath, std::ios::in);
std::string tempSection;
std::string tempKey;
std::string tempValue;
std::string tempAnn;
// , +1, -1
int tempSectionBracket = 0;
enum class LineType
{
// section, , ,
section = 1, key = 2, value = 3, ann = 4, refuse = 5
};
std::shared_ptr<LineType> lineType = std::make_shared<LineType>();
*lineType = LineType::refuse;
//
std::string tempData;
std::string temp_end_section;
std::string temp_end_key;
while (getline(iniFile, tempData)) {
if (tempData.length() == 0) {
continue;
}
bool emptystr = true;
for (char tempCheck : tempData) {
if (tempCheck == ' ') {
continue;
}
emptystr = false;
if (tempCheck == '[') {
*lineType = LineType::section;
}
else if (tempCheck == ';') {
*lineType = LineType::ann;
}
else {
*lineType = LineType::key;
}
break;
}
if (emptystr) {
continue;
}
for (char tempCh : tempData) {
if (*lineType != LineType::refuse && tempCh == ' ') {
continue;
}
else if (*lineType == LineType::section && tempCh == '[') {
*lineType = LineType::section;
if (++tempSectionBracket >= 2) {
throw* (new IniFormatError());
}
}
else if (*lineType == LineType::section && tempCh == ']') {
*lineType = LineType::refuse;
if (--tempSectionBracket < 0) {
throw* (new IniFormatError());
}
}
else if (*lineType != LineType::ann && tempCh == ';') {
*lineType = LineType::ann;
}
else if (*lineType != LineType::ann && *lineType != LineType::value && tempCh == '=') {
*lineType = LineType::value;
}
else if (*lineType == LineType::ann) {
tempAnn.append(TypeToString(tempCh));
}
else if (*lineType == LineType::section) {
tempSection.append(TypeToString(tempCh));
}
else if (*lineType == LineType::key) {
tempKey.append(TypeToString(tempCh));
}
else if (*lineType == LineType::value) {
tempValue.append(TypeToString(tempCh));
}
}
if (!tempSection.empty()) {
// section
iniContent->insert(std::make_pair(tempSection, std::unordered_map<std::string, std::vector<std::string>>()));
temp_end_section = tempSection;
temp_end_key.clear();
}
else if (!tempKey.empty()) {
std::vector<std::string> temp_add_ann;
temp_add_ann.push_back(tempValue);
if (!tempAnn.empty()) {
temp_add_ann.push_back(tempAnn);
}
iniContent->find(temp_end_section)->second.insert(std::make_pair(tempKey, temp_add_ann));
temp_end_key = tempKey;
}
else if (!tempAnn.empty()) {
if (!temp_end_key.empty()) {
iniContent->find(temp_end_section)->second.find(temp_end_key)->second.push_back(tempAnn);
}
}
tempSection.clear();
tempKey.clear();
tempValue.clear();
tempAnn.clear();
*lineType = LineType::refuse;
}
//
lineType.~shared_ptr();
//
iniFile.close();
}
rwini::ReadWriteini::~ReadWriteini()
{
delete iniContent;
}
/*
* @name:Writeini
* @describe:
* @param {const char*}
* @return:bool
*/
bool rwini::ReadWriteini::Writeini()
{
std::ofstream iniFile;
iniFile.open(iniPath, std::ios::out | std::ios::trunc);
for (auto&& i : *iniContent) {
iniFile << "[" << i.first << "]" << std::endl;
for (auto&& j : i.second) {
iniFile << j.first << "=" << j.second.front() << std::endl;
for (int k = 1; k < j.second.size(); k++) {
if (j.second[k].front() != ';') {
iniFile << ";";
}
iniFile << j.second[k] << std::endl;
}
}
iniFile << std::endl;
}
iniFile.close();
return true;
}
std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>::iterator
rwini::ReadWriteini::SeekSection(std::string temp_section)
noexcept(false)
{
if (temp_section.empty()) {
throw* (new NullSectionOrKey("section"));
}
auto iter = iniContent->find(temp_section);
if (iter == iniContent->end()) {
throw* (new NotFoundSection(" section:" + temp_section));
}
return iter;
}
std::unordered_map<std::string, std::vector<std::string>>::iterator
rwini::ReadWriteini::SeekKey(std::string temp_section, std::string temp_key)
noexcept(false) {
if (temp_section.empty()) {
throw* (new NullSectionOrKey("section"));
}
if (temp_key.empty()) {
throw* (new NullSectionOrKey("key"));
}
auto iter = iniContent->find(temp_section);
if (iter == iniContent->end()) {
throw* (new NotFoundSection(" section:" + temp_section));
}
auto tempiter = iter->second.find(temp_key);
if (tempiter == iter->second.end()) {
throw* (new NotFoundKey(" section:" + temp_section + " key:" + temp_key));
}
return tempiter;
}
#endif // READWRITEINI_TEMPLATE_
#endif // !READWRITE_H_