added qse_htb_cbsert().
exported qse_htb_allocpair() and qse_htb_freepair()
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: htb.c 363 2010-10-27 12:54:37Z hyunghwan.chung $ | ||||
|  * $Id: htb.c 364 2010-10-28 13:09:53Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -23,15 +23,16 @@ | ||||
|  | ||||
| QSE_IMPLEMENT_COMMON_FUNCTIONS (htb) | ||||
|  | ||||
| #define htb_t    qse_htb_t | ||||
| #define pair_t   qse_htb_pair_t | ||||
| #define copier_t qse_htb_copier_t | ||||
| #define freeer_t qse_htb_freeer_t | ||||
| #define hasher_t qse_htb_hasher_t | ||||
| #define comper_t qse_htb_comper_t | ||||
| #define keeper_t qse_htb_keeper_t | ||||
| #define sizer_t  qse_htb_sizer_t | ||||
| #define walker_t qse_htb_walker_t | ||||
| #define htb_t      qse_htb_t | ||||
| #define pair_t     qse_htb_pair_t | ||||
| #define copier_t   qse_htb_copier_t | ||||
| #define freeer_t   qse_htb_freeer_t | ||||
| #define hasher_t   qse_htb_hasher_t | ||||
| #define comper_t   qse_htb_comper_t | ||||
| #define keeper_t   qse_htb_keeper_t | ||||
| #define sizer_t    qse_htb_sizer_t | ||||
| #define walker_t   qse_htb_walker_t | ||||
| #define cbserter_t qse_htb_cbserter_t | ||||
|  | ||||
| #define KPTR(p)  QSE_HTB_KPTR(p) | ||||
| #define KLEN(p)  QSE_HTB_KLEN(p) | ||||
| @ -47,14 +48,8 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (htb) | ||||
| #define KTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_KEY]) | ||||
| #define VTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_VAL]) | ||||
|  | ||||
| #define UPSERT 1 | ||||
| #define UPDATE 2 | ||||
| #define ENSERT 3 | ||||
| #define INSERT 4 | ||||
|  | ||||
|  | ||||
| static pair_t* alloc_pair (htb_t* htb,  | ||||
| 	void* kptr, size_t klen, void* vptr, size_t vlen) | ||||
| QSE_INLINE pair_t* qse_htb_allocpair ( | ||||
| 	htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen) | ||||
| { | ||||
| 	pair_t* n; | ||||
| 	copier_t kcop = htb->mancbs->copier[QSE_HTB_KEY]; | ||||
| @ -116,7 +111,7 @@ static pair_t* alloc_pair (htb_t* htb, | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static void free_pair (htb_t* htb, pair_t* pair) | ||||
| QSE_INLINE void qse_htb_freepair (htb_t* htb, pair_t* pair) | ||||
| { | ||||
| 	if (htb->mancbs->freeer[QSE_HTB_KEY] != QSE_NULL)  | ||||
| 		htb->mancbs->freeer[QSE_HTB_KEY] (htb, KPTR(pair), KLEN(pair)); | ||||
| @ -125,7 +120,7 @@ static void free_pair (htb_t* htb, pair_t* pair) | ||||
| 	QSE_MMGR_FREE (htb->mmgr, pair); | ||||
| } | ||||
|  | ||||
| static pair_t* change_pair_val ( | ||||
| static QSE_INLINE pair_t* change_pair_val ( | ||||
| 	htb_t* htb, pair_t* pair, void* vptr, size_t vlen) | ||||
| { | ||||
| 	if (VPTR(pair) == vptr && VLEN(pair) == vlen)  | ||||
| @ -159,11 +154,11 @@ static pair_t* change_pair_val ( | ||||
| 			else | ||||
| 			{ | ||||
| 				/* need to reconstruct the pair */ | ||||
| 				pair_t* p = alloc_pair (htb,  | ||||
| 				pair_t* p = qse_htb_allocpair (htb,  | ||||
| 					KPTR(pair), KLEN(pair), | ||||
| 					vptr, vlen); | ||||
| 				if (p == QSE_NULL) return QSE_NULL; | ||||
| 				free_pair (htb, pair); | ||||
| 				qse_htb_freepair (htb, pair); | ||||
| 				return p; | ||||
| 			} | ||||
| 		} | ||||
| @ -332,79 +327,6 @@ void qse_htb_setmancbs (htb_t* htb, const qse_htb_mancbs_t* mancbs) | ||||
| 	htb->mancbs = mancbs; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| copier_t qse_htb_getcopier (htb_t* htb, qse_htb_id_t id) | ||||
| { | ||||
| 	QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, | ||||
| 		"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); | ||||
| 	return htb->copier[id]; | ||||
| } | ||||
|  | ||||
| void qse_htb_setcopier (htb_t* htb, qse_htb_id_t id, copier_t copier) | ||||
| { | ||||
| 	QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, | ||||
| 		"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); | ||||
| 	if (copier == QSE_NULL) copier = QSE_HTB_COPIER_SIMPLE; | ||||
| 	htb->copier[id] = copier; | ||||
| } | ||||
|  | ||||
| freeer_t qse_htb_getfreeer (htb_t* htb, qse_htb_id_t id) | ||||
| { | ||||
| 	QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, | ||||
| 		"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); | ||||
| 	return htb->freeer[id]; | ||||
| } | ||||
|  | ||||
| void qse_htb_setfreeer (htb_t* htb, qse_htb_id_t id, freeer_t freeer) | ||||
| { | ||||
| 	QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, | ||||
| 		"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); | ||||
| 	htb->freeer[id] = freeer; | ||||
| } | ||||
|  | ||||
| hasher_t qse_htb_gethasher (htb_t* htb) | ||||
| { | ||||
| 	return htb->hasher; | ||||
| } | ||||
|  | ||||
| void qse_htb_sethasher (htb_t* htb, hasher_t hasher) | ||||
| { | ||||
| 	if (hasher == QSE_NULL) hasher = hash_key; | ||||
| 	htb->hasher = hasher;	 | ||||
| } | ||||
|  | ||||
| comper_t qse_htb_getcomper (htb_t* htb) | ||||
| { | ||||
| 	return htb->comper; | ||||
| } | ||||
|  | ||||
| void qse_htb_setcomper (htb_t* htb, comper_t comper) | ||||
| { | ||||
| 	if (comper == QSE_NULL) comper = comp_key; | ||||
| 	htb->comper = comper; | ||||
| } | ||||
|  | ||||
| keeper_t qse_htb_getkeeper (htb_t* htb) | ||||
| { | ||||
| 	return htb->keeper; | ||||
| } | ||||
|  | ||||
| void qse_htb_setkeeper (htb_t* htb, keeper_t keeper) | ||||
| { | ||||
| 	htb->keeper = keeper; | ||||
| } | ||||
|  | ||||
| sizer_t qse_htb_getsizer (htb_t* htb) | ||||
| { | ||||
| 	return htb->sizer; | ||||
| } | ||||
|  | ||||
| void qse_htb_setsizer (htb_t* htb, sizer_t sizer) | ||||
| { | ||||
| 	htb->sizer = sizer; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| size_t qse_htb_getsize (htb_t* htb) | ||||
| { | ||||
| 	return htb->size; | ||||
| @ -498,6 +420,12 @@ static QSE_INLINE_ALWAYS int reorganize (htb_t* htb) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* insert options */ | ||||
| #define UPSERT 1 | ||||
| #define UPDATE 2 | ||||
| #define ENSERT 3 | ||||
| #define INSERT 4 | ||||
|  | ||||
| static pair_t* insert ( | ||||
| 	htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen, int opt) | ||||
| { | ||||
| @ -522,17 +450,18 @@ static pair_t* insert ( | ||||
| 					p = change_pair_val (htb, pair, vptr, vlen); | ||||
| 					if (p == QSE_NULL)  | ||||
| 					{ | ||||
| 						/* error in change the value */ | ||||
| 						/* error in changing the value */ | ||||
| 						return QSE_NULL;  | ||||
| 					} | ||||
| 					if (p != pair)  | ||||
| 					{ | ||||
| 						/* pair reallocated.  | ||||
| 						 * relink it */ | ||||
| 						/* old pair destroyed. new pair reallocated. | ||||
| 						 * relink to include the new pair but to drop | ||||
| 						 * the old pair. */ | ||||
| 						if (prev == QSE_NULL)  | ||||
| 							htb->bucket[hc] = p; | ||||
| 						else NEXT(prev) = p; | ||||
| 						NEXT(p) = next; | ||||
| 						NEXT(p) = next;  | ||||
| 					} | ||||
| 					return p; | ||||
|  | ||||
| @ -554,7 +483,9 @@ static pair_t* insert ( | ||||
|  | ||||
| 	if (htb->threshold > 0 && htb->size >= htb->threshold) | ||||
| 	{ | ||||
| 		if (reorganize(htb) == 0) /* ignore the error */ | ||||
| 		/* ingore reorganization error as it simply means | ||||
| 		 * more bucket collision and performance penalty. */ | ||||
| 		if (reorganize(htb) == 0)  | ||||
| 		{ | ||||
| 			hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa; | ||||
| 		} | ||||
| @ -562,7 +493,7 @@ static pair_t* insert ( | ||||
|  | ||||
| 	QSE_ASSERT (pair == QSE_NULL); | ||||
|  | ||||
| 	pair = alloc_pair (htb, kptr, klen, vptr, vlen); | ||||
| 	pair = qse_htb_allocpair (htb, kptr, klen, vptr, vlen); | ||||
| 	if (pair == QSE_NULL) return QSE_NULL; /* error */ | ||||
|  | ||||
| 	NEXT(pair) = htb->bucket[hc]; | ||||
| @ -597,6 +528,68 @@ pair_t* qse_htb_update ( | ||||
| 	return insert (htb, kptr, klen, vptr, vlen, UPDATE); | ||||
| } | ||||
|  | ||||
| pair_t* qse_htb_cbsert ( | ||||
| 	htb_t* htb, void* kptr, size_t klen, cbserter_t cbserter, void* ctx) | ||||
| { | ||||
| 	pair_t* pair, * p, * prev, * next; | ||||
| 	size_t hc; | ||||
|  | ||||
| 	hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa; | ||||
| 	pair = htb->bucket[hc]; | ||||
| 	prev = QSE_NULL; | ||||
|  | ||||
| 	while (pair != QSE_NULL)  | ||||
| 	{ | ||||
| 		next = NEXT(pair); | ||||
|  | ||||
| 		if (htb->mancbs->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)  | ||||
| 		{ | ||||
| 			/* found a pair with a matching key */ | ||||
| 			p = cbserter (htb, pair, kptr, klen, ctx); | ||||
| 			if (p == QSE_NULL)  | ||||
| 			{ | ||||
| 				/* error returned by the callback function */ | ||||
| 				return QSE_NULL;  | ||||
| 			} | ||||
| 			if (p != pair)  | ||||
| 			{ | ||||
| 				/* old pair destroyed. new pair reallocated. | ||||
| 				 * relink to include the new pair but to drop | ||||
| 				 * the old pair. */ | ||||
| 				if (prev == QSE_NULL)  | ||||
| 					htb->bucket[hc] = p; | ||||
| 				else NEXT(prev) = p; | ||||
| 				NEXT(p) = next;  | ||||
| 			} | ||||
| 			return p; | ||||
| 		} | ||||
|  | ||||
| 		prev = pair; | ||||
| 		pair = next; | ||||
| 	} | ||||
|  | ||||
| 	if (htb->threshold > 0 && htb->size >= htb->threshold) | ||||
| 	{ | ||||
| 		/* ingore reorganization error as it simply means | ||||
| 		 * more bucket collision and performance penalty. */ | ||||
| 		if (reorganize(htb) == 0) | ||||
| 		{ | ||||
| 			hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	QSE_ASSERT (pair == QSE_NULL); | ||||
|  | ||||
| 	pair = cbserter (htb, QSE_NULL, kptr, klen, ctx); | ||||
| 	if (pair == QSE_NULL) return QSE_NULL; /* error */ | ||||
|  | ||||
| 	NEXT(pair) = htb->bucket[hc]; | ||||
| 	htb->bucket[hc] = pair; | ||||
| 	htb->size++; | ||||
|  | ||||
| 	return pair; /* new key added */ | ||||
| } | ||||
|  | ||||
| int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen) | ||||
| { | ||||
| 	pair_t* pair, * prev; | ||||
| @ -614,7 +607,7 @@ int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen) | ||||
| 				htb->bucket[hc] = NEXT(pair); | ||||
| 			else NEXT(prev) = NEXT(pair); | ||||
|  | ||||
| 			free_pair (htb, pair); | ||||
| 			qse_htb_freepair (htb, pair); | ||||
| 			htb->size--; | ||||
|  | ||||
| 			return 0; | ||||
| @ -639,7 +632,7 @@ void qse_htb_clear (htb_t* htb) | ||||
| 		while (pair != QSE_NULL)  | ||||
| 		{ | ||||
| 			next = NEXT(pair); | ||||
| 			free_pair (htb, pair); | ||||
| 			qse_htb_freepair (htb, pair); | ||||
| 			htb->size--; | ||||
| 			pair = next; | ||||
| 		} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user