diff --git a/src/ini_reader.h b/src/ini_reader.h index 9e3ce89..703b3b2 100644 --- a/src/ini_reader.h +++ b/src/ini_reader.h @@ -236,10 +236,7 @@ public: last_error_index++; string_size lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if((!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) && !inDirectSaveSection) //empty lines and comments are ignored continue; ProcessEscapeChar(strLine); diff --git a/src/interfaces.cpp b/src/interfaces.cpp index 0ef6a0a..0fae787 100644 --- a/src/interfaces.cpp +++ b/src/interfaces.cpp @@ -118,10 +118,7 @@ std::string convertRuleset(const std::string &content, int type) strLine = trim(strLine); lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if(!strLine.empty() && (strLine[0] != ';' && strLine[0] != '#' && !(lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/'))) { @@ -287,10 +284,7 @@ std::string getRuleset(RESPONSE_CALLBACK_ARGS) lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if(!strLine.empty() && (strLine[0] != ';' && strLine[0] != '#' && !(lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/'))) { @@ -299,7 +293,7 @@ std::string getRuleset(RESPONSE_CALLBACK_ARGS) if(startsWith(strLine, "IP-CIDR6")) strLine.replace(0, 8, "IP6-CIDR"); strLine += "," + group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2 && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") + if(count_least(strLine, ',', 3) && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") strLine = regReplace(strLine, rule_match_regex, "$1$3$2"); else strLine = regReplace(strLine, rule_match_regex, "$1$3"); @@ -361,10 +355,7 @@ int importItems(string_array &target, bool scope_limit = true) { lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine = strLine.substr(0, lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; result.emplace_back(strLine); @@ -411,11 +402,17 @@ void readRegexMatch(YAML::Node node, const std::string &delimiter, string_array void readEmoji(YAML::Node node, string_array &dest, bool scope_limit = true) { YAML::Node object; - std::string url, match, rep, strLine; + std::string script, url, match, rep, strLine; for(unsigned i = 0; i < node.size(); i++) { object = node[i]; + object["script"] >>= script; + if(script.size()) + { + dest.emplace_back("!!script:" + script); + continue; + } object["import"] >>= url; if(url.size()) { @@ -2032,17 +2029,14 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS) while(getline(ss, strLine, delimiter)) { lineSize = strLine.size(); - if(strLine[lineSize - 1] == '\r') //remove line break - { - strLine = strLine.substr(0, lineSize - 1); - lineSize--; - } + if(lineSize && strLine[lineSize - 1] == '\r') //remove line break + strLine.erase(--lineSize); if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; else if(strLine.find("USER-AGENT") == 0 || strLine.find("URL-REGEX") == 0 || strLine.find("PROCESS-NAME") == 0 || strLine.find("AND") == 0 || strLine.find("OR") == 0) //remove unsupported types continue; strLine += strArray[2]; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); rule.push_back(strLine); } @@ -2210,10 +2204,7 @@ std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS) { lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if(!strLine.empty() && regMatch(strLine, pattern)) { diff --git a/src/misc.cpp b/src/misc.cpp index f36644f..fdb8dff 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -1194,8 +1194,10 @@ void ProcessEscapeChar(std::string &str) str.replace(pos, 2, "\t"); break; default: - str.erase(pos, 1); + /// ignore others for backward compatibility + //str.erase(pos, 1); + break; } - pos = str.find('\\', pos); + pos = str.find('\\', pos + 1); } } diff --git a/src/misc.h b/src/misc.h index 396b065..25de92c 100644 --- a/src/misc.h +++ b/src/misc.h @@ -131,9 +131,22 @@ template static inline T to_number(const U &value, T de int to_int(const std::string &str, int def_value = 0); +static inline bool count_least(const std::string &hay, const char needle, size_t cnt) +{ + string_size pos = hay.find(needle); + while(pos != hay.npos) + { + cnt--; + if(!cnt) + return true; + pos = hay.find(needle, pos + 1); + } + return false; +} + static inline char getLineBreak(const std::string &str) { - return count(str.begin(), str.end(), '\n') < 1 ? '\r' : '\n'; + return count_least(str, '\n', 1) ? '\n' : '\r'; } class tribool diff --git a/src/subexport.cpp b/src/subexport.cpp index 2e3b4bd..d014958 100644 --- a/src/subexport.cpp +++ b/src/subexport.cpp @@ -486,13 +486,15 @@ std::string nodeRename(const nodeInfo &node, const string_array &rename_array) string_size pos; std::string match, rep; std::string remark = node.remarks, real_rule; - duk_context *ctx = duktape_init(); + duk_context *ctx = NULL; defer(duk_destroy_heap(ctx);) for(const std::string &x : rename_array) { if(startsWith(x, "!!script:")) { + if(!ctx) + ctx = duktape_init(); std::string script = x.substr(9); if(startsWith(script, "path:")) script = fileGet(script.substr(5), true); @@ -547,13 +549,15 @@ std::string addEmoji(const nodeInfo &node, const string_array &emoji_array) { std::string real_rule; string_size pos; - duk_context *ctx = duktape_init(); + duk_context *ctx = NULL; defer(duk_destroy_heap(ctx);) for(const std::string &x : emoji_array) { if(startsWith(x, "!!script:")) { + if(!ctx) + ctx = duktape_init(); std::string script = x.substr(9); if(startsWith(script, "path:")) script = fileGet(script.substr(5), true); @@ -636,7 +640,7 @@ void rulesetToClash(YAML::Node &base_rule, std::vector &ruleset if(strLine.find("FINAL") == 0) strLine.replace(0, 5, "MATCH"); strLine += "," + rule_group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); allRules.emplace_back(strLine); total_rules++; @@ -660,11 +664,8 @@ void rulesetToClash(YAML::Node &base_rule, std::vector &ruleset lineSize--; } */ - if(lineSize) - { - strLine = trim(trim_of(strLine, '\r')); - lineSize = strLine.size(); - } + if(lineSize && strLine[lineSize - 1] == '\r') //remove line break + strLine.erase(--lineSize); if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; /* @@ -680,7 +681,7 @@ void rulesetToClash(YAML::Node &base_rule, std::vector &ruleset strLine = replace_all_distinct(strLine, ",force-remote-dns", ""); */ strLine += "," + rule_group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); allRules.emplace_back(strLine); //Rules.push_back(strLine); @@ -727,7 +728,7 @@ std::string rulesetToClashStr(YAML::Node &base_rule, std::vector 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); output_content += " - " + strLine + "\n"; total_rules++; @@ -744,17 +745,17 @@ std::string rulesetToClashStr(YAML::Node &base_rule, std::vector max_allowed_rules) break; lineSize = strLine.size(); - if(lineSize) + if(lineSize && strLine[lineSize - 1] == '\r') { - strLine = trim(trim_of(strLine, '\r')); + strLine.erase(lineSize - 1); lineSize = strLine.size(); } if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; - if(!std::any_of(clash_rule_type.begin(), clash_rule_type.end(), [strLine](std::string type){return startsWith(strLine, type);})) + if(std::none_of(clash_rule_type.begin(), clash_rule_type.end(), [strLine](std::string type){return startsWith(strLine, type);})) continue; strLine += "," + rule_group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); output_content += " - " + strLine + "\n"; total_rules++; @@ -816,14 +817,14 @@ void rulesetToSurge(INIReader &base_rule, std::vector &ruleset_ strLine += "," + rule_group; if(surge_ver == -1 || surge_ver == -2) { - if(std::count(strLine.begin(), strLine.end(), ',') > 2 && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") + if(count_least(strLine, ',', 3) && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") strLine = regReplace(strLine, rule_match_regex, "$1$3$2"); else strLine = regReplace(strLine, rule_match_regex, "$1$3"); } else { - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, rule_match_regex, "$1$3$2"); } strLine = replace_all_distinct(strLine, ",,", ","); @@ -912,18 +913,8 @@ void rulesetToSurge(INIReader &base_rule, std::vector &ruleset_ if(max_allowed_rules && total_rules > max_allowed_rules) break; lineSize = strLine.size(); - /* if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } - */ - if(lineSize) - { - strLine = trim(trim_of(strLine, '\r')); - lineSize = strLine.size(); - } + strLine.erase(--lineSize); if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; @@ -960,14 +951,14 @@ void rulesetToSurge(INIReader &base_rule, std::vector &ruleset_ { if(startsWith(strLine, "IP-CIDR6")) strLine.replace(0, 8, "IP6-CIDR"); - if(std::count(strLine.begin(), strLine.end(), ',') > 2 && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") + if(count_least(strLine, ',', 3) && regReplace(strLine, rule_match_regex, "$2") == ",no-resolve") strLine = regReplace(strLine, rule_match_regex, "$1$3$2"); else strLine = regReplace(strLine, rule_match_regex, "$1$3"); } else { - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, rule_match_regex, "$1$3$2"); } allRules.emplace_back(strLine); diff --git a/src/templates.cpp b/src/templates.cpp index 3c4fe33..3d94f1f 100644 --- a/src/templates.cpp +++ b/src/templates.cpp @@ -261,7 +261,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector &rules if(strLine.find("FINAL") == 0) strLine.replace(0, 5, "MATCH"); strLine += "," + rule_group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); rules.emplace_back(strLine); continue; @@ -329,10 +329,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector &rules { lineSize = strLine.size(); if(lineSize && strLine[lineSize - 1] == '\r') //remove line break - { - strLine.erase(lineSize - 1); - lineSize--; - } + strLine.erase(--lineSize); if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored continue; @@ -351,7 +348,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector &rules else { strLine += "," + rule_group; - if(std::count(strLine.begin(), strLine.end(), ',') > 2) + if(count_least(strLine, ',', 3)) strLine = regReplace(strLine, "^(.*?,.*?)(,.*)(,.*)$", "$1$3$2"); rules.emplace_back(strLine); }