Skip to content

Instantly share code, notes, and snippets.

@assyrianic
Last active July 31, 2023 02:05
Show Gist options
  • Save assyrianic/e1e2374462a0485a0a0dfbc85de01760 to your computer and use it in GitHub Desktop.
Save assyrianic/e1e2374462a0485a0a0dfbc85de01760 to your computer and use it in GitHub Desktop.
#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