AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Snippets and Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=112)
-   -   [SP] ConfigMap: StringMap & SMCParser (https://forums.alliedmods.net/showthread.php?t=319763)

nergal 11-18-2019 20:47

[SP] ConfigMap: StringMap & SMCParser
 
presenting ConfigMap which is a StringMap Tree very much similar to KeyValues.

Difference is that it only works with strings as values and stringmaps as sections.


API:
Code:

ConfigMap(const char[] filename);

int GetSize(const char[] key_path);

int Get(const char[] key_path, char[] buffer, int buf_size);

ConfigMap GetSection(const char[] key_path);

KeyValType GetKeyValType(const char[] key_path);

int GetInt(const char[] key_path, int& i, int base=10);

int GetFloat(const char[] key_path, float& f);

stock void DeleteCfg(ConfigMap& cfg, bool clear_only=false);

Accessing values and sections is easy:

assume this config:
Code:

"root" {
    "value1"    "howdy"
    "section1" {
        "value1"    "hi"
    }
   
    "section2" {
        "subsection1" {
            "value1"    "bonjour"
        }
    }
}

to access the value "howdy", use the key path string: "root.value1"
to access the value "hi", use the key path string: "root.section1.value1"
to access the value "bonjour", use the key path string: "root.section2.subsection1.value1"

to reduce having to use these key path strings all the time on frequently used subsections, use `GetSection` to save the ConfigMap of a subsection, there is no need to free the instance to the subsection.

Download Link
Tutorial on how to use it.

Features:
Iterating key-values by number.
Retrieving keys in a performant manner.
Partial string interpolation.
Math parsing with custom variables.

MAGNAT2645 11-21-2019 10:13

Re: [SP] ConfigMap: StringMap & SMCParser
 
Is there any way to include ConfigMap to Voice Changer? I just don't want to use KeyValues loop every time NormalSoundHook is called.

nergal 06-29-2020 13:55

Re: [SP] ConfigMap: StringMap & SMCParser
 
Quote:

Originally Posted by MAGNAT2645 (Post 2673871)
Is there any way to include ConfigMap to Voice Changer? I just don't want to use KeyValues loop every time NormalSoundHook is called.

yes! you gotta compile it with Voice Changer. I also want to add that ConfigMap is loop-friendlier than KeyValues since all you need to do get a specific section and iterate that section, here's an example of what I mean from VSH2 which uses ConfigMap:

Code:

        static char download_keys[][] = {
                "downloads.sounds",
                "downloads.models",
                "downloads.materials"
        };
       
        for( int i; i<sizeof(download_keys); i++ ) {
                ConfigMap download_map = g_vsh2.m_hCfg.GetSection(download_keys[i]);
                if( download_map != null ) {
                        for( int n; n<download_map.Size; n++ ) {
                                char index[10];
                                Format(index, sizeof(index), "%i", n);
                                int value_size = download_map.GetSize(index);
                                char[] filepath = new char[value_size];
                                if( download_map.Get(index, filepath, value_size) ) {
                                        switch( i ) {
                                                case 0: PrepareSound(filepath);
                                                case 1: PrepareModel(filepath);
                                                case 2: PrepareMaterial(filepath);
                                        }
                                }
                        }
                }
        }

Have it iterate over an array of keys that map to a section, grab that section, and iterate over it as needed :)

nergal 09-24-2020 14:38

Re: [SP] ConfigMap: StringMap & SMCParser
 
I've updated the OP with the latest code and even converted the library into an include file.
I've also provided a tutorial link on all the capabilities of ConfigMap and how to use it.

MAGNAT2645 09-25-2020 07:59

Re: [SP] ConfigMap: StringMap & SMCParser
 
You can put __nullable__ into methodmap definition like
Code:

methodmap ConfigMap < StringMap __nullable__ {
and then you are able to use
ConfigMap hCfg = new ConfigMap();

EDIT: Nevermind, it seems that Handle-typed methodmaps can use new keyword without __nullable__.
PLS add GetBool method (at least as wrapper around GetInt)

nergal 09-26-2020 18:23

Re: [SP] ConfigMap: StringMap & SMCParser
 
Quote:

Originally Posted by MAGNAT2645 (Post 2718822)
PLS add GetBool method (at least as wrapper around GetInt)

Sounds good, have it work from a number (1 and 0) or the words 'true' and 'false?

MAGNAT2645 09-27-2020 02:34

Re: [SP] ConfigMap: StringMap & SMCParser
 
I have this stock:
Code:

#define _BOOL(%1) view_as< bool >( %1 )

stock bool StringToBool(const char[] str, bool simple=true) {
        if ( simple )
                return _BOOL( StringToInt( str ) );

        if ( strcmp( str, "true", false ) == 0 || strcmp( str, "yes", false ) == 0 || strcmp( str , "on", false ) == 0 || str[0] == '1' )
                return true;

        return false;
}

Sometimes i use words like "true" in my configs, sometimes only "0" and "1". You can use same method if you want.

nergal 09-27-2020 18:21

Re: [SP] ConfigMap: StringMap & SMCParser
 
Quote:

Originally Posted by MAGNAT2645 (Post 2719185)
I have this stock:
Code:

#define _BOOL(%1) view_as< bool >( %1 )

stock bool StringToBool(const char[] str, bool simple=true) {
        if ( simple )
                return _BOOL( StringToInt( str ) );

        if ( strcmp( str, "true", false ) == 0 || strcmp( str, "yes", false ) == 0 || strcmp( str , "on", false ) == 0 || str[0] == '1' )
                return true;

        return false;
}

Sometimes i use words like "true" in my configs, sometimes only "0" and "1". You can use same method if you want.

it's not bad but what would I return if there's a failure? I guess I could have it pass something like a reference to a bool and the method itself returns an int.

Another thing is that your method just checks if the word is "true" or something synonymous and returns false otherwise, which means someone could just put "peanut butter" as a value and trying to make that as a bool would return a value of false lol.

Treating a string value as a bool would require the value of the key to actually represent something that makes sense as a boolean value as opposed to having specific words being able to be treated as a boolean value while everything else is just assumed boolean false.

MAGNAT2645 09-28-2020 07:09

Re: [SP] ConfigMap: StringMap & SMCParser
 
That's just a stock which returns true (only if string treated as true) or false (in any other case), you don't have to use it. It was just an example of simple/advanced conversion.

nergal 09-28-2020 13:09

Re: [SP] ConfigMap: StringMap & SMCParser
 
Quote:

Originally Posted by MAGNAT2645 (Post 2719378)
That's just a stock which returns true (only if string treated as true) or false (in any other case), you don't have to use it. It was just an example of simple/advanced conversion.

alright, put this code in your cfgmap.inc and test out how it goes:

Code:

        public int GetBool(const char[] key_path, bool& b, bool simple=true) {
                if( this==null ) {
                        return 0;
                }
                PackVal val;
                bool result = this.GetVal(key_path, val);
                if( result && val.tag==KeyValType_Value ) {
                        val.data.Reset();
                        char[] strval = new char[val.size];
                        val.data.ReadString(strval, val.size);
                        if( simple ) {
                                b = StringToInt(strval) != 0;
                        } else {
                                if( !strcmp(strval, "true", false) || !strcmp(strval, "1", false) ) {
                                        b = true;
                                } else if( !strcmp(strval, "false", false) || !strcmp(strval, "0", false) ) {
                                        b = false;
                                } else {
                                        return 0;
                                }
                        }
                        return val.size - 1;
                }
                return 0;
        }



All times are GMT -4. The time now is 04:17.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.