56 lines
1.6 KiB
C
56 lines
1.6 KiB
C
#ifndef INCLUDED_HASHTABLE_H
|
|
#define INCLUDED_HASHTABLE_H
|
|
|
|
#include "base.h"
|
|
|
|
struct HashTableBucket {
|
|
uintptr_t hash;
|
|
LispVal *key;
|
|
LispVal *value;
|
|
};
|
|
|
|
DEFOBJTYPE(HashTable, HASH_TABLE, HASH_TABLE_P, {
|
|
LispVal *hash_fn;
|
|
LispVal *eq_fn;
|
|
struct HashTableBucket *data;
|
|
size_t size;
|
|
size_t count;
|
|
|
|
struct HashTableBucket *cache_bucket;
|
|
});
|
|
|
|
// makes no effort to ensure its values are not GCed!!!
|
|
LispVal *make_hash_table_no_gc(LispVal *hash_fn, LispVal *eq_fn);
|
|
void release_hash_table_no_gc(LispVal *val);
|
|
|
|
DECLARE_FUNCTION(make_hash_table, (LispVal * hash_fn, LispVal *eq_fn));
|
|
DECLARE_FUNCTION(gethash, (LispVal * ht, LispVal *key, LispVal *def));
|
|
DECLARE_FUNCTION(puthash, (LispVal * ht, LispVal *key, LispVal *val));
|
|
DECLARE_FUNCTION(remhash, (LispVal * ht, LispVal *key));
|
|
DECLARE_FUNCTION(hash_table_count, (LispVal * ht));
|
|
|
|
static ALWAYS_INLINE size_t HASH_TABLE_COUNT(LispVal *ht) {
|
|
assert(HASH_TABLE_P(ht));
|
|
return ((LispHashTable *) ht)->count;
|
|
}
|
|
|
|
static ALWAYS_INLINE bool HT_BUCKET_EMPTY_P(struct HashTableBucket *b) {
|
|
return !b->key;
|
|
}
|
|
|
|
static ALWAYS_INLINE LispVal *HASH_KEY(LispVal *ht, size_t i) {
|
|
assert(HASH_TABLE_P(ht));
|
|
return ((LispHashTable *) ht)->data[i].key;
|
|
}
|
|
|
|
static ALWAYS_INLINE LispVal *HASH_VALUE(LispVal *ht, size_t i) {
|
|
assert(HASH_TABLE_P(ht));
|
|
return ((LispHashTable *) ht)->data[i].value;
|
|
}
|
|
|
|
#define HT_FOREACH_INDEX(ht, i) \
|
|
for (size_t i = 0; i < ((LispHashTable *) ht)->size; ++i) \
|
|
if (!HT_BUCKET_EMPTY_P(&((LispHashTable *) ht)->data[i]))
|
|
|
|
#endif
|