add hashmap
This commit is contained in:
parent
986006449d
commit
112d98edcd
1 changed files with 244 additions and 146 deletions
390
slibs.h
390
slibs.h
|
@ -11,94 +11,94 @@
|
||||||
|
|
||||||
#define sl_auto(name, x) typeof(x) name = x
|
#define sl_auto(name, x) typeof(x) name = x
|
||||||
|
|
||||||
#define sl_new(type, ...) \
|
#define sl_new(type, ...) \
|
||||||
({ \
|
({ \
|
||||||
type *ptr = malloc(sizeof(type)); \
|
type *ptr = malloc(sizeof(type)); \
|
||||||
*ptr = (type){__VA_ARGS__}; \
|
*ptr = (type){__VA_ARGS__}; \
|
||||||
ptr; \
|
ptr; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define sl_init(type, ...) \
|
#define sl_init(type, ...) \
|
||||||
(type) { __VA_ARGS__ }
|
(type) { __VA_ARGS__ }
|
||||||
|
|
||||||
#define sl_array_len(arr) sizeof(arr) / sizeof(arr[0])
|
#define sl_array_len(arr) sizeof(arr) / sizeof(arr[0])
|
||||||
|
|
||||||
#define sl_fmt_spec(arg) \
|
#define sl_fmt_spec(arg) \
|
||||||
_Generic((arg), \
|
_Generic((arg), \
|
||||||
int8_t: "%d", \
|
int8_t: "%d", \
|
||||||
int16_t: "%d", \
|
int16_t: "%d", \
|
||||||
int32_t: "%d", \
|
int32_t: "%d", \
|
||||||
int64_t: "%lld", \
|
int64_t: "%lld", \
|
||||||
uint8_t: "%u", \
|
uint8_t: "%u", \
|
||||||
uint16_t: "%u", \
|
uint16_t: "%u", \
|
||||||
uint32_t: "%lu", \
|
uint32_t: "%lu", \
|
||||||
uint64_t: "%llu", \
|
uint64_t: "%llu", \
|
||||||
double: "%lf", \
|
double: "%lf", \
|
||||||
float: "%f", \
|
float: "%f", \
|
||||||
char: "%c", \
|
char: "%c", \
|
||||||
char *: "%s", \
|
char *: "%s", \
|
||||||
void *: "%p", \
|
void *: "%p", \
|
||||||
default: "Unknown")
|
default: "Unknown")
|
||||||
|
|
||||||
#define sl_stringify(x) #x
|
#define sl_stringify(x) #x
|
||||||
|
|
||||||
// Vector
|
// Vector
|
||||||
|
|
||||||
#define sl_vec(type) \
|
#define sl_vec(type) \
|
||||||
struct \
|
struct \
|
||||||
{ \
|
{ \
|
||||||
type *data; \
|
type *data; \
|
||||||
size_t size; \
|
size_t size; \
|
||||||
size_t capacity; \
|
size_t capacity; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_grow(vec) \
|
#define sl_vec_grow(vec) \
|
||||||
{ \
|
{ \
|
||||||
(vec).capacity = (vec).capacity * 2 + 1; \
|
(vec).capacity = (vec).capacity * 2 + 1; \
|
||||||
void *ptr = realloc((vec).data, (vec).capacity * sizeof(*(vec).data)); \
|
void *ptr = realloc((vec).data, (vec).capacity * sizeof(*(vec).data)); \
|
||||||
if (ptr) \
|
if (ptr) \
|
||||||
(vec).data = ptr; \
|
(vec).data = ptr; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_push(vec, element) \
|
#define sl_vec_push(vec, element) \
|
||||||
{ \
|
{ \
|
||||||
if ((vec).size >= (vec).capacity) \
|
if ((vec).size >= (vec).capacity) \
|
||||||
sl_vec_grow(vec); \
|
sl_vec_grow(vec); \
|
||||||
(vec).data[(vec).size++] = (element); \
|
(vec).data[(vec).size++] = (element); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_unshift(vec, element) \
|
#define sl_vec_unshift(vec, element) \
|
||||||
{ \
|
{ \
|
||||||
if ((vec).size >= (vec).capacity) \
|
if ((vec).size >= (vec).capacity) \
|
||||||
sl_vec_grow(vec); \
|
sl_vec_grow(vec); \
|
||||||
memmove((vec).data + 1, (vec).data, (vec).size * sizeof(*(vec).data)); \
|
memmove((vec).data + 1, (vec).data, (vec).size * sizeof(*(vec).data)); \
|
||||||
(vec).data[0] = (element); \
|
(vec).data[0] = (element); \
|
||||||
(vec).size++; \
|
(vec).size++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_shift(vec) \
|
#define sl_vec_shift(vec) \
|
||||||
{ \
|
{ \
|
||||||
memmove((vec).data, (vec).data + 1, (vec).size * sizeof(*(vec).data)); \
|
memmove((vec).data, (vec).data + 1, (vec).size * sizeof(*(vec).data)); \
|
||||||
(vec).size--; \
|
(vec).size--; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_forward(vec) \
|
#define sl_vec_forward(vec) \
|
||||||
{ \
|
{ \
|
||||||
(vec).data++; \
|
(vec).data++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_backward(vec) \
|
#define sl_vec_backward(vec) \
|
||||||
{ \
|
{ \
|
||||||
(vec).data--; \
|
(vec).data--; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_pop(vec) \
|
#define sl_vec_pop(vec) \
|
||||||
{ \
|
{ \
|
||||||
if ((vec).size > 0) \
|
if ((vec).size > 0) \
|
||||||
{ \
|
{ \
|
||||||
(vec).size--; \
|
(vec).size--; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_vec_at(vec, index) ((vec).data[index])
|
#define sl_vec_at(vec, index) ((vec).data[index])
|
||||||
|
|
||||||
|
@ -112,32 +112,133 @@
|
||||||
|
|
||||||
#define sl_vec_end(vec) ((vec).data + (vec).size)
|
#define sl_vec_end(vec) ((vec).data + (vec).size)
|
||||||
|
|
||||||
#define sl_vec_it(name, vec) \
|
#define sl_vec_it(name, vec) \
|
||||||
sl_auto((name), sl_vec_begin(vec)); \
|
sl_auto((name), sl_vec_begin(vec)); \
|
||||||
(name) != sl_vec_end(vec); \
|
(name) != sl_vec_end(vec); \
|
||||||
++(name)
|
++(name)
|
||||||
|
|
||||||
|
// TODO: Linked List
|
||||||
|
|
||||||
|
// #define sl_list(name, type) \
|
||||||
|
// struct name \
|
||||||
|
// { \
|
||||||
|
// type *data; \
|
||||||
|
// struct name *next; \
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #define sl_list_append(list, value) \
|
||||||
|
// { \
|
||||||
|
// sl_auto(curr, list);\
|
||||||
|
|
||||||
|
// } \
|
||||||
|
|
||||||
|
// Hashmap
|
||||||
|
|
||||||
|
#define SL_MAX_HASH_ENTRIES 512
|
||||||
|
int sl_hash(const char *str);
|
||||||
|
|
||||||
|
#define sl_map(name, valuetype) \
|
||||||
|
typedef valuetype sl_##name##_type; \
|
||||||
|
\
|
||||||
|
typedef struct sl_##name##_entry \
|
||||||
|
{ \
|
||||||
|
const char *key; \
|
||||||
|
sl_##name##_type value; \
|
||||||
|
} sl_##name##_entry; \
|
||||||
|
\
|
||||||
|
typedef sl_vec(sl_##name##_entry) sl_##name##_entry_vec; \
|
||||||
|
\
|
||||||
|
typedef struct sl_##name##_map \
|
||||||
|
{ \
|
||||||
|
sl_##name##_entry_vec *entries[SL_MAX_HASH_ENTRIES]; \
|
||||||
|
} sl_##name##_map; \
|
||||||
|
\
|
||||||
|
sl_##name##_map name = {0};
|
||||||
|
|
||||||
|
#define sl_map_set(map, key_, val) \
|
||||||
|
{ \
|
||||||
|
int hash = sl_hash(key_); \
|
||||||
|
sl_##map##_entry_vec *entry = map.entries[hash]; \
|
||||||
|
if (!entry) \
|
||||||
|
{ \
|
||||||
|
entry = calloc(1, sizeof(sl_##map##_entry_vec)); \
|
||||||
|
map.entries[hash] = entry; \
|
||||||
|
} \
|
||||||
|
int found = 0; \
|
||||||
|
for (sl_vec_it(el, *entry)) \
|
||||||
|
{ \
|
||||||
|
if (strcmp(el->key, key_) == 0) \
|
||||||
|
{ \
|
||||||
|
el->value = val; \
|
||||||
|
found = 1; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (!found) \
|
||||||
|
{ \
|
||||||
|
sl_##map##_entry new_entry = {key_, val}; \
|
||||||
|
sl_vec_push(*entry, new_entry) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define sl_map_get(map, key_) \
|
||||||
|
({ \
|
||||||
|
sl_##map##_entry_vec *entry = map.entries[sl_hash(key_)]; \
|
||||||
|
sl_##map##_type* value = NULL; \
|
||||||
|
\
|
||||||
|
if (entry) \
|
||||||
|
{ \
|
||||||
|
for (sl_vec_it(el, *entry)) \
|
||||||
|
{ \
|
||||||
|
if (strcmp(el->key, key_) == 0) \
|
||||||
|
{ \
|
||||||
|
value = &el->value; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
value; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#ifdef SL_IMPLEMENTATION
|
||||||
|
int sl_hash(const char *str)
|
||||||
|
{
|
||||||
|
uint32_t seed = 0;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len && i < sizeof(uint32_t); i++)
|
||||||
|
{
|
||||||
|
seed <<= 8;
|
||||||
|
seed |= str[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
srand(seed);
|
||||||
|
return rand() % SL_MAX_HASH_ENTRIES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// String
|
// String
|
||||||
|
|
||||||
typedef sl_vec(char) sl_string;
|
typedef sl_vec(char) sl_string;
|
||||||
|
|
||||||
#define sl_string(c_str) \
|
#define sl_string(c_str) \
|
||||||
({ \
|
({ \
|
||||||
sl_string str = {0}; \
|
sl_string str = {0}; \
|
||||||
for (size_t i = 0; i < strlen((c_str)); i++) \
|
for (size_t i = 0; i < strlen((c_str)); i++) \
|
||||||
sl_vec_push(str, (c_str)[i]); \
|
sl_vec_push(str, (c_str)[i]); \
|
||||||
str; \
|
str; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define sl_tostring(val) \
|
#define sl_tostring(val) \
|
||||||
({ \
|
({ \
|
||||||
sl_auto(len, snprintf(NULL, 0, sl_fmt_spec(val), val) + 1); \
|
sl_auto(len, snprintf(NULL, 0, sl_fmt_spec(val), val) + 1); \
|
||||||
sl_auto(buf, (char *)malloc(len)); \
|
sl_auto(buf, (char *)malloc(len)); \
|
||||||
snprintf(buf, len, sl_fmt_spec(val), val); \
|
snprintf(buf, len, sl_fmt_spec(val), val); \
|
||||||
sl_auto(str, sl_string(buf)); \
|
sl_auto(str, sl_string(buf)); \
|
||||||
free(buf); \
|
free(buf); \
|
||||||
str; \
|
str; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define sl_str_free(str) sl_vec_free(str)
|
#define sl_str_free(str) sl_vec_free(str)
|
||||||
|
|
||||||
|
@ -146,8 +247,8 @@ char *sl_c_str(sl_string str);
|
||||||
#ifdef SL_IMPLEMENTATION
|
#ifdef SL_IMPLEMENTATION
|
||||||
char *sl_c_str(sl_string str)
|
char *sl_c_str(sl_string str)
|
||||||
{
|
{
|
||||||
sl_vec_push(str, '\0');
|
sl_vec_push(str, '\0');
|
||||||
return str.data;
|
return str.data;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -156,50 +257,49 @@ void sl_append_c_str(sl_string *sl_str, const char *c_str);
|
||||||
#ifdef SL_IMPLEMENTATION
|
#ifdef SL_IMPLEMENTATION
|
||||||
void sl_append_c_str(sl_string *sl_str, const char *c_str)
|
void sl_append_c_str(sl_string *sl_str, const char *c_str)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < strlen(c_str); i++)
|
for (int i = 0; i < strlen(c_str); i++)
|
||||||
{
|
{
|
||||||
sl_vec_push(*sl_str, c_str[i]);
|
sl_vec_push(*sl_str, c_str[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pointers
|
// Pointers
|
||||||
|
|
||||||
#define sl_ptr(type) \
|
#define sl_ptr(type) \
|
||||||
struct \
|
struct \
|
||||||
{ \
|
{ \
|
||||||
type *ptr; \
|
type *ptr; \
|
||||||
int ref_count; \
|
int ref_count; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sl_ptr_make(raw_ptr) \
|
#define sl_ptr_make(raw_ptr) \
|
||||||
{ \
|
{ \
|
||||||
raw_ptr, 1 \
|
raw_ptr, 1}
|
||||||
}
|
|
||||||
|
|
||||||
#define sl_ptr_release(smart_ptr) \
|
#define sl_ptr_release(smart_ptr) \
|
||||||
({ \
|
({ \
|
||||||
smart_ptr.ref_count--; \
|
smart_ptr.ref_count--; \
|
||||||
if (smart_ptr.ref_count <= 0) \
|
if (smart_ptr.ref_count <= 0) \
|
||||||
{ \
|
{ \
|
||||||
free(smart_ptr.ptr); \
|
free(smart_ptr.ptr); \
|
||||||
} \
|
} \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define sl_ptr_get(smart_ptr, raw_ptr_name, scope) \
|
#define sl_ptr_get(smart_ptr, raw_ptr_name, scope) \
|
||||||
({ \
|
({ \
|
||||||
assert(smart_ptr.ref_count > 0 && "Smart pointer already released!"); \
|
assert(smart_ptr.ref_count > 0 && "Smart pointer already released!"); \
|
||||||
sl_auto(raw_ptr_name, smart_ptr.ptr); \
|
sl_auto(raw_ptr_name, smart_ptr.ptr); \
|
||||||
smart_ptr.ref_count++; \
|
smart_ptr.ref_count++; \
|
||||||
scope; \
|
scope; \
|
||||||
sl_ptr_release(smart_ptr); \
|
sl_ptr_release(smart_ptr); \
|
||||||
});
|
});
|
||||||
|
|
||||||
#define sl_ptr_scope(smart_ptr, scope) \
|
#define sl_ptr_scope(smart_ptr, scope) \
|
||||||
({ \
|
({ \
|
||||||
scope; \
|
scope; \
|
||||||
sl_ptr_release(smart_ptr); \
|
sl_ptr_release(smart_ptr); \
|
||||||
});
|
});
|
||||||
|
|
||||||
FILE *sl_open_file(const char *filename, const char *mode);
|
FILE *sl_open_file(const char *filename, const char *mode);
|
||||||
sl_string *sl_read_file(const char *filename);
|
sl_string *sl_read_file(const char *filename);
|
||||||
|
@ -208,41 +308,39 @@ void sl_write_file(const char *filename, const sl_string buffer);
|
||||||
#ifdef SL_IMPLEMENTATION
|
#ifdef SL_IMPLEMENTATION
|
||||||
FILE *sl_open_file(const char *filename, const char *mode)
|
FILE *sl_open_file(const char *filename, const char *mode)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(filename, mode);
|
FILE *file = fopen(filename, mode);
|
||||||
if (!file)
|
return file;
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: could not open file %s\n", filename);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sl_string *sl_read_file(const char *filename)
|
sl_string *sl_read_file(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *file = sl_open_file(filename, "r");
|
FILE *file = sl_open_file(filename, "r");
|
||||||
if(!file) return NULL;
|
if (!file)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
size_t file_size = ftell(file);
|
size_t file_size = ftell(file);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
sl_string *buffer = sl_new(sl_string, 0);
|
sl_string *buffer = sl_new(sl_string, 0);
|
||||||
|
|
||||||
for (size_t i = 0; i < file_size; i++)
|
for (size_t i = 0; i < file_size; i++)
|
||||||
{
|
{
|
||||||
sl_vec_push(*buffer, fgetc(file));
|
sl_vec_push(*buffer, fgetc(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sl_write_file(const char *filename, sl_string buffer)
|
void sl_write_file(const char *filename, sl_string buffer)
|
||||||
{
|
{
|
||||||
FILE *file = sl_open_file(filename, "w");
|
FILE *file = sl_open_file(filename, "w");
|
||||||
if(!file) return;
|
if (!file)
|
||||||
|
return;
|
||||||
|
|
||||||
fputs(sl_c_str(buffer), file);
|
fputs(sl_c_str(buffer), file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue