#ifndef STR_HT_H
#define STR_HT_H
/* char * -> void * open addressing hashtable */
/* keys and values are strdupped (strcloned) */
#define ht_deleted_key ((char *)1)
#define ht_isused(e) ((e)->key && (e)->key != ht_deleted_key)
#define ht_isempty(e) (((e)->key == NULL) || (e)->key == ht_deleted_key)
#define ht_isdeleted(e) ((e)->key == ht_deleted_key)
typedef struct {
unsigned int hash;
char *key;
void *value;
} ht_entry_t;
typedef struct {
unsigned int mask;
unsigned int fill;
unsigned int used;
int isstr;
ht_entry_t *table;
int refcount;
} ht_t;
ht_t *ht_alloc(int isstr);
void ht_free(ht_t *ht);
ht_t *ht_clear(ht_t *ht);
ht_t *ht_resize(ht_t *ht, unsigned int hint);
/* value of ht[key], NULL if key is empty or deleted */
void *ht_get(ht_t *ht, const char *key);
/* ht[key] = value and return NULL or return ht[key] if key is already used */
void *ht_insert(ht_t *ht, const char *key, void *value);
/* ht[key] = value and return a pointer to the strdupped key */
const char *ht_set(ht_t *ht, const char *key, void *value);
/* delete key and return ht_deleted_key or NULL if key was not used */
const char *ht_del(ht_t *ht, const char *key);
/* iteration */
#define foreach(ht, e) \
for (e = (ht)->table; e != (ht)->table + (ht)->mask + 1; e++) \
if (ht_isused(e))
/* first used (useful for iteration) NULL if empty */
ht_entry_t *ht_first(const ht_t *ht);
/* next used (useful for iteration) NULL if there is no more used */
ht_entry_t *ht_next(const ht_t *ht, ht_entry_t *entry);
#endif