{"name":"loadConfig","operator":null,"title":"loadConfig","type":"command","url":"https://community.bistudio.com/wiki/loadConfig","revid":341399,"updated":"2023-05-25T14:02:22Z","groups":["Config"],"status":"ok","replaced_by":[],"games":[{"game":"arma3","name":"Arma 3","version":"2.10"}],"since":{"game":"arma3","name":"Arma 3","version":"2.10"},"arma3_since":"2.10","branch":null,"locality":{"argument":null,"effect":null,"server_exec":false},"exec":null,"description":"Loads the given file as a Config, allowing easy processing of the config file contents using commands such as configClasses, configProperties, >>, etc. It can load .rvmat, .bisurf, .cpp, .bin, .sqm, and description.ext files (both binarized and unbinarized configs are supported).\n\n> [!IMPORTANT]\n> - Config loading can be very slow; the config should only be loaded once and cached, e.g in a HashMap of `File Path → Config` pairs (see #Example 3).\n> - It is advised to store the generated config in a variable, otherwise it will get destroyed if it is not being referenced directly (see #Example 2).","syntaxes":[{"syntax":"loadConfig path","since":null,"effect":null,"exec":null,"params":[{"name":"path","type":"String","optional":false,"default":null,"description":"path to the file, which should be in a valid config format.","types":["String"],"since":null,"text":"path: String - path to the file, which should be in a valid config format."}],"returns":{"type":"Config","types":["Config"],"description":"loaded config. Returns configNull if the file doesn't exist.","text":"Config - loaded config. Returns configNull if the file doesn't exist."},"form":"unary","operator":null,"left":null,"right":{"text":"path","types":["String"]}}],"examples":[{"text":"```sqf\nprivate _cfg = loadConfig \"a3\\data_f\\default_super.rvmat\"; // note: very slow! ~0.1200 ms on tested system\ngetText (_cfg >> \"Stage2\" >> \"uvSource\");\n```","code":["private _cfg = loadConfig \"a3\\data_f\\default_super.rvmat\"; // note: very slow! ~0.1200 ms on tested system\ngetText (_cfg >> \"Stage2\" >> \"uvSource\");"]},{"text":"```sqf\n// INCORRECT - the config is destroyed after the first operator >> accesses it\ngetNumber (loadConfig \"mission.sqm\" >> \"ScenarioData\" >> \"respawnDelay\");\n\n// CORRECT - the config is destroyed only when the variable _cfg is destroyed\n_cfg = loadConfig \"mission.sqm\";\ngetNumber (_cfg >> \"ScenarioData\" >> \"respawnDelay\");\n```","code":["// INCORRECT - the config is destroyed after the first operator >> accesses it\ngetNumber (loadConfig \"mission.sqm\" >> \"ScenarioData\" >> \"respawnDelay\");\n\n// CORRECT - the config is destroyed only when the variable _cfg is destroyed\n_cfg = loadConfig \"mission.sqm\";\ngetNumber (_cfg >> \"ScenarioData\" >> \"respawnDelay\");"]},{"text":"```sqf\n// using a hashmap to cache loaded configs, since loading configs is very slow and should be done once.\nprivate _fnc_loadConfig = {\n    params [\"_path\"];\n    // initialize cache if not initialized yet\n    if (isNil \"TAG_configCache\") then\n    {\n        TAG_configCache = createHashMap;\n    };\n    private _cfg = TAG_configCache getOrDefault [_path, configNull];\n    // if path doesn't exist in the cache or cfg is null, load the config\n    if (isNull _cfg) then\n    {\n        _cfg = loadConfig _path;\n        TAG_configCache set [_path, _cfg];\n    };\n    _cfg;\n};\n// the first call will be slow (~0.1200 ms), but subsequent calls are fast (~0.0050 ms)\n[\"a3\\data_f\\default_super.rvmat\"] call _fnc_loadConfig;\n```","code":["// using a hashmap to cache loaded configs, since loading configs is very slow and should be done once.\nprivate _fnc_loadConfig = {\n\tparams [\"_path\"];\n\t// initialize cache if not initialized yet\n\tif (isNil \"TAG_configCache\") then\n\t{\n\t\tTAG_configCache = createHashMap;\n\t};\n\tprivate _cfg = TAG_configCache getOrDefault [_path, configNull];\n\t// if path doesn't exist in the cache or cfg is null, load the config\n\tif (isNull _cfg) then\n\t{\n\t\t_cfg = loadConfig _path;\n\t\tTAG_configCache set [_path, _cfg];\n\t};\n\t_cfg;\n};\n// the first call will be slow (~0.1200 ms), but subsequent calls are fast (~0.0050 ms)\n[\"a3\\data_f\\default_super.rvmat\"] call _fnc_loadConfig;"]},{"text":"```sqf\n// converting a config into hashmap\nprivate _fnc_convertClass = {\n    params [\"_cfgClass\"];\n\n    private _result = createHashMap;\n    private _props = configProperties [_cfgClass, \"true\", true];\n    // note: Hashmaps are case-sensitive so configName cases have to be consistent (e.g. all lowercase)\n    {\n        if (isNumber _x)    then { _result set [toLowerANSI configName _x, getNumber _x];    continue; };\n        if (isText _x)        then { _result set [toLowerANSI configName _x, getText _x];        continue; };\n        if (isArray _x)        then { _result set [toLowerANSI configName _x, getArray _x];    continue; };\n    } forEach _props;\n\n    private _classes = \"true\" configClasses _cfgClass;\n    {\n        _result set [toLowerANSI configName _x, _x call _fnc_convertClass];\n    } forEach _classes;\n\n    _result;\n};\n\nprivate _cfg = loadConfig \"mission.sqm\";\nprivate _cfgMap = _cfg call _fnc_convertClass;\n\n// the following expression is similar to getNumber(_cfg >> \"EditorData\" >> \"moveGridStep\")\n// note that all strings are lowercase (which is how they were stored in hashmap)\n_cfgMap get \"editordata\" get \"movegridstep\";\n```","code":["// converting a config into hashmap\nprivate _fnc_convertClass = {\n\tparams [\"_cfgClass\"];\n\n\tprivate _result = createHashMap;\n\tprivate _props = configProperties [_cfgClass, \"true\", true];\n\t// note: Hashmaps are case-sensitive so configName cases have to be consistent (e.g. all lowercase)\n\t{\n\t\tif (isNumber _x)\tthen { _result set [toLowerANSI configName _x, getNumber _x];\tcontinue; };\n\t\tif (isText _x)\t\tthen { _result set [toLowerANSI configName _x, getText _x];\t\tcontinue; };\n\t\tif (isArray _x)\t\tthen { _result set [toLowerANSI configName _x, getArray _x];\tcontinue; };\n\t} forEach _props;\n\n\tprivate _classes = \"true\" configClasses _cfgClass;\n\t{\n\t\t_result set [toLowerANSI configName _x, _x call _fnc_convertClass];\n\t} forEach _classes;\n\n\t_result;\n};\n\nprivate _cfg = loadConfig \"mission.sqm\";\nprivate _cfgMap = _cfg call _fnc_convertClass;\n\n// the following expression is similar to getNumber(_cfg >> \"EditorData\" >> \"moveGridStep\")\n// note that all strings are lowercase (which is how they were stored in hashmap)\n_cfgMap get \"editordata\" get \"movegridstep\";"]}],"multiplayer":null,"problems":null,"aliases":[],"see_also":["loadFile","config greater greater name","configFile","configClasses","isText","isNumber","isArray","isClass","configName","getText","getNumber","getArray"],"notes":[{"user":"Dedmen","date":"2022-03-22T09:14:37Z","text":"When trying to load a terrain surface name, like you get from Ammo Eventhandlers when you hit the terrain, you can simply use\n\n```sqf\nprivate _config = configFile >> \"CfgSurfaces\" >> _surfaceName;\n```\n\nYou can recognize surface names by them not having any \\ path separators in them, they usually start with gdt, for example \"gdtvrsurface01\"."}],"categories":["Arma 3: New Scripting Commands","Arma 3: Scripting Commands","Command Group: Config","Introduced with Arma 3 version 2.10","Scripting Commands"]}