#ifndef	ACL_MEMDB_INCLUDE_H
#define	ACL_MEMDB_INCLUDE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "../stdlib/acl_define.h"

typedef struct ACL_MDT_NOD ACL_MDT_NOD;
typedef struct ACL_MDT_RES ACL_MDT_RES;
typedef struct ACL_MDT_REC ACL_MDT_REC;
typedef struct ACL_MDT_REF ACL_MDT_REF;
typedef struct ACL_MDT_IDX ACL_MDT_IDX;
typedef struct ACL_MDT ACL_MDT;
typedef struct ACL_MDB ACL_MDB;

/* ݱؼֶεԼ־λ */
#define ACL_MDT_FLAG_NUL		(0)
#define ACL_MDT_FLAG_UNI		(1 << 0)	/**< ʾΨһ */
#define	ACL_MDT_FLAG_KMR		(1 << 1)	/**< ʾüڴ */
#define ACL_MDT_FLAG_DMR		(1 << 2)	/**< ʾֵڴ */
/**< ظͬʱָ ACL_MDT_FLAG_UNI | ACL_MDT_FLAG_OOV ʱʹֵǾֵ */
#define ACL_MDT_FLAG_OOV		(1 << 3)

#define	ACL_MDT_FLAG_SLICE1		(1 << 10)	/**<  ACL_SLICE_FLAG_GC1 */
#define	ACL_MDT_FLAG_SLICE2		(1 << 11)	/**<  ACL_SLICE_FLAG_GC2 */
#define	ACL_MDT_FLAG_SLICE3		(1 << 12)	/**<  ACL_SLICE_FLAG_GC3 */
#define	ACL_MDT_FLAG_SLICE_RTGC_OFF	(1 << 13)	/**< رڴƬʵʱչ */

/************************************************************************/
/*                          in acl_mdb.c                                */
/************************************************************************/

/**
 * һݿ
 * @param dbname {const char*} ݿ
 * @param dbtype {const char*} ݿ: hash/avl
 * @return {ACL_MDB*} ݿ
 */
ACL_API ACL_MDB *acl_mdb_create(const char *dbname, const char *dbtype);

/**
 * رղͷһڴݿ
 * @param mdb {ACL_MDB*} ݿ
 */
ACL_API void acl_mdb_free(ACL_MDB *mdb);

/**
 * ڸݿϴһݱ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} 
 * @param tbl_flag {unsigned int} Ա־λ
 * @param init_capacity {size_t} ݱÿڲϣĳʼ
 * @param key_labels {const char *[]} ݱֶ
 * @param flags {unsigned int[]}  key_labels ӦԼ־λ
 * @return {ACL_MDT*} ½ݱ
 */
ACL_API ACL_MDT *acl_mdb_tbl_create(ACL_MDB *mdb, const char *tbl_name,
	unsigned int tbl_flag, size_t init_capacity,
	const char *key_labels[], unsigned int flags[]);

/**
 * һµݼ¼
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param data {void*} Ӧ
 * @param dlen {unsigned int} data ݴС
 * @param key_labels {const char *[]} ݱֶ
 * @param keys {const char *[]} ݱֶӦֵ
 * @return {ACL_MDB_NOD*} ӵݱд洢ľ
 */
ACL_API ACL_MDT_NOD *acl_mdb_add(ACL_MDB *mdb, const char *tbl_name,
	void *data, unsigned int dlen,
	const char *key_labels[], const char *keys[]);

/**
 * ̽ݱжӦֵֶǷ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param key_label {const char*} ݱֶ
 * @param key {const char*} ݱֶμֵ
 * @return {int} 0: , != 0: 
 */
ACL_API int acl_mdb_probe(ACL_MDB *mdb, const char *tbl_name,
	const char *key_label, const char *key);

/**
 * ݿвѯĽ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param key_label {const char*} ݱеֶ
 * @param key {const char*} ݱеֵֶ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param limit {int} ѯĽϣ
 * @return {ACL_MDT_RES*} ѯΪѯΪջ
 */
ACL_API ACL_MDT_RES *acl_mdb_find(ACL_MDB *mdb, const char *tbl_name,
	const char *key_label, const char *key, int from, int limit);

/**
 * ݿгĳݱĳΧĽ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param limit {int} ѯĽϣ
 * @return {ACL_MDT_RES*} ѯΪѯΪջ
 */
ACL_API ACL_MDT_RES *acl_mdb_list(ACL_MDB *mdb, const char *tbl_name,
	int from, int limit);

/**
 * ݿɾһݼ¼
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param key_label {const char*} ݱֶ
 * @param key {const char*} ݱֵֶ
 * @param onfree_fn {void (*)(void*, unsigned int)}
  *	ͷûĶʱõͷŻص
 * @return {int} ɾ
 */
ACL_API int acl_mdb_del(ACL_MDB *mdb, const char *tbl_name,
	const char *key_label, const char *key,
	void (*onfree_fn)(void*, unsigned int));

/**
 * ݿĳݱݽ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @param walk_fn صúط0ֵֹͣ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param limit {int} ѯĽϣ
 * @return {int} ݽֵ
 */
ACL_API int acl_mdb_walk(ACL_MDB *mdb, const char *tbl_name,
	int (*walk_fn)(const void*, unsigned int),
	int from, int limit);

/**
 * ݿĳݱԪܸ
 * @param mdb {ACL_MDB*} ݿ
 * @param tbl_name {const char*} ݱ
 * @return {int} >=0
 */
ACL_API int acl_mdb_cnt(ACL_MDB *mdb, const char *tbl_name);

/************************************************************************/
/*                          in acl_mdt.c                                */
/************************************************************************/

/**
 * һݱ
 * @param dbtype {const char *} : hash/avl
 * @param tbl_name {const char*} 
 * @param tbl_flag {unsigned int} Ա־λ
 * @param init_capacity {size_t} ÿڲϣĳʼ
 * @param key_labels {const char *[]} еĸֶ飬NULL
 * @param flags {unsigned int[]}  key_labels ӦԼ־λ
 * @return {ACL_MDT*} ½ݱľ
 */
ACL_API ACL_MDT *acl_mdt_create(const char *dbtype, const char *tbl_name,
	unsigned int tbl_flag, size_t init_capacity,
	const char *key_labels[], unsigned int flags[]);

/**
 * ͷһڴ
 * @param mdt {ACL_MDT*} ڴݱ
 */
ACL_API void acl_mdt_free(ACL_MDT *mdt);

/**
 * ݱһµݼ¼
 * @param mdt {ACL_MDT*} ݱ
 * @param data {void*} ûĶ̬,  ACL_MDT_FLAG_DMR ־λ
 *  δãڲһݸö̬
 * @param dlen {unsigned int} data ݳ
 * @param key_labels {const char*[]} ݱֶ飬NULL
 * @param keys {const char*[]} ݱֵֶ飬NULL
 * @return {ACL_MDT_NOD*} ӵݽ
 */
ACL_API ACL_MDT_NOD *acl_mdt_add(ACL_MDT *mdt, void *data,
	unsigned int dlen, const char *key_labels[], const char *keys[]);

/**
 * ̽ݱжӦֵֶǷ
 * @param mdt {ACL_MDT*} ݱ
 * @param key_label {const char*} ݱֶ
 * @param key {const char*} ݱֶμֵ
 * @return {int} 0: , != 0: 
 */
ACL_API int acl_mdt_probe(ACL_MDT *mdt, const char *key_label, const char *key);

/**
 * ݱвѯĳݱֵĽ
 * @param mdt {ACL_MDT*} ݱ
 * @param key_label {const char*} ݱֶ
 * @param key {const char*} ݱֶμֵ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param limit {int} ѯĽϣ
 * @return {ACL_MDT_REC*} ӦĳֵֶĽ
 */
ACL_API ACL_MDT_RES *acl_mdt_find(ACL_MDT *mdt, const char *key_label,
	const char *key, int from, int limit);

/**
 * ݱ˳гĳΧڵݽ㼯
 * @param mdt {ACL_MDT*} ݱ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param limit {int} ѯĽϣ
 * @return {ACL_MDT_REC*} ӦĳֵֶĽ
 */
ACL_API ACL_MDT_RES *acl_mdt_list(ACL_MDT *mdt, int from, int limit);

/**
 * ݱɾӦĳֶμֵĽ
 * @param mdt {ACL_MDT*} ݱ
 * @param key_label {const char*} ݱֶ
 * @param key {const char*} ݱֶμֵ
 * @param onfree_fn {void (*)(void*, unsigned int}
 *	ûͷŶ̬ݵĻص
 * @return {int} ͷŵݽĿ
 */
ACL_API int acl_mdt_delete(ACL_MDT *mdt, const char *key_label,
	const char *key, void (*onfree_fn)(void*, unsigned int));

/**
 * ݱݽ㣬صûĴ
 * @param mdt {ACL_MDT*} ݱ
 * @param walk_fn ص0ֹͣ
 * @param from {int} ѯĽϣǴӸλÿʼд洢
 * @param len {int} ѯĽϣ
 * @return {int} ݳ
 */
ACL_API int acl_mdt_walk(ACL_MDT *mdt, int (*walk_fn)(const void*, unsigned int),
	int from, int len);

/**
 * ѯĽлȡһݽ
 * @param res {ACL_MDT_RES*} ݽ
 * @return {void*} ûԼܹʶĶ̬ݣNULLʾѾû
 */
ACL_API const void *acl_mdt_fetch_row(ACL_MDT_RES *res);

/**
 * òѯеļ¼
 * @param res {ACL_MDT_RES*} ݽ
 * @return {int} 0: Ϊ; > 0: Ϊ
 */
ACL_API int acl_mdt_row_count(ACL_MDT_RES *res);

/**
 * ͷŲѯ̬ڴ棬ͷʵʵݽ
 * @param res {ACL_MDT_RES*} ݽ
 */
ACL_API void acl_mdt_res_free(ACL_MDT_RES *res);

/**
 * ݱԪص
 * @param mdt {ACL_MDT*} ݱ
 * @return {int} >=0
 */
ACL_API int acl_mdt_cnt(ACL_MDT *mdt);

#ifdef	__cplusplus
}
#endif

#endif

