/*
* Copyright (c) 2003, 2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
* $Id: bht-int.h,v 1.12 2005/06/16 00:09:34 ca Exp $
*/
/*
** This file may be included multiple times! Do NOT protect against that.
*/
#include "sm/types.h"
#include "sm/error.h"
/* Structure of one hash table entry. */
typedef struct sm_bht_entry_S sm_bht_entry_T, *sm_bht_entry_P;
struct sm_bht_entry_S
{
/*
** Notice: we don't copy keys (or value)!
** These are just pointers to the original data.
** Hence they must be "persistent".
** Question: do we want to add an option to make a copy?
*/
char *bhe_key; /* lookup key */
uint bhe_len; /* key length */
void *bhe_value; /* associated value */
/* XXX should we use something from queue.h? */
sm_bht_entry_P bhe_next; /* colliding entry */
sm_bht_entry_P bhe_prev; /* colliding entry */
#if SM_TWO_KEYS
char *bhe_key2; /* lookup key */
uint bhe_len2; /* key length */
sm_bht_entry_P bhe_next2; /* colliding entry */
sm_bht_entry_P bhe_prev2; /* colliding entry */
#endif /* SM_TWO_KEYS */
};
/* Structure of one hash table. */
typedef struct sm_bht_S sm_bht_T, *sm_bht_P;
struct sm_bht_S
{
uint bht_size; /* length of entries array */
uint bht_used; /* number of entries in table */
uint bht_limit; /* max number of entries */
#if SM_BHT_PERF
/* performance (statistics) data */
ulong bht_adds; /* */
ulong bht_lookups; /* */
ulong bht_deletes; /* */
ulong bht_acollisions; /* */
ulong bht_lcollisions; /* */
ulong bht_dcollisions; /* */
uint bht_grows; /* */
uint bht_chainlen; /* */
uint bht_chainmax; /* */
#endif /* SM_BHT_PERF */
sm_bht_entry_P *bht_data; /* entries array, auto-resized */
#if SM_TWO_KEYS
sm_bht_entry_P *bht_data2; /* entries array, auto-resized */
#endif /* SM_TWO_KEYS */
};
/*
** bhfree_F should get both keys for the TWO_KEY case...
** or none at all (which makes some it harder for some applications
** that don't store the key in the value (struct)).
*/
typedef void (*sm_bhfree_F)(void *_value, void *_key, void *_ctx);
typedef sm_ret_T (*sm_bhwalk_F)(sm_bht_entry_P, void *);
sm_bht_P sm_bht_new(uint _size, uint _limit);
sm_ret_T sm_bht_create(sm_bht_P *_ptable);
sm_ret_T sm_bht_setopt(sm_bht_P _table, uint _htsize, uint _limit);
sm_ret_T sm_bht_getopt(sm_bht_P _table, uint *_phtsize, uint *_plimit);
sm_ret_T sm_bht_open(sm_bht_P *_ptable);
sm_ret_T sm_bht_add(sm_bht_P _bht, char *_key, uint _len,
#if SM_TWO_KEYS
char *_key2, uint _len2,
#endif /* SM_TWO_KEYS */
void *_value, sm_bht_entry_P *_entry);
sm_bht_entry_P sm_bht_locate(sm_bht_P _bht, const char *_key, uint _len);
void *sm_bht_find(sm_bht_P _bht, const char *_key, uint _len);
void sm_bht_rm(sm_bht_P _bht, const char *_key, uint _len,
sm_bhfree_F _free_fn, void *_ctx);
void sm_bht_rm_all(sm_bht_P _bht, const char *_key, uint _len,
sm_bhfree_F _free_fn, void *_ctx);
void sm_bht_destroy(sm_bht_P _bht, sm_bhfree_F _free_fn, void *_ctx);
sm_ret_T sm_bht_walk(sm_bht_P _bht, sm_bhwalk_F _fn, void *);
#if 0
sm_bht_entry_P *sm_bht_list(sm_bht_P _bht);
#endif /* 0 */
void sm_bht_stats(sm_bht_P _bht, char *_out, uint _len);
#ifndef SM_BHT_INT_H
#define SM_BHT_INT_H
/* For external access to the list */
#define bht_entry_next(bhe) ((bhe)->bhe_next)
#define bht_entry_prev(bhe) ((bhe)->bhe_prev)
#define bht_entry_key(bhe) ((bhe)->bhe_key)
#define bht_entry_keylen(bhe) ((bhe)->bhe_len)
#define bht_entry_value(bhe) ((bhe)->bhe_value)
#if SM_BHT_PERF
# define bhtincradd(table) ((table)->bht_adds++)
# define bhtincrlu(table) ((table)->bht_lookups++)
# define bhtincrdel(table) ((table)->bht_deletes++)
# define bhtincracol(table) ((table)->bht_acollisions++)
# define bhtincrlcol(table) ((table)->bht_lcollisions++)
# define BHTINCRDCOL(table, elem) do { \
if ((elem)->bhe_next != NULL || (elem)->bhe_prev != NULL) \
(table)->bht_dcollisions++; \
} while (0)
# define bhtincrgrows(table) ((table)->bht_grows++)
# define bhtinitchain(table) (table)->bht_chainlen = 0
# define BHTINCRCHAIN(table) do { \
if (++(table)->bht_chainlen > \
(table)->bht_chainmax) \
(table)->bht_chainmax = \
(table)->bht_chainlen;\
} while (0)
# define BHTCHAINLEN(table, elem) do { \
sm_bht_entry_P h; \
(table)->bht_chainlen = 0; \
h = elem; \
while (h != NULL) \
{ \
++(table)->bht_chainlen;\
h = h->bhe_next; \
} \
if ((table)->bht_chainlen > \
(table)->bht_chainmax) \
(table)->bht_chainmax = \
(table)->bht_chainlen;\
} while (0)
#else /* SM_BHT_PERF */
# define bhtincradd(table)
# define bhtincrlu(table)
# define bhtincrdel(table)
# define bhtincracol(table)
# define bhtincrlcol(table)
# define BHTINCRDCOL(table, elem)
# define bhtincrgrows(table)
# define bhtinitchain(table)
# define BHTINCRCHAIN(table)
# define BHTCHAINLEN(table, elem)
#endif /* SM_BHT_PERF */
#endif /* SM_BHT_INT_H */
syntax highlighted by Code2HTML, v. 0.9.1