assyrianic / SM-Ordmap

A Hash Table that preserves insertion order for SourceMod Plugins.
https://forums.alliedmods.net/showthread.php?t=331318
MIT License
6 stars 0 forks source link

Retrieving keys #1

Closed MAGNAT2645 closed 1 year ago

MAGNAT2645 commented 1 year ago

Is there any way to iterate all existing keys in a map? I want to use OrdMap to add string keys and paths as values in order provided by config and i need to get key name while iterating and then compare it with another string.

And offtopic but i got these errors when tried to build the extension on Windows (VS 2017 with Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27050 for x86)

extension.cpp
c:\home\github\sm-ordmap_ext\smordmap\ordmap\carray.h(67): error C2059: syntax error: '.'
c:\home\github\sm-ordmap_ext\smordmap\ordmap\cstr.h(73): error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax
c:\home\github\sm-ordmap_ext\smordmap\ordmap/ordmap.h(324): error C2059: syntax error: '}'
c:\home\github\sm-ordmap_ext\smordmap\ordmap/ordmap.h(324): error C2143: syntax error: missing ';' before '}'

Build failed: ordmap.ext\extension.obj

and if i change these

CARRAY_API struct CArray carray_make_from_array(void *const buf, const size_t cap, const size_t len) {
    return( struct CArray ){ .table = ( uint8_t* )buf, .cap = cap, .len = len };
}

CSTR_API void cstring_clear(struct CStr *const str) {
    if( str->cstr != NULL ) {
        free(str->cstr);
        str->cstr = NULL;
    }
    *str = (struct CStr){0};
}

to

CARRAY_API struct CArray carray_make_from_array(void *const buf, const size_t cap, const size_t len) {
    return CArray { ( uint8_t* )buf, cap, len };
}

CSTR_API void cstring_clear(struct CStr *const str) {
    if( str->cstr != NULL ) {
        free(str->cstr);
        str->cstr = NULL;
    }
    *str = CStr {0};
}

it builds fine.

assyrianic commented 1 year ago

sure but I want to mention that my ConfigMap structure also saves and lets you iterate keys by the order they were from in a cfg file.

MAGNAT2645 commented 1 year ago

I like ConfigMap but i think it has a lot of unnecessary functions (last revision on gist) which can affect performance in callbacks like NormalSHook (even if a little) and i'm not sure if last gist version is stable. Also i'm not a big fan of using StringMapSnapshot to iterate over keys so OrdMap would be useful for me if it allowed to iterate keys.

Right now i'm using a combination of StringMaps and ArrayLists to preserve config order. Looks like this:

"voicechanger"
{
        <StringMap> of model sections

    "models/naithon/gaben/gaben.mdl"
    {
            <StringMap> of sound sections + <ArrayList> to store keys in order.

        "pyro_paincrticialdeath"
        {
                <ArrayList> of sounds (these are used to get random sound from section)
            "downloadable" "aon/models/gaben/paincrticialdeath.mp3"
        }
        "pyro_painsevere"
        {
                <ArrayList> of sounds
            "downloadable" "aon/models/gaben/paincrticialdeath.mp3"
        }
        "pyro_"
        {
                <ArrayList> of sounds
            "downloadable" "aon/models/gaben/speech01.mp3"
            "downloadable" "aon/models/gaben/speech02.mp3"
            "downloadable" "aon/models/gaben/speech03.mp3"
            "downloadable" "aon/models/gaben/speech04.mp3"
            "downloadable" "aon/models/gaben/speech05.mp3"
            "downloadable" "aon/models/gaben/speech06.mp3"
            "downloadable" "aon/models/gaben/speech07.mp3"
            "downloadable" "aon/models/gaben/speech08.mp3"
            "downloadable" "aon/models/gaben/speech09.mp3"
            "downloadable" "aon/models/gaben/speech10.mp3"
            "downloadable" "aon/models/gaben/speech11.mp3"
            "downloadable" "aon/models/gaben/speech12.mp3"
            "downloadable" "aon/models/gaben/speech13.mp3"
            "downloadable" "aon/models/gaben/speech14.mp3"
            "downloadable" "aon/models/gaben/speech15.mp3"
            "downloadable" "aon/models/gaben/speech16.mp3"
            "downloadable" "aon/models/gaben/speech17.mp3"
            "downloadable" "aon/models/gaben/speech18.mp3"
            "downloadable" "aon/models/gaben/speech19.mp3"
        }
    }
}
assyrianic commented 1 year ago

I like ConfigMap but i think it has a lot of unnecessary functions (last revision on gist) which can affect performance in callbacks like NormalSHook (even if a little) and i'm not sure if last gist version is stable. Also i'm not a big fan of using StringMapSnapshot to iterate over keys so OrdMap would be useful for me if it allowed to iterate keys.

Right now i'm using a combination of StringMaps and ArrayLists to preserve config order. Looks like this:

"voicechanger"
{
        <StringMap> of model sections

  "models/naithon/gaben/gaben.mdl"
  {
          <StringMap> of sound sections + <ArrayList> to store keys in order.

      "pyro_paincrticialdeath"
      {
              <ArrayList> of sounds (these are used to get random sound from section)
          "downloadable" "aon/models/gaben/paincrticialdeath.mp3"
      }
      "pyro_painsevere"
      {
              <ArrayList> of sounds
          "downloadable" "aon/models/gaben/paincrticialdeath.mp3"
      }
      "pyro_"
      {
              <ArrayList> of sounds
          "downloadable" "aon/models/gaben/speech01.mp3"
          "downloadable" "aon/models/gaben/speech02.mp3"
          "downloadable" "aon/models/gaben/speech03.mp3"
          "downloadable" "aon/models/gaben/speech04.mp3"
          "downloadable" "aon/models/gaben/speech05.mp3"
          "downloadable" "aon/models/gaben/speech06.mp3"
          "downloadable" "aon/models/gaben/speech07.mp3"
          "downloadable" "aon/models/gaben/speech08.mp3"
          "downloadable" "aon/models/gaben/speech09.mp3"
          "downloadable" "aon/models/gaben/speech10.mp3"
          "downloadable" "aon/models/gaben/speech11.mp3"
          "downloadable" "aon/models/gaben/speech12.mp3"
          "downloadable" "aon/models/gaben/speech13.mp3"
          "downloadable" "aon/models/gaben/speech14.mp3"
          "downloadable" "aon/models/gaben/speech15.mp3"
          "downloadable" "aon/models/gaben/speech16.mp3"
          "downloadable" "aon/models/gaben/speech17.mp3"
          "downloadable" "aon/models/gaben/speech18.mp3"
          "downloadable" "aon/models/gaben/speech19.mp3"
      }
  }
}

Right now i'm using a combination of StringMaps and ArrayLists to preserve config order. Looks like this:

This is no longer necessary, newest gist of ConfigMap lets you iterate keys in the order they were in the config, here's an example code of it:

int size = my_cfg.Size;
for( int i; i < size; i++ ) {
    int key_len = my_cfg.GetKeySize(i);
    char[] key = new char[key_len + 1];
    my_cfg.GetKey(i, key, key_len);
    /// do something with the key.
}

This way of iterating keys does NOT use StringMapSnapshot so it's much less overhead.

MAGNAT2645 commented 1 year ago

So it's still a lot of code and i'm not sure if it will work for my config structure (if i change downloadable to <enum>)

    char szBuffer[PLATFORM_MAX_PATH];
    GetEntPropString( iClient, Prop_Data, "m_ModelName", szPath, sizeof szPath );
    ReplaceString( szBuffer, sizeof szBuffer, ".", "\\." );
    Format( szBuffer, sizeof szBuffer, "voicechanger.%s", szBuffer );

    ConfigMap hModelSect = g_hRootConfig.GetSection( szBuffer );
    if ( !hModelSect )
    {
        return Plugin_Continue;
    }

    bool bChanged = false;
    for ( int i = 0, iSounds = hModelSect.Size; i < iSounds; ++i )
    {
        hModelSect.GetKey( i, szBuffer, sizeof szBuffer );
        if ( StrContains( szSample, szBuffer, false ) == -1 )
        {
            continue;
        }

        ConfigMap hSoundsSect = hModelSect.GetSection( szBuffer );
        hSoundsSect.GetIntKey( GetRandomInt( 0, hSoundsSect.Size - 1 ), szSample, sizeof szSample );
        bChanged = true;
        break;
    }

    if ( hModelSect.GetInt( "pitch", iPitch ) )
    {
        bChanged = true;
    }

    return bChanged ? Plugin_Changed : Plugin_Continue;
assyrianic commented 1 year ago

So it's still a lot of code and i'm not sure if it will work for my config structure (if i change downloadable to <enum>)

    char szBuffer[PLATFORM_MAX_PATH];
    GetEntPropString( iClient, Prop_Data, "m_ModelName", szPath, sizeof szPath );
    ReplaceString( szBuffer, sizeof szBuffer, ".", "\\." );
    Format( szBuffer, sizeof szBuffer, "voicechanger.%s", szBuffer );

    ConfigMap hModelSect = g_hRootConfig.GetSection( szBuffer );
    if ( !hModelSect )
    {
        return Plugin_Continue;
    }

    bool bChanged = false;
    for ( int i = 0, iSounds = hModelSect.Size; i < iSounds; ++i )
    {
        hModelSect.GetKey( i, szBuffer, sizeof szBuffer );
        if ( StrContains( szSample, szBuffer, false ) == -1 )
        {
            continue;
        }

        ConfigMap hSoundsSect = hModelSect.GetSection( szBuffer );
        hSoundsSect.GetIntKey( GetRandomInt( 0, hSoundsSect.Size - 1 ), szSample, sizeof szSample );
        bChanged = true;
        break;
    }

    if ( hModelSect.GetInt( "pitch", iPitch ) )
    {
        bChanged = true;
    }

    return bChanged ? Plugin_Changed : Plugin_Continue;

looks good to me, have you tested it?

MAGNAT2645 commented 1 year ago

No, I will but i really thought OrdMap would be better way to store such structure and use it in things like NormalSHook to change voicelines. And i just don't like doing ReplaceString every time before getting subsections...

assyrianic commented 1 year ago

No, I will but i really thought OrdMap would be better way to store such structure and use it in things like NormalSHook to change voicelines. And i just don't like doing ReplaceString every time before getting subsections...

the newest configmap also has string interpolation if that helps.

MAGNAT2645 commented 1 year ago

I know but that is not useful for me right now. So there's no way to iterate keys in OrdMap?

assyrianic commented 1 year ago

I know but that is not useful for me right now. So there's no way to iterate keys in OrdMap?

currently no. OrdMap design in general is rather obsolete [by my personal standards]

MAGNAT2645 commented 1 year ago

That's sad. Well i hope someday StringMap will keep insertion order. Or SM team might add a new handle type for this.