loadConfig: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
No edit summary
m (Text replacement - "seperat" to "separat")
 
(4 intermediate revisions by 2 users not shown)
Line 2: Line 2:


|game1= arma3
|game1= arma3
|branch= dev
|version1= 2.10
|version1= 2.10


|gr1= Config
|gr1= Config


|descr= Loads the given file as a [[Config]], allowing easy processing of the config file contents using commands such as [[configClasses]], [[configProperties]], [[config greater greater name|>>]], etc. It can load .rvmat, .bisurf, .cpp, .bin, .sqm, and description.ext files (both binarized and unbinarized configs are supported).
|descr= Loads the given file as a [[Config]], allowing easy processing of the config file contents using commands such as [[configClasses]], [[configProperties]], [[config greater greater name|>>]], etc. It can load [[Rvmat File Format|.rvmat]], .bisurf, [[CPP File Format|.cpp]], [[BIN File Formats|.bin]], [[Mission.sqm|.sqm]], and [[Description.ext|description.ext]] files (both binarized and unbinarized configs are supported).
{{Feature|important|Loading a config can be very slow. The config should only be loaded once and cached. For example, the result can be stored in a [[HashMap]] of {{hl|File Path → Config}} pairs. (See {{Link|#Example 2}}).}}
{{Feature|important|
* Config loading can be very slow; the config should only be loaded once and cached, e.g in a [[HashMap]] of {{hl|File Path → Config}} pairs (see {{Link|#Example 3}}).
* It is advised to store the generated config in a variable, otherwise it will get destroyed if it is not being referenced directly (see {{Link|#Example 2}}).
}}


|s1= [[loadConfig]] path
|s1= [[loadConfig]] path
Line 22: Line 24:


|x2= <sqf>
|x2= <sqf>
// INCORRECT - the config is destroyed after the first operator >> accesses it
getNumber (loadConfig "mission.sqm" >> "ScenarioData" >> "respawnDelay");
// CORRECT - the config is destroyed only when the variable _cfg is destroyed
_cfg = loadConfig "mission.sqm";
getNumber (_cfg >> "ScenarioData" >> "respawnDelay");
</sqf>
|x3= <sqf>
// using a hashmap to cache loaded configs, since loading configs is very slow and should be done once.
// using a hashmap to cache loaded configs, since loading configs is very slow and should be done once.
private _fnc_loadConfig = {
private _fnc_loadConfig = {
params ["_path"];
params ["_path"];
// initialize cache if not initialized yet
// initialize cache if not initialized yet
if (isNil "TAG_configCache") then {
if (isNil "TAG_configCache") then
{
TAG_configCache = createHashMap;
TAG_configCache = createHashMap;
};
};
private _cfg = TAG_configCache getOrDefault [_path, configNull];
private _cfg = TAG_configCache getOrDefault [_path, configNull];
// if path doesn't exist in the cache or cfg is null, load the config
// if path doesn't exist in the cache or cfg is null, load the config
if (isNull _cfg) then {
if (isNull _cfg) then
{
_cfg = loadConfig _path;
_cfg = loadConfig _path;
TAG_configCache set [_path, _cfg];
TAG_configCache set [_path, _cfg];
Line 41: Line 54:
</sqf>
</sqf>


|x3= <sqf>
|x4= <sqf>
// converting a config into hashmap
// converting a config into hashmap
private _fnc_convertClass = {
private _fnc_convertClass = {
Line 48: Line 61:
private _result = createHashMap;
private _result = createHashMap;
private _props = configProperties [_cfgClass, "true", true];
private _props = configProperties [_cfgClass, "true", true];
// Note: Hashmaps are case-sensitive. So configName cases have to be consistent (e.g. all lowercase)
// note: Hashmaps are case-sensitive so configName cases have to be consistent (e.g. all lowercase)
{
{
if (isNumber _x) then {_result set [toLowerANSI configName _x, getNumber _x]; continue; };
if (isNumber _x) then { _result set [toLowerANSI configName _x, getNumber _x]; continue; };
if (isText _x) then {_result set [toLowerANSI configName _x, getText _x]; continue; };
if (isText _x) then { _result set [toLowerANSI configName _x, getText _x]; continue; };
if (isArray _x) then {_result set [toLowerANSI configName _x, getArray _x]; continue; };
if (isArray _x) then { _result set [toLowerANSI configName _x, getArray _x]; continue; };
} forEach _props;
} forEach _props;


Line 59: Line 72:
_result set [toLowerANSI configName _x, _x call _fnc_convertClass];
_result set [toLowerANSI configName _x, _x call _fnc_convertClass];
} forEach _classes;
} forEach _classes;
_result;
_result;
};
};
private _cfg = loadConfig "mission.sqm";
private _cfg = loadConfig "mission.sqm";
private _cfgMap = _cfg call _fnc_convertClass;
private _cfgMap = _cfg call _fnc_convertClass;


// The following expression is similar to getNumber(_cfg >> "EditorData" >> "moveGridStep")
// the following expression is similar to getNumber(_cfg >> "EditorData" >> "moveGridStep")
// Notice that all strings are lowercase (which is how they were stored in hashmap)
// note that all strings are lowercase (which is how they were stored in hashmap)
_cfgMap get "editordata" get "movegridstep";
_cfgMap get "editordata" get "movegridstep";
</sqf>
</sqf>
Line 77: Line 92:
|text= When trying to load a terrain surface name, like you get from Ammo Eventhandlers when you hit the terrain, you can simply use
|text= When trying to load a terrain surface name, like you get from Ammo Eventhandlers when you hit the terrain, you can simply use
<sqf>private _config = configFile >> "CfgSurfaces" >> _surfaceName;</sqf>
<sqf>private _config = configFile >> "CfgSurfaces" >> _surfaceName;</sqf>
You can recognize surface names by them not having any \ path seperators in them, they usually start with gdt, for example "gdtvrsurface01".
You can recognize surface names by them not having any \ path separators in them, they usually start with gdt, for example "gdtvrsurface01".
}}
}}

Latest revision as of 15:02, 25 May 2023

Hover & click on the images for description

Description

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).
  • 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).
  • 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).
Groups:
Config

Syntax

Syntax:
loadConfig path
Parameters:
path: String - path to the file, which should be in a valid config format.
Return Value:
Config - loaded config. Returns configNull if the file doesn't exist.

Examples

Example 1:
private _cfg = loadConfig "a3\data_f\default_super.rvmat"; // note: very slow! ~0.1200 ms on tested system getText (_cfg >> "Stage2" >> "uvSource");
Example 2:
// INCORRECT - the config is destroyed after the first operator >> accesses it getNumber (loadConfig "mission.sqm" >> "ScenarioData" >> "respawnDelay"); // CORRECT - the config is destroyed only when the variable _cfg is destroyed _cfg = loadConfig "mission.sqm"; getNumber (_cfg >> "ScenarioData" >> "respawnDelay");
Example 3:
// using a hashmap to cache loaded configs, since loading configs is very slow and should be done once. private _fnc_loadConfig = { params ["_path"]; // initialize cache if not initialized yet if (isNil "TAG_configCache") then { TAG_configCache = createHashMap; }; private _cfg = TAG_configCache getOrDefault [_path, configNull]; // if path doesn't exist in the cache or cfg is null, load the config if (isNull _cfg) then { _cfg = loadConfig _path; TAG_configCache set [_path, _cfg]; }; _cfg; }; // the first call will be slow (~0.1200 ms), but subsequent calls are fast (~0.0050 ms) ["a3\data_f\default_super.rvmat"] call _fnc_loadConfig;
Example 4:
// converting a config into hashmap private _fnc_convertClass = { params ["_cfgClass"]; private _result = createHashMap; private _props = configProperties [_cfgClass, "true", true]; // note: Hashmaps are case-sensitive so configName cases have to be consistent (e.g. all lowercase) { if (isNumber _x) then { _result set [toLowerANSI configName _x, getNumber _x]; continue; }; if (isText _x) then { _result set [toLowerANSI configName _x, getText _x]; continue; }; if (isArray _x) then { _result set [toLowerANSI configName _x, getArray _x]; continue; }; } forEach _props; private _classes = "true" configClasses _cfgClass; { _result set [toLowerANSI configName _x, _x call _fnc_convertClass]; } forEach _classes; _result; }; private _cfg = loadConfig "mission.sqm"; private _cfgMap = _cfg call _fnc_convertClass; // the following expression is similar to getNumber(_cfg >> "EditorData" >> "moveGridStep") // note that all strings are lowercase (which is how they were stored in hashmap) _cfgMap get "editordata" get "movegridstep";

Additional Information

See also:
loadFile >> configFile configClasses isText isNumber isArray isClass configName getText getNumber getArray

Notes

Report bugs on the Feedback Tracker and/or discuss them on the Arma Discord or on the Forums.
Only post proven facts here! Add Note
Dedmen - c
Posted on Mar 22, 2022 - 09:14 (UTC)
When trying to load a terrain surface name, like you get from Ammo Eventhandlers when you hit the terrain, you can simply use
private _config = configFile >> "CfgSurfaces" >> _surfaceName;
You can recognize surface names by them not having any \ path separators in them, they usually start with gdt, for example "gdtvrsurface01".