Last active
July 31, 2023 02:05
-
-
Save assyrianic/e1e2374462a0485a0a0dfbc85de01760 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sourcemod> | |
#pragma semicolon 1 | |
#pragma newdecls required | |
stock int any_hash(any a, int seed=0) { | |
int h = seed; | |
h = ( i & 0xFF) + (h << 6) + (h << 16) - h; | |
h = ((i >>> 8) & 0xFF) + (h << 6) + (h << 16) - h; | |
h = ((i >>> 16) & 0xFF) + (h << 6) + (h << 16) - h; | |
h = ((i >>> 24) & 0xFF) + (h << 6) + (h << 16) - h; | |
return h; | |
} | |
stock int str_hash(const char[] key, int seed=0) { | |
int h = seed; | |
for( int i=0; key[i] != 0; i++ ) { | |
h = key[i] + (h << 6) + (h << 16) - h; | |
} | |
return h; | |
} | |
enum{ MAX_MAP_ARRAY_SIZE = 8 }; | |
enum struct SPMap { | |
any data[MAX_MAP_ARRAY_SIZE]; | |
int hashes[MAX_MAP_ARRAY_SIZE]; | |
int buckets[MAX_MAP_ARRAY_SIZE]; | |
int cap; | |
int len; | |
void Init(int cap=MAX_MAP_ARRAY_SIZE) { | |
this.cap = cap; | |
for( int i; i < this.cap; i++ ) { | |
this.buckets[i] = -1; | |
this.hashes[i] = 0; | |
this.data[i] = 0; | |
} | |
this.len = 0; | |
} | |
void _Insert(int hash, int val_idx) { | |
int mask = this.cap - 1; | |
int bkt_idx = hash & mask; | |
while( this.buckets[bkt_idx] != -1 ) { | |
bkt_idx++; | |
if( bkt_idx >= mask ) { | |
bkt_idx &= mask; | |
} | |
} | |
this.hashes[val_idx] = hash; | |
this.buckets[bkt_idx] = val_idx; | |
this.len++; | |
} | |
bool InsertByStrKey(const char[] key, any data) { | |
if( this.len >= this.cap ) { | |
return false; | |
} | |
int val_idx = this.len; | |
this.data[val_idx] = data; | |
int hash = str_hash(key); | |
this._Insert(hash, val_idx); | |
return true; | |
} | |
bool InsertByAnyKey(any key, any data) { | |
if( this.len >= this.cap ) { | |
return false; | |
} | |
int val_idx = this.len; | |
this.data[val_idx] = data; | |
int hash = any_hash(key); | |
this._Insert(hash, val_idx); | |
return true; | |
} | |
int _Find(int hash, int &bkt_index=0) { | |
int mask = this.cap - 1; | |
int bkt_idx = hash & mask; | |
int val_idx = this.buckets[bkt_idx]; | |
if( val_idx != -1 ) { | |
bkt_index = bkt_idx; | |
return val_idx; | |
} | |
for( int i = bkt_idx+1; i != bkt_idx; (i = (i+1 >= mask)? ((i+1) & mask) : i+1) ) { | |
/// sometimes the `bkt_idx` is at the mask index. Account for that. | |
if( i > mask ) { | |
continue; | |
} | |
int idx = this.buckets[i]; | |
if( idx==-1 ) { | |
continue; | |
} else if( this.hashes[idx]==hash ) { | |
bkt_index = i; | |
return idx; | |
} | |
} | |
return -1; | |
} | |
any _Get(int hash, bool &res) { | |
int val_idx = this._Find(hash, val_idx); | |
res = val_idx != -1; | |
if( res ) { | |
return this.data[val_idx]; | |
} | |
return 0; | |
} | |
any GetByStrKey(const char[] key, bool &res=false) { | |
int hash = str_hash(key); | |
return this._Get(hash, res); | |
} | |
any GetByAnyKey(any key, bool &res=false) { | |
int hash = any_hash(key); | |
return this._Get(hash, res); | |
} | |
bool _Remove(int hash) { | |
int bkt_idx; | |
int val_idx = this._Find(hash, bkt_idx); | |
bool res = val_idx != -1; | |
if( res ) { | |
this.buckets[bkt_idx] = -1; | |
this.data[val_idx] = 0; | |
this.hashes[val_idx] = 0; | |
} | |
return res; | |
} | |
bool RemoveByStrKey(const char[] key) { | |
int hash = str_hash(key); | |
return this._Remove(hash); | |
} | |
bool RemoveByAnyKey(any key) { | |
int hash = any_hash(key); | |
return this._Remove(hash); | |
} | |
} | |
public Plugin myinfo = { | |
name = "", | |
author = "", | |
description = "", | |
version = "0.0.0", | |
url = "" | |
}; | |
public void OnPluginStart() { | |
SPMap map; | |
map.Init(); | |
map.InsertByStrKey("lol1", 100); | |
map.InsertByStrKey("lol2", 200); | |
map.InsertByStrKey("lol3", 300); | |
map.InsertByStrKey("lol4", 400); | |
map.InsertByStrKey("lol5", 500); | |
map.InsertByStrKey("lol6", 600); | |
map.InsertByStrKey("lol7", 700); | |
map.InsertByStrKey("lol8", 800); | |
any t; | |
t = map.GetByStrKey("lol1"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol2"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol3"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol4"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol5"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol6"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol7"); | |
PrintToServer("b4 t :: %i", t); | |
t = map.GetByStrKey("lol8"); | |
PrintToServer("b4 t :: %i", t); | |
map.RemoveByStrKey("lol6"); | |
t = map.GetByStrKey("lol1"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol2"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol3"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol4"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol5"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol6"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol7"); | |
PrintToServer("aft t :: %i", t); | |
t = map.GetByStrKey("lol8"); | |
PrintToServer("aft t :: %i", t); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment