Created
May 28, 2023 03:40
-
-
Save opsJson/eae6b73f693ab281e0515bca6606e6ff to your computer and use it in GitHub Desktop.
Hashtable macro in C. TYPE is the variable type, KEY_SIZE is the maximum key string size, TABLE_SIZE is the maximum table size. (must be a prime number)
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
#ifndef HASHTABLE_H_ | |
#define HASHTABLE_H_ | |
#include <string.h> | |
unsigned int djb2(const char *str){ | |
unsigned long hash = 5381; | |
int c; | |
while ((c = *str++)) { | |
hash = ((hash << 5) + hash) + c; | |
} | |
return hash; | |
} | |
#define HASHTABLE(TYPE, KEY_SIZE, TABLE_SIZE) \ | |
typedef struct { \ | |
char key[KEY_SIZE]; \ | |
TYPE value; \ | |
} bucket_t_##TYPE; \ | |
\ | |
bucket_t_##TYPE table_##TYPE[TABLE_SIZE]; \ | |
\ | |
int table_set_##TYPE(const char *key, TYPE value) { \ | |
unsigned int i, index; \ | |
\ | |
if (!key) return 0; \ | |
index = djb2(key) % TABLE_SIZE; \ | |
\ | |
for (i=0; i<TABLE_SIZE; i++) { \ | |
int pos = index + i; \ | |
\ | |
if (pos >= TABLE_SIZE) { \ | |
pos -= TABLE_SIZE; \ | |
} \ | |
\ | |
if (!table_##TYPE[pos].key[0]) { \ | |
strncpy(table_##TYPE[pos].key, key, sizeof(table_##TYPE[pos].key)); \ | |
table_##TYPE[pos].value = value; \ | |
return 1; \ | |
} \ | |
\ | |
if (strcmp(table_##TYPE[pos].key, key) == 0) { \ | |
strncpy(table_##TYPE[pos].key, key, sizeof(table_##TYPE[pos].key)); \ | |
table_##TYPE[pos].value = value; \ | |
return 1; \ | |
} \ | |
} \ | |
\ | |
return 0; \ | |
} \ | |
\ | |
int table_get_##TYPE(const char *key, TYPE *value) { \ | |
unsigned int i, index; \ | |
\ | |
if (!key || !value) return 0; \ | |
index = djb2(key) % TABLE_SIZE; \ | |
\ | |
for (i=0; i<TABLE_SIZE; i++) { \ | |
int pos = index + i; \ | |
\ | |
if (pos >= TABLE_SIZE) { \ | |
pos -= TABLE_SIZE; \ | |
} \ | |
\ | |
if (!table_##TYPE[pos].key[0]) { \ | |
return 0; \ | |
} \ | |
\ | |
if (strcmp(table_##TYPE[pos].key, key) == 0) { \ | |
*value = table_##TYPE[pos].value; \ | |
return 1; \ | |
} \ | |
} \ | |
\ | |
return 0; \ | |
} \ | |
#endif | |
/*/////////////////////////////////// | |
Testing: | |
///////////////////////////////////*/ | |
HASHTABLE(int, 32, 211) | |
typedef char *string; | |
HASHTABLE(string, 32, 211) | |
struct Example { | |
int a; | |
float b; | |
}; | |
typedef struct Example Example; | |
HASHTABLE(Example, 16, 211) | |
#include <stdio.h> | |
int main() { | |
int a, b, c; | |
string str1, str2, str3; | |
Example x, y, w, z; | |
x.a = 123; | |
x.b = 0.123; | |
y.a = 69; | |
y.b = 6.9; | |
table_set_int("1", 1); | |
table_set_int("2", 2); | |
table_set_int("3", 3); | |
table_set_string("foo", "bar"); | |
table_set_string("one", "two"); | |
table_set_string("->", "<-"); | |
table_set_Example("myStruct", x); | |
table_set_Example("myStruct2", y); | |
table_get_int("1", &a); | |
table_get_int("2", &b); | |
table_get_int("3", &c); | |
table_get_string("foo", &str1); | |
table_get_string("one", &str2); | |
table_get_string("->", &str3); | |
table_get_Example("myStruct", &w); | |
table_get_Example("myStruct", &z); | |
printf("%i\n", a); | |
printf("%i\n", b); | |
printf("%i\n", c); | |
printf("%s\n", str1); | |
printf("%s\n", str2); | |
printf("%s\n", str3); | |
printf("%i %f\n", w.a, w.b); | |
printf("%i %f\n", z.a, z.b); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment