mirror of
https://github.com/MetaCubeX/subconverter.git
synced 2025-11-04 18:19:42 +08:00
Add error handling for loading base configurations and preference settings
This commit is contained in:
parent
b1f373ee58
commit
09c14e0222
@ -9,6 +9,15 @@
|
|||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
#define INIREADER_EXCEPTION_NONE 0
|
||||||
|
#define INIREADER_EXCEPTION_EMPTY -1
|
||||||
|
#define INIREADER_EXCEPTION_DUPLICATE -2
|
||||||
|
#define INIREADER_EXCEPTION_OUTOFBOUND -3
|
||||||
|
#define INIREADER_EXCEPTION_NOTEXIST -4
|
||||||
|
#define INIREADER_EXCEPTION_NOTPARSED -5
|
||||||
|
|
||||||
|
#define __SAVE_ERROR_AND_RETURN(x) {last_error = x; return last_error;}
|
||||||
|
|
||||||
typedef std::map<std::string, std::multimap<std::string, std::string>> ini_data_struct;
|
typedef std::map<std::string, std::multimap<std::string, std::string>> ini_data_struct;
|
||||||
typedef std::multimap<std::string, std::string> string_multimap;
|
typedef std::multimap<std::string, std::string> string_multimap;
|
||||||
typedef std::vector<std::string> string_array;
|
typedef std::vector<std::string> string_array;
|
||||||
@ -34,6 +43,10 @@ private:
|
|||||||
|
|
||||||
std::string isolated_items_section;
|
std::string isolated_items_section;
|
||||||
|
|
||||||
|
//error flags
|
||||||
|
int last_error = INIREADER_EXCEPTION_NONE;
|
||||||
|
unsigned int last_error_index = 0;
|
||||||
|
|
||||||
bool chkIgnore(std::string section)
|
bool chkIgnore(std::string section)
|
||||||
{
|
{
|
||||||
bool excluded = false, included = false;
|
bool excluded = false, included = false;
|
||||||
@ -86,6 +99,33 @@ public:
|
|||||||
|
|
||||||
~INIReader() = default;
|
~INIReader() = default;
|
||||||
|
|
||||||
|
std::string GetErrorString(int error)
|
||||||
|
{
|
||||||
|
switch(error)
|
||||||
|
{
|
||||||
|
case INIREADER_EXCEPTION_EMPTY:
|
||||||
|
return "Empty document";
|
||||||
|
case INIREADER_EXCEPTION_DUPLICATE:
|
||||||
|
return "Duplicate section";
|
||||||
|
case INIREADER_EXCEPTION_NOTEXIST:
|
||||||
|
return "Target does not exist";
|
||||||
|
case INIREADER_EXCEPTION_OUTOFBOUND:
|
||||||
|
return "Item exists outside of any section";
|
||||||
|
case INIREADER_EXCEPTION_NOTPARSED:
|
||||||
|
return "Parse error";
|
||||||
|
default:
|
||||||
|
return "Undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetLastError()
|
||||||
|
{
|
||||||
|
if(parsed)
|
||||||
|
return GetErrorString(last_error);
|
||||||
|
else
|
||||||
|
return "line " + std::__cxx11::to_string(last_error_index) + ": " + GetErrorString(last_error);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Exclude a section with the given name.
|
* @brief Exclude a section with the given name.
|
||||||
*/
|
*/
|
||||||
@ -137,7 +177,7 @@ public:
|
|||||||
int Parse(std::string content) //parse content into mapped data
|
int Parse(std::string content) //parse content into mapped data
|
||||||
{
|
{
|
||||||
if(!content.size()) //empty content
|
if(!content.size()) //empty content
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_EMPTY);
|
||||||
|
|
||||||
//remove UTF-8 BOM
|
//remove UTF-8 BOM
|
||||||
if(content.compare(0, 3, "\xEF\xBB\xBF") == 0)
|
if(content.compare(0, 3, "\xEF\xBB\xBF") == 0)
|
||||||
@ -157,8 +197,10 @@ public:
|
|||||||
if(store_isolated_line)
|
if(store_isolated_line)
|
||||||
curSection = isolated_items_section; //items before any section define will be store in this section
|
curSection = isolated_items_section; //items before any section define will be store in this section
|
||||||
strStrm<<content;
|
strStrm<<content;
|
||||||
|
last_error_index = 0; //reset error index
|
||||||
while(getline(strStrm, strLine, delimiter)) //get one line of content
|
while(getline(strStrm, strLine, delimiter)) //get one line of content
|
||||||
{
|
{
|
||||||
|
last_error_index++;
|
||||||
lineSize = strLine.size();
|
lineSize = strLine.size();
|
||||||
if(!lineSize || strLine[0] == ';' || strLine[0] == '#') //empty lines and comments are ignored
|
if(!lineSize || strLine[0] == ';' || strLine[0] == '#') //empty lines and comments are ignored
|
||||||
continue;
|
continue;
|
||||||
@ -172,7 +214,7 @@ public:
|
|||||||
if(inExcludedSection) //this section is excluded
|
if(inExcludedSection) //this section is excluded
|
||||||
continue;
|
continue;
|
||||||
if(!curSection.size()) //not in any section
|
if(!curSection.size()) //not in any section
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_OUTOFBOUND);
|
||||||
itemName = trim(strLine.substr(0, strLine.find("=")));
|
itemName = trim(strLine.substr(0, strLine.find("=")));
|
||||||
itemVal = trim(strLine.substr(strLine.find("=") + 1));
|
itemVal = trim(strLine.substr(strLine.find("=") + 1));
|
||||||
itemGroup.emplace(itemName, itemVal); //insert to current section
|
itemGroup.emplace(itemName, itemVal); //insert to current section
|
||||||
@ -195,7 +237,7 @@ public:
|
|||||||
ini_content.erase(curSection); //remove the old section
|
ini_content.erase(curSection); //remove the old section
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -1; //not allowed, stop
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
||||||
}
|
}
|
||||||
ini_content.emplace(curSection, itemGroup); //insert previous section to content map
|
ini_content.emplace(curSection, itemGroup); //insert previous section to content map
|
||||||
read_sections.emplace_back(curSection); //add to read sections list
|
read_sections.emplace_back(curSection); //add to read sections list
|
||||||
@ -223,13 +265,13 @@ public:
|
|||||||
ini_content.erase(curSection); //remove the old section
|
ini_content.erase(curSection); //remove the old section
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -1; //not allowed, stop
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
|
||||||
}
|
}
|
||||||
ini_content.emplace(curSection, itemGroup); //insert this section to content map
|
ini_content.emplace(curSection, itemGroup); //insert this section to content map
|
||||||
read_sections.emplace_back(curSection); //add to read sections list
|
read_sections.emplace_back(curSection); //add to read sections list
|
||||||
}
|
}
|
||||||
parsed = true;
|
parsed = true;
|
||||||
return 0; //all done
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE); //all done
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,7 +280,7 @@ public:
|
|||||||
int ParseFile(std::string filePath)
|
int ParseFile(std::string filePath)
|
||||||
{
|
{
|
||||||
if(!fileExist(filePath))
|
if(!fileExist(filePath))
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
return Parse(fileGet(filePath, false));
|
return Parse(fileGet(filePath, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,10 +322,10 @@ public:
|
|||||||
int EnterSection(std::string section)
|
int EnterSection(std::string section)
|
||||||
{
|
{
|
||||||
if(!SectionExist(section))
|
if(!SectionExist(section))
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
current_section = cached_section = section;
|
current_section = cached_section = section;
|
||||||
cached_section_content = ini_content.at(section);
|
cached_section_content = ini_content.at(section);
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -356,7 +398,7 @@ public:
|
|||||||
unsigned int ItemCount(std::string section)
|
unsigned int ItemCount(std::string section)
|
||||||
{
|
{
|
||||||
if(!parsed || !SectionExist(section))
|
if(!parsed || !SectionExist(section))
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTPARSED);
|
||||||
|
|
||||||
return ini_content.at(section).size();
|
return ini_content.at(section).size();
|
||||||
}
|
}
|
||||||
@ -376,7 +418,7 @@ public:
|
|||||||
int GetItems(std::string section, string_multimap &data)
|
int GetItems(std::string section, string_multimap &data)
|
||||||
{
|
{
|
||||||
if(!parsed || !SectionExist(section))
|
if(!parsed || !SectionExist(section))
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
|
|
||||||
if(cached_section != section)
|
if(cached_section != section)
|
||||||
{
|
{
|
||||||
@ -385,7 +427,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = cached_section_content;
|
data = cached_section_content;
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -402,12 +444,12 @@ public:
|
|||||||
int GetAll(std::string section, std::string itemName, string_array &results) //retrieve item(s) with the same itemName prefix
|
int GetAll(std::string section, std::string itemName, string_array &results) //retrieve item(s) with the same itemName prefix
|
||||||
{
|
{
|
||||||
if(!parsed)
|
if(!parsed)
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTPARSED);
|
||||||
|
|
||||||
string_multimap mapTemp;
|
string_multimap mapTemp;
|
||||||
|
|
||||||
if(GetItems(section, mapTemp) != 0)
|
if(GetItems(section, mapTemp) != 0)
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
|
|
||||||
for(auto &x : mapTemp)
|
for(auto &x : mapTemp)
|
||||||
{
|
{
|
||||||
@ -415,7 +457,7 @@ public:
|
|||||||
results.emplace_back(x.second);
|
results.emplace_back(x.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -539,7 +581,7 @@ public:
|
|||||||
int Set(std::string section, std::string itemName, std::string itemVal)
|
int Set(std::string section, std::string itemName, std::string itemVal)
|
||||||
{
|
{
|
||||||
if(!section.size())
|
if(!section.size())
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
|
|
||||||
if(!parsed)
|
if(!parsed)
|
||||||
parsed = true;
|
parsed = true;
|
||||||
@ -556,7 +598,7 @@ public:
|
|||||||
ini_content.insert(std::pair<std::string, std::multimap<std::string, std::string>>(section, mapTemp));
|
ini_content.insert(std::pair<std::string, std::multimap<std::string, std::string>>(section, mapTemp));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -565,7 +607,7 @@ public:
|
|||||||
int Set(std::string itemName, std::string itemVal)
|
int Set(std::string itemName, std::string itemVal)
|
||||||
{
|
{
|
||||||
if(!current_section.size())
|
if(!current_section.size())
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
return Set(current_section, itemName, itemVal);
|
return Set(current_section, itemName, itemVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +682,7 @@ public:
|
|||||||
int RenameSection(std::string oldName, std::string newName)
|
int RenameSection(std::string oldName, std::string newName)
|
||||||
{
|
{
|
||||||
if(!SectionExist(oldName) || SectionExist(newName))
|
if(!SectionExist(oldName) || SectionExist(newName))
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE);
|
||||||
/*
|
/*
|
||||||
auto nodeHandler = ini_content.extract(oldName);
|
auto nodeHandler = ini_content.extract(oldName);
|
||||||
nodeHandler.key() = newName;
|
nodeHandler.key() = newName;
|
||||||
@ -648,7 +690,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
ini_content[newName] = std::move(ini_content[oldName]);
|
ini_content[newName] = std::move(ini_content[oldName]);
|
||||||
ini_content.erase(oldName);
|
ini_content.erase(oldName);
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -658,7 +700,7 @@ public:
|
|||||||
{
|
{
|
||||||
int retVal;
|
int retVal;
|
||||||
if(!SectionExist(section))
|
if(!SectionExist(section))
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
|
|
||||||
retVal = ini_content.at(section).erase(itemName);
|
retVal = ini_content.at(section).erase(itemName);
|
||||||
if(retVal && cached_section == section)
|
if(retVal && cached_section == section)
|
||||||
@ -690,11 +732,11 @@ public:
|
|||||||
{
|
{
|
||||||
cached_section_content = mapTemp;
|
cached_section_content = mapTemp;
|
||||||
}
|
}
|
||||||
return 0;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return -1;
|
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NOTEXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/main.cpp
33
src/main.cpp
@ -134,15 +134,21 @@ void readConf()
|
|||||||
{
|
{
|
||||||
guarded_mutex guard(on_configuring);
|
guarded_mutex guard(on_configuring);
|
||||||
std::cerr<<"Reading preference settings..."<<std::endl;
|
std::cerr<<"Reading preference settings..."<<std::endl;
|
||||||
|
INIReader ini;
|
||||||
|
ini.allow_dup_section_titles = true;
|
||||||
|
//ini.do_utf8_to_gbk = true;
|
||||||
|
int retVal = ini.ParseFile(pref_path);
|
||||||
|
if(retVal != INIREADER_EXCEPTION_NONE)
|
||||||
|
{
|
||||||
|
std::cerr<<"Unable to load preference settings. Reason: "<<ini.GetLastError()<<"\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
eraseElements(def_exclude_remarks);
|
eraseElements(def_exclude_remarks);
|
||||||
eraseElements(def_include_remarks);
|
eraseElements(def_include_remarks);
|
||||||
eraseElements(clash_extra_group);
|
eraseElements(clash_extra_group);
|
||||||
eraseElements(rulesets);
|
eraseElements(rulesets);
|
||||||
string_array emojis_temp, renames_temp;
|
string_array emojis_temp, renames_temp;
|
||||||
INIReader ini;
|
|
||||||
ini.allow_dup_section_titles = true;
|
|
||||||
//ini.do_utf8_to_gbk = true;
|
|
||||||
ini.ParseFile(pref_path);
|
|
||||||
|
|
||||||
ini.EnterSection("common");
|
ini.EnterSection("common");
|
||||||
if(ini.ItemExist("api_mode"))
|
if(ini.ItemExist("api_mode"))
|
||||||
@ -250,20 +256,31 @@ void readConf()
|
|||||||
void generateBase()
|
void generateBase()
|
||||||
{
|
{
|
||||||
std::string base_content;
|
std::string base_content;
|
||||||
|
int retVal = 0;
|
||||||
std::cerr<<"Generating base content for Clash/R...\n";
|
std::cerr<<"Generating base content for Clash/R...\n";
|
||||||
if(fileExist(clash_rule_base))
|
if(fileExist(clash_rule_base))
|
||||||
base_content = fileGet(clash_rule_base, false);
|
base_content = fileGet(clash_rule_base, false);
|
||||||
else
|
else
|
||||||
base_content = webGet(clash_rule_base, getSystemProxy());
|
base_content = webGet(clash_rule_base, getSystemProxy());
|
||||||
clash_base = YAML::Load(base_content);
|
try
|
||||||
rulesetToClash(clash_base, ruleset_content_array);
|
{
|
||||||
|
clash_base = YAML::Load(base_content);
|
||||||
|
rulesetToClash(clash_base, ruleset_content_array);
|
||||||
|
}
|
||||||
|
catch (YAML::Exception &e)
|
||||||
|
{
|
||||||
|
std::cerr<<"Unable to load Clash base content. Reason: "<<e.msg<<"\n";
|
||||||
|
}
|
||||||
std::cerr<<"Generating base content for Mellow...\n";
|
std::cerr<<"Generating base content for Mellow...\n";
|
||||||
if(fileExist(mellow_rule_base))
|
if(fileExist(mellow_rule_base))
|
||||||
base_content = fileGet(mellow_rule_base, false);
|
base_content = fileGet(mellow_rule_base, false);
|
||||||
else
|
else
|
||||||
base_content = webGet(mellow_rule_base, getSystemProxy());
|
base_content = webGet(mellow_rule_base, getSystemProxy());
|
||||||
mellow_base.Parse(base_content);
|
retVal = mellow_base.Parse(base_content);
|
||||||
rulesetToSurge(mellow_base, ruleset_content_array, 2);
|
if(retVal != INIREADER_EXCEPTION_NONE)
|
||||||
|
std::cerr<<"Unable to load Mellow base content. Reason: "<<mellow_base.GetLastError()<<"\n";
|
||||||
|
else
|
||||||
|
rulesetToSurge(mellow_base, ruleset_content_array, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
std::string subconverter(RESPONSE_CALLBACK_ARGS)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user