Skip to content

Instantly share code, notes, and snippets.

@opsJson
Created May 28, 2023 03:40
Show Gist options
  • Save opsJson/eae6b73f693ab281e0515bca6606e6ff to your computer and use it in GitHub Desktop.
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)
#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