<!-- #
include
<stdio.h-->#
include
#
include
typedef unsigned long ulong;typedef unsigned int uint;typedef unsigned char zend_bool;typedef unsigned int size_t;typedef void (*dtor_func_t)(void *pDest);typedef ulong (*hash_func_t)(char *arKey, uint nKeyLength);#define SUCCESS 0#define FAILURE -1
#define HASH_UPDATE (1<<0)#define HASH_ADD (1<<1)#define HASH_NEXT_INSERT(1<<2) #define HASH_DEL_KEY 0 #define perealloc_recoverable(ptr, size, persistent) (__zend_realloc((ptr), (size)))#define pefree_rel(ptr, persistent)(free(ptr))
void *tmp = malloc(len);
if
(tmp) {
return
tmp;
}
fprintf
(stderr,
"Out of memory\n"
);
exit
(1);}
inline
static
void * __zend_realloc(void *p, size_t len) {
p = realloc(p, len);
if
(p) {
return
p;
}
fprintf
(stderr,
"Out of memory\n"
);
exit
(1);}
typedef struct bucket {
ulong h;
uint nKeyLength;
void *pData;
void *pDataPtr;
struct bucket *pListNext;
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
char arKey[1];
} Bucket;
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer;
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;} HashTable;
typedef struct _zend_hash_key {
char *arKey;
uint nKeyLength;
ulong h;} zend_hash_key; typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);
#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
(element)->pNext = (list_head); \
(element)->pLast = NULL; \
if
((element)->pNext) { \
(element)->pNext->pLast = (element); \
} #define CONNECT_TO_GLOBAL_DLLIST(element, ht) \
(element)->pListLast = (ht)->pListTail; \
(ht)->pListTail = (element); \
(element)->pListNext = NULL; \
if
((element)->pListLast != NULL) { \
(element)->pListLast->pListNext = (element); \
} \
if
(!(ht)->pListHead) { \
(ht)->pListHead = (element); \
} \
if
((ht)->pInternalPointer == NULL) { \
(ht)->pInternalPointer = (element); \
} #define ZEND_HASH_IF_FULL_DO_RESIZE(ht) \
if
((ht)->nNumOfElements > (ht)->nTableSize) {\
zend_hash_do_resize(ht); \
} int zend_hash_rehash(HashTable *ht) {
Bucket *p;
uint nIndex;
memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
p = ht->pListHead;
while
(p != NULL) {
nIndex = p->h & ht->nTableMask;
CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
ht->arBuckets[nIndex] = p;
p = p->pListNext;
}
return
SUCCESS;}
static
int zend_hash_do_resize(HashTable *ht) {
Bucket **t;
if
((ht->nTableSize << 1) > 0) {
t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
if
(t) {
ht->arBuckets = t;
ht->nTableSize = (ht->nTableSize << 1);
ht->nTableMask = ht->nTableSize - 1;
zend_hash_rehash(ht);
return
SUCCESS;
}
return
FAILURE;
}
return
SUCCESS;}
#define UPDATE_DATA(ht, p, pData, nDataSize) \
if
(nDataSize == sizeof(void*)) { \
if
((p)->pData != &(p)->pDataPtr) { \
pefree_rel((p)->pData, (ht)->persistent); \
} \
memcpy(&(p)->pDataPtr, pData, sizeof(void *)); \
(p)->pData = &(p)->pDataPtr; \
}
else
{ \
if
((p)->pData == &(p)->pDataPtr) { \
(p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent); \
(p)->pDataPtr=NULL; \
}
else
{ \
(p)->pData = (void *) perealloc_rel((p)->pData, nDataSize, (ht)->persistent);\
\
} \
memcpy((p)->pData, pData, nDataSize); \
} #define INIT_DATA(ht, p, pData, nDataSize); \
if
(nDataSize == sizeof(void*)) { \
memcpy(&(p)->pDataPtr, pData, sizeof(void *)); \
(p)->pData = &(p)->pDataPtr; \
}
else
{ \
(p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);\
if
(!(p)->pData) { \
pefree_rel(p, (ht)->persistent); \
return
FAILURE; \
} \
memcpy((p)->pData, pData, nDataSize); \
(p)->pDataPtr=NULL; \
}
static
inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength) {
register ulong hash = 5381;
for
(; nKeyLength >= 8; nKeyLength -= 8) {
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
hash = ((hash << 5) + hash) + *arKey++;
}
switch
(nKeyLength) {
case
7: hash = ((hash << 5) + hash) + *arKey++;
case
6: hash = ((hash << 5) + hash) + *arKey++;
case
5: hash = ((hash << 5) + hash) + *arKey++;
case
4: hash = ((hash << 5) + hash) + *arKey++;
case
3: hash = ((hash << 5) + hash) + *arKey++;
case
2: hash = ((hash << 5) + hash) + *arKey++;
case
1: hash = ((hash << 5) + hash) + *arKey++;
break
;
case
0:
break
;
}
return
hash;}ulong zend_hash_func(char *arKey, uint nKeyLength) {
return
zend_inline_hash_func(arKey, nKeyLength);}
uint i = 3;
Bucket **tmp;
zend_bool persistent = 1;
if
(nSize >= 0x80000000) {
ht->nTableSize = 0x80000000;
}
else
{
while
((1U << i) < nSize) {
i++;
}
ht->nTableSize = 1 << i;
}
ht->nTableMask = ht->nTableSize - 1;
ht->pDestructor = pDestructor;
ht->arBuckets = NULL;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
ht->nNextFreeElement = 0;
ht->pInternalPointer = NULL;
ht->persistent = persistent;
ht->nApplyCount = 0;
ht->bApplyProtection = 1;
tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
if
(!tmp) {
return
FAILURE;
}
ht->arBuckets = tmp;
return
SUCCESS;} int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag) {
ulong h;
uint nIndex;
Bucket *p;
if
(nKeyLength <= 0) {
return
FAILURE;
}
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while
(p != NULL) {
if
((p->h == h) && (p->nKeyLength == nKeyLength)) {
if
(!memcmp(p->arKey, arKey, nKeyLength)) {
if
(flag & HASH_ADD) {
return
FAILURE;
}
if
(ht->pDestructor) {
ht->pDestructor(p->pData);
}
UPDATE_DATA(ht, p, pData, nDataSize);
if
(pDest) {
*pDest = p->pData;
}
return
SUCCESS;
}
}
p = p->pNext;}
p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
if
(!p) {
return
FAILURE;}memcpy(p->arKey, arKey, nKeyLength);p->nKeyLength = nKeyLength;INIT_DATA(ht, p, pData, nDataSize);p->h = h;CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
if
(pDest) {*pDest = p->pData;}
CONNECT_TO_GLOBAL_DLLIST(p, ht);ht->arBuckets[nIndex] = p;
ht->nNumOfElements++;ZEND_HASH_IF_FULL_DO_RESIZE(ht);
return
SUCCESS;} void zend_hash_destroy(HashTable *ht) {
Bucket *p, *q;
p = ht->pListHead;
while
(p != NULL) {
q = p;
p = p->pListNext;
if
(ht->pDestructor) {
ht->pDestructor(q->pData);
}
if
(q->pData != &q->pDataPtr) {
pefree(q->pData, ht->persistent);
}
pefree(q, ht->persistent);
}
pefree(ht->arBuckets, ht->persistent); }
int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData) {
ulong h;
uint nIndex;
Bucket *p;
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while
(p != NULL) {
if
((p->h == h) && (p->nKeyLength == nKeyLength)) {
if
(!memcmp(p->arKey, arKey, nKeyLength)) {
*pData = p->pData;
return
SUCCESS;
}
}
p = p->pNext;}
return
FAILURE;}
void zend_hash_display(HashTable *ht) {
Bucket *p;
uint i;
int flag = 0 ;
for
(i = 0; i < ht->nTableSize; i++) {
p = ht->arBuckets[i];
flag = 0;
while
(p != NULL) {
printf(
"(%d %s <==> 0x%lX %d) "
, i, p->arKey, p->h, p->pNext);
p = p->pNext;
flag = 1;
}
if
(flag == 1) {
printf(
"\n"
);
} }
p = ht->pListTail;
while
(p != NULL) {
printf(
"%s <==> 0x%lX\n"
, p->arKey, p->h);
p = p->pListLast;
}}int main() {
int i;
char ch[20];
HashTable ht;
zend_hash_init(&ht, 50, NULL, NULL);
for
(i = 30; i < 68; i++) {
sprintf(ch,
"%d"
, i);
ch[
strlen
(ch) + 1] = '\0';
zend_hash_add_or_update(&ht, ch,
strlen
(ch) + 1, NULL, 0, NULL, 0);
}
zend_hash_display(&ht);
zend_hash_destroy(&ht);
return
0;}?>