// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// Copyright (c) 2015 - 2016 Evol developers
#include "common/hercules.h"
#include "common/db.h"
#include "common/memmgr.h"
#include "emap/hashtable.h"
struct htreg_interface htreg_s;
struct htreg_interface *htreg;
int64 htreg_new_hashtable(void)
{
int64 id = htreg->last_id++;
struct DBMap *ht = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,
HT_MAX_KEY_LEN);
i64db_put(htreg->htables, id, ht);
return id;
}
bool htreg_destroy_hashtable(int64 id)
{
struct DBMap *ht = i64db_get(htreg->htables, id);
if (ht)
{
db_destroy(ht);
i64db_remove(htreg->htables, id);
return true;
}
return false;
}
bool htreg_hashtable_exists(int64 id)
{
return i64db_exists(htreg->htables, id);
}
int64 htreg_hashtable_size(int64 id)
{
struct DBMap *ht = i64db_get(htreg->htables, id);
if (ht)
return db_size(ht);
return 0;
}
bool htreg_clear_hashtable(int64 id)
{
struct DBMap *ht = i64db_get(htreg->htables, id);
if (ht)
{
db_clear(ht);
return true;
}
return false;
}
const struct DBData* htreg_hashtable_getvalue(int64 id, const char *key,
const struct DBData *defval)
{
struct DBMap *ht = i64db_get(htreg->htables, id);
if (ht)
{
struct DBData *val = ht->get(ht, DB->str2key(key));
return val ? val : defval;
}
return NULL;
}
bool htreg_hashtable_setvalue(int64 id, const char *key,
struct DBData value)
{
struct DBMap *ht = i64db_get(htreg->htables, id);
if (!ht)
return false;
bool keep = true;
switch(value.type)
{
case DB_DATA_INT:
case DB_DATA_UINT:
keep = value.u.i;
break;
case DB_DATA_PTR:
keep = value.u.ptr && *(char*)value.u.ptr;
break;
}
if (keep)
ht->put(ht, DB->str2key(key), value, NULL);
else
strdb_remove(ht, key);
return true;
}
/**
* Iterators
*/
int64 htreg_create_iterator(int64 htId)
{
struct DBMap *ht = i64db_get(htreg->htables, htId);
if (ht)
{
int64 id = htreg->last_iterator_id++;
struct DBIterator *it = db_iterator(ht);
i64db_put(htreg->iterators, id, it);
return id;
}
return 0;
}
bool htreg_destroy_iterator(int64 id)
{
struct DBIterator *it = i64db_get(htreg->iterators, id);
if (it)
{
dbi_destroy(it);
return true;
}
return false;
}
bool htreg_iterator_check(int64 id)
{
struct DBIterator *it = i64db_get(htreg->iterators, id);
return it ? dbi_exists(it) : false;
}
bool htreg_iterator_exists(int64 id)
{
return i64db_exists(htreg->iterators, id);
}
const char* htreg_iterator_nextkey(int64 id)
{
struct DBIterator *it = i64db_get(htreg->iterators, id);
if (it)
{
union DBKey key;
it->next(it, &key);
if (dbi_exists(it))
return key.str;
}
return NULL;
}
/**
* Initializer.
*/
void htreg_init(void)
{
htreg->htables = i64db_alloc(DB_OPT_BASE);
htreg->iterators = i64db_alloc(DB_OPT_BASE);
}
/**
* Finalizer.
*/
void htreg_final(void)
{
struct DBIterator *iter = db_iterator(htreg->htables);
struct DBMap *ht;
for(ht=dbi_first(iter); dbi_exists(iter); ht=dbi_next(iter))
db_destroy(ht);
dbi_destroy(iter);
db_destroy(htreg->htables);
// NOTE: maybe I should destroy iteratos before hashtables
struct DBIterator *it;
iter = db_iterator(htreg->iterators);
for (it=dbi_first(iter); dbi_exists(iter); it=dbi_next(iter))
dbi_destroy(it);
dbi_destroy(iter);
db_destroy(htreg->iterators);
}
/**
* Interface defaults initializer.
*/
void htreg_defaults(void)
{
htreg = &htreg_s;
htreg->last_id = 1;
htreg->htables = NULL;
htreg->init = htreg_init;
htreg->final = htreg_final;
htreg->new_hashtable = htreg_new_hashtable;
htreg->destroy_hashtable = htreg_destroy_hashtable;
htreg->hashtable_exists = htreg_hashtable_exists;
htreg->hashtable_size = htreg_hashtable_size;
htreg->clear_hashtable = htreg_clear_hashtable;
htreg->hashtable_getvalue = htreg_hashtable_getvalue;
htreg->hashtable_setvalue = htreg_hashtable_setvalue;
htreg->last_iterator_id = 1;
htreg->iterators = NULL;
htreg->create_iterator = htreg_create_iterator;
htreg->destroy_iterator = htreg_destroy_iterator;
htreg->iterator_check = htreg_iterator_check;
htreg->iterator_exists = htreg_iterator_exists;
htreg->iterator_nextkey = htreg_iterator_nextkey;
}