#ifndef SWIFT_DATA_HTABLE_H
#define SWIFT_DATA_HTABLE_H

#include <swift/stdlib.h>

#include <swift/data/api.h>
#include <swift/data/array.h>
#include <swift/data/bitset.h>
#include <swift/data/types.h>

typedef struct swift_htable_t swift_htable_t;
typedef struct swift_htable_iter_t swift_htable_iter_t;

struct swift_htable_t {
	swift_bitset_t set;
	unsigned char *data;
	swift_hash_fn_t hash;
	swift_eq_fn_t eq;
	size_t count, size, item_size;
};

struct swift_htable_iter_t {
	swift_htable_t *htable;
	void *data;
	size_t index;
};

#define SWIFT_HTABLE_ITER(...) ((swift_htable_iter_t){__VA_ARGS__})

SWIFT_DATA_API bool swift_init_htable_size(swift_htable_t *htable,
	swift_hash_fn_t hash, swift_eq_fn_t eq, size_t item_size,
	size_t size);
SWIFT_DATA_API bool swift_init_htable(swift_htable_t *htable,
	swift_hash_fn_t hash, swift_eq_fn_t eq, size_t item_size);
SWIFT_DATA_API void swift_term_htable(swift_htable_t *htable);
SWIFT_DATA_API swift_htable_t *swift_new_htable_size(swift_hash_fn_t hash,
	swift_eq_fn_t eq, size_t item_size, size_t size);
SWIFT_DATA_API swift_htable_t *swift_new_htable(swift_hash_fn_t hash,
	swift_eq_fn_t eq, size_t item_size);
SWIFT_DATA_API void swift_del_htable(swift_htable_t *htable);
SWIFT_DATA_API bool swift_htable_resize(swift_htable_t *htable, size_t size);
SWIFT_DATA_API bool swift_htable_expand(swift_htable_t *htable, size_t count);
SWIFT_DATA_API size_t swift_htable_count(swift_htable_t *htable);
SWIFT_DATA_API size_t swift_htable_size(swift_htable_t *htable);

SWIFT_DATA_API size_t swift_htable_next_index(swift_htable_t *htable,
	size_t index);
SWIFT_DATA_API swift_htable_iter_t swift_htable_first(
	swift_htable_t *htable);
SWIFT_DATA_API bool swift_htable_next(swift_htable_iter_t *iter);

SWIFT_DATA_API bool swift_htable_contains(swift_htable_t *htable,
	const void *key);
SWIFT_DATA_API void *swift_htable_get(struct swift_htable_t *htable,
	size_t index);
SWIFT_DATA_API size_t swift_htable_set(struct swift_htable_t *htable,
	size_t index, void *entry);
SWIFT_DATA_API size_t swift_htable_search_index(swift_htable_t *htable,
	const void *key);
SWIFT_DATA_API void *swift_htable_search(swift_htable_t *htable,
	const void *key);
SWIFT_DATA_API size_t swift_htable_insert(swift_htable_t *htable, void *entry);
SWIFT_DATA_API bool swift_htable_remove_index(swift_htable_t *htable,
	size_t index);
SWIFT_DATA_API bool swift_htable_remove(swift_htable_t *htable,
	const void *key);

#endif /* SWIFT_DATA_HTABLE_H */
