فهرست منبع

Optimize codes

Tindy X 2 سال پیش
والد
کامیت
c578ea6318

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 425 - 100
include/quickjspp.hpp


+ 5 - 5
src/generator/config/nodemanip.cpp

@@ -210,20 +210,20 @@ int addNodes(std::string link, std::vector<Proxy> &allNodes, int groupID, parse_
         for(Proxy &x : nodes)
         {
             x.GroupId = groupID;
-            if(custom_group.size())
+            if(!custom_group.empty())
                 x.Group = custom_group;
         }
         copyNodes(nodes, allNodes);
         break;
     default:
         explode(link, node);
-        if(node.Type == -1)
+        if(node.Type == ProxyType::Unknown)
         {
             writeLog(LOG_TYPE_ERROR, "No valid link found.");
             return -1;
         }
         node.GroupId = groupID;
-        if(custom_group.size())
+        if(!custom_group.empty())
             node.Group = custom_group;
         allNodes.emplace_back(std::move(node));
     }
@@ -494,9 +494,9 @@ void preprocessNodes(std::vector<Proxy> &nodes, extra_settings &ext)
                     auto compare = (std::function<int(const Proxy&, const Proxy&)>) ctx.eval("compare");
                     auto comparer = [&](const Proxy &a, const Proxy &b)
                     {
-                        if(a.Type == ProxyType::Unknow)
+                        if(a.Type == ProxyType::Unknown)
                             return 1;
-                        if(b.Type == ProxyType::Unknow)
+                        if(b.Type == ProxyType::Unknown)
                             return 0;
                         return compare(a, b);
                     };

+ 11 - 3
src/generator/config/subexport.cpp

@@ -116,7 +116,15 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy &
     std::string target, ret_real_rule;
     static const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.+?)(?:!!(.*))?$)";
     static const std::string type_regex = R"(^!!(?:TYPE)=(.+?)(?:!!(.*))?$)", port_regex = R"(^!!(?:PORT)=(.+?)(?:!!(.*))?$)", server_regex = R"(^!!(?:SERVER)=(.+?)(?:!!(.*))?$)";
-    static const string_array types = {"", "SS", "SSR", "VMESS", "TROJAN", "SNELL", "HTTP", "HTTPS", "SOCKS5", "WIREGUARD"};
+    static const std::map<ProxyType, const char *> types = {{ProxyType::Shadowsocks,  "SS"},
+                                                            {ProxyType::ShadowsocksR, "SSR"},
+                                                            {ProxyType::VMess,        "VMESS"},
+                                                            {ProxyType::Trojan,       "TROJAN"},
+                                                            {ProxyType::Snell,        "SNELL"},
+                                                            {ProxyType::HTTP,         "HTTP"},
+                                                            {ProxyType::HTTPS,        "HTTPS"},
+                                                            {ProxyType::SOCKS5,       "SOCKS5"},
+                                                            {ProxyType::WireGuard,    "WIREGUARD"}};
     if(startsWith(rule, "!!GROUP="))
     {
         regGetMatch(rule, group_regex, 3, 0, &target, &ret_real_rule);
@@ -134,9 +142,9 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy &
     {
         regGetMatch(rule, type_regex, 3, 0, &target, &ret_real_rule);
         real_rule = ret_real_rule;
-        if(node.Type == ProxyType::Unknow)
+        if(node.Type == ProxyType::Unknown)
             return false;
-        return regMatch(types[node.Type], target);
+        return regMatch(types.at(node.Type), target);
     }
     else if(startsWith(rule, "!!PORT="))
     {

+ 7 - 7
src/generator/template/templates.cpp

@@ -96,7 +96,7 @@ int render_template(const std::string &content, const template_args &vars, std::
     for(auto &x : vars.request_params)
     {
         all_args += x.first;
-        if(x.second.size())
+        if(!x.second.empty())
         {
             parse_json_pointer(data["request"], x.first, x.second);
             all_args += "=" + x.second;
@@ -295,19 +295,19 @@ const std::string clash_script_keyword_template = R"(  keywords = [{{ rule.keywo
 std::string findFileName(const std::string &path)
 {
     string_size pos = path.rfind('/');
-    if(pos == path.npos)
+    if(pos == std::string::npos)
     {
         pos = path.rfind('\\');
-        if(pos == path.npos)
+        if(pos == std::string::npos)
             pos = 0;
     }
     string_size pos2 = path.rfind('.');
-    if(pos2 < pos || pos2 == path.npos)
+    if(pos2 < pos || pos2 == std::string::npos)
         pos2 = path.size();
     return path.substr(pos + 1, pos2 - pos - 1);
 }
 
-int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &ruleset_content_array, std::string remote_path_prefix, bool script, bool overwrite_original_rules, bool clash_classical_ruleset)
+int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &ruleset_content_array, const std::string &remote_path_prefix, bool script, bool overwrite_original_rules, bool clash_classical_ruleset)
 {
     nlohmann::json data;
     std::string match_group, geoips, retrieved_rules;
@@ -381,7 +381,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
                 groups.emplace_back(std::move(rule_name));
                 continue;
             }
-            if(remote_path_prefix.size())
+            if(!remote_path_prefix.empty())
             {
                 if(fileExist(rule_path, true) || isLink(rule_path))
                 {
@@ -524,7 +524,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
     }
     if(script)
     {
-        if(geoips.size())
+        if(!geoips.empty())
             parse_json_pointer(data, "geoips", geoips.erase(geoips.size() - 1));
 
         parse_json_pointer(data, "match_group", match_group);

+ 1 - 1
src/generator/template/templates.h

@@ -16,6 +16,6 @@ struct template_args
 };
 
 int render_template(const std::string &content, const template_args &vars, std::string &output, const std::string &include_scope = "templates");
-int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &ruleset_content_array, std::string remote_path_prefix, bool script, bool overwrite_original_rules, bool clash_classic_ruleset);
+int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &ruleset_content_array, const std::string &remote_path_prefix, bool script, bool overwrite_original_rules, bool clash_classic_ruleset);
 
 #endif // TEMPLATES_H_INCLUDED

+ 4 - 4
src/parser/config/proxy.h

@@ -9,9 +9,9 @@
 using String = std::string;
 using StringArray = std::vector<String>;
 
-enum ProxyType
+enum class ProxyType
 {
-    Unknow,
+    Unknown,
     Shadowsocks,
     ShadowsocksR,
     VMess,
@@ -23,7 +23,7 @@ enum ProxyType
     WireGuard
 };
 
-inline String getProxyTypeName(int type)
+inline String getProxyTypeName(ProxyType type)
 {
     switch(type)
     {
@@ -50,7 +50,7 @@ inline String getProxyTypeName(int type)
 
 struct Proxy
 {
-    int Type = ProxyType::Unknow;
+    ProxyType Type = ProxyType::Unknown;
     uint32_t Id = 0;
     uint32_t GroupId = 0;
     String Group;

+ 6 - 6
src/parser/subparser.cpp

@@ -743,15 +743,15 @@ void explodeTrojan(std::string trojan, Proxy &node)
     std::string server, port, psk, addition, group, remark, host, path, network;
     tribool tfo, scv;
     trojan.erase(0, 9);
-    string_size pos = trojan.rfind("#");
+    string_size pos = trojan.rfind('#');
 
-    if(pos != trojan.npos)
+    if(pos != std::string::npos)
     {
         remark = urlDecode(trojan.substr(pos + 1));
         trojan.erase(pos);
     }
-    pos = trojan.find("?");
-    if(pos != trojan.npos)
+    pos = trojan.find('?');
+    if(pos != std::string::npos)
     {
         addition = trojan.substr(pos + 1);
         trojan.erase(pos);
@@ -1242,7 +1242,7 @@ void explodeShadowrocket(std::string rocket, Proxy &node)
     std::string addition;
     rocket = rocket.substr(8);
 
-    string_size pos = rocket.find("?");
+    string_size pos = rocket.find('?');
     addition = rocket.substr(pos + 1);
     rocket.erase(pos);
 
@@ -2274,7 +2274,7 @@ void explodeSub(std::string sub, std::vector<Proxy> &nodes)
             if(strLink.rfind("\r") != strLink.npos)
                 strLink.erase(strLink.size() - 1);
             explode(strLink, node);
-            if(strLink.empty() || node.Type == ProxyType::Unknow)
+            if(strLink.empty() || node.Type == ProxyType::Unknown)
             {
                 continue;
             }

+ 23 - 26
src/script/script_quickjs.cpp

@@ -2,6 +2,7 @@
 #include <map>
 #include <iostream>
 #include <quickjspp.hpp>
+#include <quickjs/quickjs-libc.h>
 
 #ifdef _WIN32
 #include <windows.h>
@@ -291,9 +292,7 @@ namespace qjs
         static qjs_fetch_Headers unwrap(JSContext *ctx, JSValueConst v)
         {
             qjs_fetch_Headers result;
-            auto headers = JS_GetPropertyStr(ctx, v, "headers");
-            result.headers = js_traits<detail::string_icase_map>::unwrap(ctx, headers);
-            JS_FreeValue(ctx, headers);
+            result.headers = unwrap_free<detail::string_icase_map>(ctx, v, "headers");
             return result;
         }
         static JSValue wrap(JSContext *ctx, const qjs_fetch_Headers &h)
@@ -310,14 +309,12 @@ namespace qjs
         static qjs_fetch_Request unwrap(JSContext *ctx, JSValueConst v)
         {
             qjs_fetch_Request request;
-            auto headers = JS_GetPropertyStr(ctx, v, "headers");
-            request.method = JS_GetPropertyToString(ctx, v, "method");
-            request.url = JS_GetPropertyToString(ctx, v, "url");
-            request.postdata = JS_GetPropertyToString(ctx, v, "data");
-            request.proxy = JS_GetPropertyToString(ctx, v, "proxy");
-            request.cookies = JS_GetPropertyToString(ctx, v, "cookies");
-            request.headers = js_traits<qjs_fetch_Headers>::unwrap(ctx, headers);
-            JS_FreeValue(ctx, headers);
+            request.method = unwrap_free<std::string>(ctx, v, "method");
+            request.url = unwrap_free<std::string>(ctx, v, "url");
+            request.postdata = unwrap_free<std::string>(ctx, v, "data");
+            request.proxy = unwrap_free<std::string>(ctx, v, "proxy");
+            request.cookies = unwrap_free<std::string>(ctx, v, "cookies");
+            request.headers = unwrap_free<qjs_fetch_Headers>(ctx, v, "headers");
             return request;
         }
     };
@@ -390,7 +387,6 @@ std::string getGeoIP(const std::string &address, const std::string &proxy)
 void script_runtime_init(qjs::Runtime &runtime)
 {
     js_std_init_handlers(runtime.rt);
-    JS_SetModuleLoaderFunc(runtime.rt, nullptr, js_module_loader, nullptr);
 }
 
 int ShowMsgbox(const std::string &title, std::string content, uint16_t type = 0)
@@ -459,18 +455,6 @@ int script_context_init(qjs::Context &context)
             .fun<&qjs_fetch_Response::content>("data")
             .fun<&qjs_fetch_Response::cookies>("cookies")
             .fun<&qjs_fetch_Response::headers>("headers");
-            /*
-        module.class_<nodeInfo>("NodeInfo")
-            .constructor<>()
-            .fun<&nodeInfo::linkType>("LinkType")
-            .fun<&nodeInfo::id>("ID")
-            .fun<&nodeInfo::groupID>("GroupID")
-            .fun<&nodeInfo::group>("Group")
-            .fun<&nodeInfo::remarks>("Remark")
-            .fun<&nodeInfo::server>("Hostname")
-            .fun<&nodeInfo::port>("Port")
-            .fun<&nodeInfo::proxyStr>("ProxyInfo");
-            */
         module.class_<Proxy>("Proxy")
             .constructor<>()
             .fun<&Proxy::Type>("Type")
@@ -502,7 +486,20 @@ int script_context_init(qjs::Context &context)
             .fun<&Proxy::UDP>("UDP")
             .fun<&Proxy::TCPFastOpen>("TCPFastOpen")
             .fun<&Proxy::AllowInsecure>("AllowInsecure")
-            .fun<&Proxy::TLS13>("TLS13");
+            .fun<&Proxy::TLS13>("TLS13")
+            .fun<&Proxy::SnellVersion>("SnellVersion")
+            .fun<&Proxy::ServerName>("ServerName")
+            .fun<&Proxy::SelfIP>("SelfIP")
+            .fun<&Proxy::SelfIPv6>("SelfIPv6")
+            .fun<&Proxy::PublicKey>("PublicKey")
+            .fun<&Proxy::PrivateKey>("PrivateKey")
+            .fun<&Proxy::PreSharedKey>("PreSharedKey")
+            .fun<&Proxy::DnsServers>("DnsServers")
+            .fun<&Proxy::Mtu>("Mtu")
+            .fun<&Proxy::AllowedIPs>("AllowedIPs")
+            .fun<&Proxy::KeepAlive>("KeepAlive")
+            .fun<&Proxy::TestUrl>("TestUrl")
+            .fun<&Proxy::ClientId>("ClientId");
         context.global().add<&makeDataURI>("makeDataURI")
             .add<&qjs_fetch>("fetch")
             .add<&base64Encode>("atob")
@@ -518,7 +515,7 @@ int script_context_init(qjs::Context &context)
         globalThis.Request = interUtils.Request
         globalThis.Response = interUtils.Response
         globalThis.Headers = interUtils.Headers
-        globalThis.NodeInfo = interUtils.NodeInfo
+        globalThis.Proxy = interUtils.Proxy
         import * as std from 'std'
         import * as os from 'os'
         globalThis.std = std

+ 67 - 104
src/script/script_quickjs.h

@@ -18,18 +18,7 @@ inline JSValue JS_NewString(JSContext *ctx, const std::string& str)
     return JS_NewStringLen(ctx, str.c_str(), str.size());
 }
 
-inline std::string JS_GetPropertyToString(JSContext *ctx, JSValue v, const char* prop)
-{
-    auto val = JS_GetPropertyStr(ctx, v, prop);
-    size_t len;
-    const char *str = JS_ToCStringLen(ctx, &len, val);
-    std::string result(str, len);
-    JS_FreeCString(ctx, str);
-    JS_FreeValue(ctx, val);
-    return result;
-}
-
-inline std::string JS_GetPropertyToString(JSContext *ctx, JSValueConst obj, uint32_t index) {
+inline std::string JS_GetPropertyIndexToString(JSContext *ctx, JSValueConst obj, uint32_t index) {
     JSValue val = JS_GetPropertyUint32(ctx, obj, index);
     size_t len;
     const char *str = JS_ToCStringLen(ctx, &len, val);
@@ -39,38 +28,17 @@ inline std::string JS_GetPropertyToString(JSContext *ctx, JSValueConst obj, uint
     return result;
 }
 
-inline int JS_GetPropertyToInt32(JSContext *ctx, JSValue v, const char* prop, int32_t def_value = 0)
-{
-    int32_t result = def_value;
-    auto val = JS_GetPropertyStr(ctx, v, prop);
-    int32_t ret = JS_ToInt32(ctx, &result, val);
-    JS_FreeValue(ctx, val);
-    if(ret != 0) return def_value;
-    return result;
-}
-
-inline uint32_t JS_GetPropertyToUInt32(JSContext *ctx, JSValue v, const char* prop, uint32_t def_value = 0)
-{
-    uint32_t result = def_value;
-    auto val = JS_GetPropertyStr(ctx, v, prop);
-    int ret = JS_ToUint32(ctx, &result, val);
-    JS_FreeValue(ctx, val);
-    if(ret != 0) return def_value;
-    return result;
-}
-
-inline bool JS_GetPropertyToBool(JSContext *ctx, JSValue v, const char* prop, bool def_value = false)
-{
-    bool result = def_value;
-    auto val = JS_GetPropertyStr(ctx, v, prop);
-    int ret = JS_ToBool(ctx, val);
-    JS_FreeValue(ctx, val);
-    if(ret != 0) return def_value;
-    return result;
-}
-
 namespace qjs
 {
+    template<typename T>
+    static T unwrap_free(JSContext *ctx, JSValue v, const char* key) noexcept
+    {
+        auto obj = JS_GetPropertyStr(ctx, v, key);
+        T t = js_traits<T>::unwrap(ctx, obj);
+        JS_FreeValue(ctx, obj);
+        return t;
+    }
+
     template<>
     struct js_traits<tribool>
     {
@@ -81,33 +49,28 @@ namespace qjs
             JS_SetPropertyStr(ctx, obj, "isDefined", JS_NewBool(ctx, !t.is_undef()));
             return obj;
         }
+
         static tribool unwrap(JSContext *ctx, JSValueConst v)
         {
             tribool t;
-            bool defined = JS_GetPropertyToBool(ctx, v, "isDefined");
+            bool defined = unwrap_free<bool>(ctx, v, "isDefined");
             if(defined)
             {
-                bool value = JS_GetPropertyToBool(ctx, v, "value");
+                bool value = unwrap_free<bool>(ctx, v, "value");
                 t.set(value);
             }
             return t;
         }
-        static tribool JS_GetPropertyToTriBool(JSContext *ctx, JSValue v, const char* prop)
-        {
-            auto obj = JS_GetPropertyStr(ctx, v, prop);
-            auto tb = unwrap(ctx, obj);
-            JS_FreeValue(ctx, obj);
-            return tb;
-        }
     };
 
     template<>
-    struct js_traits<StringArray> {
+    struct js_traits<StringArray>
+    {
         static StringArray unwrap(JSContext *ctx, JSValueConst v) {
             StringArray arr;
-            uint32_t length = JS_GetPropertyToUInt32(ctx, v, "length");
+            uint32_t length = unwrap_free<uint32_t>(ctx, v, "length");
             for (uint32_t i = 0; i < length; i++) {
-                arr.push_back(JS_GetPropertyToString(ctx, v, i));
+                arr.push_back(JS_GetPropertyIndexToString(ctx, v, i));
             }
             return arr;
         }
@@ -131,7 +94,7 @@ namespace qjs
                 return obj;
             }
 
-            JS_DefinePropertyValueStr(ctx, obj, "Type", JS_NewInt32(ctx, n.Type), JS_PROP_C_W_E);
+            JS_DefinePropertyValueStr(ctx, obj, "Type", js_traits<ProxyType>::wrap(ctx, n.Type), JS_PROP_C_W_E);
             JS_DefinePropertyValueStr(ctx, obj, "Id", JS_NewUint32(ctx, n.Id), JS_PROP_C_W_E);
             JS_DefinePropertyValueStr(ctx, obj, "GroupId", JS_NewUint32(ctx, n.GroupId), JS_PROP_C_W_E);
             JS_DefinePropertyValueStr(ctx, obj, "Group", JS_NewString(ctx, n.Group), JS_PROP_C_W_E);
@@ -187,55 +150,55 @@ namespace qjs
         static Proxy unwrap(JSContext *ctx, JSValueConst v)
         {
             Proxy node;
-            node.Type = JS_GetPropertyToInt32(ctx, v, "Type");
-            node.Id = JS_GetPropertyToInt32(ctx, v, "Id");
-            node.GroupId = JS_GetPropertyToInt32(ctx, v, "GroupId");
-            node.Group = JS_GetPropertyToString(ctx, v, "Group");
-            node.Remark = JS_GetPropertyToString(ctx, v, "Remark");
-            node.Hostname = JS_GetPropertyToString(ctx, v, "Server");
-            node.Port = JS_GetPropertyToUInt32(ctx, v, "Port");
-
-            node.Username = JS_GetPropertyToString(ctx, v, "Username");
-            node.Password = JS_GetPropertyToString(ctx, v, "Password");
-            node.EncryptMethod = JS_GetPropertyToString(ctx, v, "EncryptMethod");
-            node.Plugin = JS_GetPropertyToString(ctx, v, "Plugin");
-            node.PluginOption = JS_GetPropertyToString(ctx, v, "PluginOption");
-            node.Protocol = JS_GetPropertyToString(ctx, v, "Protocol");
-            node.ProtocolParam = JS_GetPropertyToString(ctx, v, "ProtocolParam");
-            node.OBFS = JS_GetPropertyToString(ctx, v, "OBFS");
-            node.OBFSParam = JS_GetPropertyToString(ctx, v, "OBFSParam");
-            node.UserId = JS_GetPropertyToString(ctx, v, "UserId");
-            node.AlterId = JS_GetPropertyToUInt32(ctx, v, "AlterId");
-            node.TransferProtocol = JS_GetPropertyToString(ctx, v, "TransferProtocol");
-            node.FakeType = JS_GetPropertyToString(ctx, v, "FakeType");
-            node.TLSSecure = JS_GetPropertyToBool(ctx, v, "TLSSecure");
-
-            node.Host = JS_GetPropertyToString(ctx, v, "Host");
-            node.Path = JS_GetPropertyToString(ctx, v, "Path");
-            node.Edge = JS_GetPropertyToString(ctx, v, "Edge");
-
-            node.QUICSecure = JS_GetPropertyToString(ctx, v, "QUICSecure");
-            node.QUICSecret = JS_GetPropertyToString(ctx, v, "QUICSecret");
-
-            node.UDP = js_traits<tribool>::JS_GetPropertyToTriBool(ctx, v, "UDP");
-            node.TCPFastOpen = js_traits<tribool>::JS_GetPropertyToTriBool(ctx, v, "TCPFastOpen");
-            node.AllowInsecure = js_traits<tribool>::JS_GetPropertyToTriBool(ctx, v, "AllowInsecure");
-            node.TLS13 = js_traits<tribool>::JS_GetPropertyToTriBool(ctx, v, "TLS13");
-
-            node.SnellVersion = JS_GetPropertyToInt32(ctx, v, "SnellVersion");
-            node.ServerName = JS_GetPropertyToString(ctx, v, "ServerName");
-
-            node.SelfIP = JS_GetPropertyToString(ctx, v, "SelfIP");
-            node.SelfIPv6 = JS_GetPropertyToString(ctx, v, "SelfIPv6");
-            node.PublicKey = JS_GetPropertyToString(ctx, v, "PublicKey");
-            node.PrivateKey = JS_GetPropertyToString(ctx, v, "PrivateKey");
-            node.PreSharedKey = JS_GetPropertyToString(ctx, v, "PreSharedKey");
-            node.DnsServers = js_traits<StringArray>::unwrap(ctx, JS_GetPropertyStr(ctx, v, "DnsServers"));
-            node.Mtu = JS_GetPropertyToUInt32(ctx, v, "Mtu");
-            node.AllowedIPs = JS_GetPropertyToString(ctx, v, "AllowedIPs");
-            node.KeepAlive = JS_GetPropertyToUInt32(ctx, v, "KeepAlive");
-            node.TestUrl = JS_GetPropertyToString(ctx, v, "TestUrl");
-            node.ClientId = JS_GetPropertyToString(ctx, v, "ClientId");
+            node.Type = unwrap_free<ProxyType>(ctx, v, "Type");
+            node.Id = unwrap_free<int32_t>(ctx, v, "Id");
+            node.GroupId = unwrap_free<int32_t>(ctx, v, "GroupId");
+            node.Group = unwrap_free<std::string>(ctx, v, "Group");
+            node.Remark = unwrap_free<std::string>(ctx, v, "Remark");
+            node.Hostname = unwrap_free<std::string>(ctx, v, "Server");
+            node.Port = unwrap_free<uint32_t>(ctx, v, "Port");
+
+            node.Username = unwrap_free<std::string>(ctx, v, "Username");
+            node.Password = unwrap_free<std::string>(ctx, v, "Password");
+            node.EncryptMethod = unwrap_free<std::string>(ctx, v, "EncryptMethod");
+            node.Plugin = unwrap_free<std::string>(ctx, v, "Plugin");
+            node.PluginOption = unwrap_free<std::string>(ctx, v, "PluginOption");
+            node.Protocol = unwrap_free<std::string>(ctx, v, "Protocol");
+            node.ProtocolParam = unwrap_free<std::string>(ctx, v, "ProtocolParam");
+            node.OBFS = unwrap_free<std::string>(ctx, v, "OBFS");
+            node.OBFSParam = unwrap_free<std::string>(ctx, v, "OBFSParam");
+            node.UserId = unwrap_free<std::string>(ctx, v, "UserId");
+            node.AlterId = unwrap_free<uint32_t>(ctx, v, "AlterId");
+            node.TransferProtocol = unwrap_free<std::string>(ctx, v, "TransferProtocol");
+            node.FakeType = unwrap_free<std::string>(ctx, v, "FakeType");
+            node.TLSSecure = unwrap_free<bool>(ctx, v, "TLSSecure");
+
+            node.Host = unwrap_free<std::string>(ctx, v, "Host");
+            node.Path = unwrap_free<std::string>(ctx, v, "Path");
+            node.Edge = unwrap_free<std::string>(ctx, v, "Edge");
+
+            node.QUICSecure = unwrap_free<std::string>(ctx, v, "QUICSecure");
+            node.QUICSecret = unwrap_free<std::string>(ctx, v, "QUICSecret");
+
+            node.UDP = unwrap_free<tribool>(ctx, v, "UDP");
+            node.TCPFastOpen = unwrap_free<tribool>(ctx, v, "TCPFastOpen");
+            node.AllowInsecure = unwrap_free<tribool>(ctx, v, "AllowInsecure");
+            node.TLS13 = unwrap_free<tribool>(ctx, v, "TLS13");
+
+            node.SnellVersion = unwrap_free<int32_t>(ctx, v, "SnellVersion");
+            node.ServerName = unwrap_free<std::string>(ctx, v, "ServerName");
+
+            node.SelfIP = unwrap_free<std::string>(ctx, v, "SelfIP");
+            node.SelfIPv6 = unwrap_free<std::string>(ctx, v, "SelfIPv6");
+            node.PublicKey = unwrap_free<std::string>(ctx, v, "PublicKey");
+            node.PrivateKey = unwrap_free<std::string>(ctx, v, "PrivateKey");
+            node.PreSharedKey = unwrap_free<std::string>(ctx, v, "PreSharedKey");
+            node.DnsServers = unwrap_free<StringArray>(ctx, v, "DnsServers");
+            node.Mtu = unwrap_free<uint32_t>(ctx, v, "Mtu");
+            node.AllowedIPs = unwrap_free<std::string>(ctx, v, "AllowedIPs");
+            node.KeepAlive = unwrap_free<uint32_t>(ctx, v, "KeepAlive");
+            node.TestUrl = unwrap_free<std::string>(ctx, v, "TestUrl");
+            node.ClientId = unwrap_free<std::string>(ctx, v, "ClientId");
             
             return node;
         }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است