mirror of
https://github.com/php/php-src.git
synced 2025-08-18 15:08:55 +02:00
- Hopefully fix the hash problem.
This commit is contained in:
parent
2b6d84ff37
commit
aa73f6b68f
2 changed files with 53 additions and 47 deletions
|
@ -228,6 +228,10 @@ ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength
|
||||||
}
|
}
|
||||||
p->h = h;
|
p->h = h;
|
||||||
p->pNext = ht->arBuckets[nIndex];
|
p->pNext = ht->arBuckets[nIndex];
|
||||||
|
p->pLast = NULL;
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p;
|
||||||
|
}
|
||||||
if (pDest) {
|
if (pDest) {
|
||||||
*pDest = p->pData;
|
*pDest = p->pData;
|
||||||
}
|
}
|
||||||
|
@ -334,6 +338,10 @@ ZEND_API int zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKey
|
||||||
}
|
}
|
||||||
p->h = h;
|
p->h = h;
|
||||||
p->pNext = ht->arBuckets[nIndex];
|
p->pNext = ht->arBuckets[nIndex];
|
||||||
|
p->pLast = NULL;
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p;
|
||||||
|
}
|
||||||
if (pDest) {
|
if (pDest) {
|
||||||
*pDest = p->pData;
|
*pDest = p->pData;
|
||||||
}
|
}
|
||||||
|
@ -438,6 +446,10 @@ ZEND_API int zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
|
||||||
}
|
}
|
||||||
|
|
||||||
p->pNext = ht->arBuckets[nIndex];
|
p->pNext = ht->arBuckets[nIndex];
|
||||||
|
p->pLast = NULL;
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p;
|
||||||
|
}
|
||||||
HANDLE_BLOCK_INTERRUPTIONS();
|
HANDLE_BLOCK_INTERRUPTIONS();
|
||||||
if (ht->pInternalPointer == NULL) {
|
if (ht->pInternalPointer == NULL) {
|
||||||
ht->pInternalPointer = p;
|
ht->pInternalPointer = p;
|
||||||
|
@ -513,6 +525,10 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
nIndex = p->h % ht->nTableSize;
|
nIndex = p->h % ht->nTableSize;
|
||||||
p->pNext = ht->arBuckets[nIndex];
|
p->pNext = ht->arBuckets[nIndex];
|
||||||
|
p->pLast = NULL;
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p;
|
||||||
|
}
|
||||||
ht->arBuckets[nIndex] = p;
|
ht->arBuckets[nIndex] = p;
|
||||||
p = p->pListNext;
|
p = p->pListNext;
|
||||||
}
|
}
|
||||||
|
@ -542,6 +558,9 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
|
||||||
} else {
|
} else {
|
||||||
t->pNext = p->pNext;
|
t->pNext = p->pNext;
|
||||||
}
|
}
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p->pLast;
|
||||||
|
}
|
||||||
if (p->pListLast != NULL) {
|
if (p->pListLast != NULL) {
|
||||||
p->pListLast->pListNext = p->pListNext;
|
p->pListLast->pListNext = p->pListNext;
|
||||||
} else {
|
} else {
|
||||||
|
@ -630,7 +649,6 @@ ZEND_API void zend_hash_clean(HashTable *ht)
|
||||||
SET_INCONSISTENT(HT_OK);
|
SET_INCONSISTENT(HT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* This function is used by the various apply() functions.
|
/* This function is used by the various apply() functions.
|
||||||
* It deletes the passed bucket, and returns the address of the
|
* It deletes the passed bucket, and returns the address of the
|
||||||
* next bucket. The hash *may* be altered during that time, the
|
* next bucket. The hash *may* be altered during that time, the
|
||||||
|
@ -639,12 +657,9 @@ ZEND_API void zend_hash_clean(HashTable *ht)
|
||||||
static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
|
static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
|
||||||
{
|
{
|
||||||
Bucket *retval;
|
Bucket *retval;
|
||||||
uint nIndex;
|
|
||||||
|
|
||||||
HANDLE_BLOCK_INTERRUPTIONS();
|
HANDLE_BLOCK_INTERRUPTIONS();
|
||||||
|
|
||||||
nIndex = p->h % ht->nTableSize;
|
|
||||||
|
|
||||||
if (ht->pDestructor) {
|
if (ht->pDestructor) {
|
||||||
ht->pDestructor(p->pData);
|
ht->pDestructor(p->pData);
|
||||||
}
|
}
|
||||||
|
@ -653,9 +668,19 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
|
||||||
}
|
}
|
||||||
retval = p->pListNext;
|
retval = p->pListNext;
|
||||||
|
|
||||||
if (ht->arBuckets[nIndex] == p) {
|
if (p->pLast) {
|
||||||
|
p->pLast->pNext = p->pNext;
|
||||||
|
} else {
|
||||||
|
uint nIndex;
|
||||||
|
|
||||||
|
nIndex = p->h % ht->nTableSize;
|
||||||
ht->arBuckets[nIndex] = p->pNext;
|
ht->arBuckets[nIndex] = p->pNext;
|
||||||
}
|
}
|
||||||
|
if (p->pNext) {
|
||||||
|
p->pNext->pLast = p->pLast;
|
||||||
|
} else {
|
||||||
|
/* Nothing to do as this list doesn't have a tail */
|
||||||
|
}
|
||||||
|
|
||||||
if (p->pListLast != NULL) {
|
if (p->pListLast != NULL) {
|
||||||
p->pListLast->pListNext = p->pListNext;
|
p->pListLast->pListNext = p->pListNext;
|
||||||
|
@ -678,24 +703,16 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
|
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
|
||||||
{
|
{
|
||||||
Bucket *p, *q;
|
Bucket *p;
|
||||||
|
|
||||||
IS_CONSISTENT(ht);
|
IS_CONSISTENT(ht);
|
||||||
|
|
||||||
p = ht->pListHead;
|
p = ht->pListHead;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
q = p;
|
p = zend_hash_apply_deleter(ht,p);
|
||||||
p = p->pListNext;
|
|
||||||
if (q->nKeyLength==0) {
|
|
||||||
zend_hash_index_del(ht, q->h);
|
|
||||||
} else {
|
|
||||||
zend_hash_del(ht, q->arKey, q->nKeyLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pefree(ht->arBuckets,ht->persistent);
|
pefree(ht->arBuckets,ht->persistent);
|
||||||
|
|
||||||
|
@ -710,41 +727,33 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
|
||||||
|
|
||||||
ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *))
|
ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *))
|
||||||
{
|
{
|
||||||
Bucket *p, *q;
|
Bucket *p;
|
||||||
|
|
||||||
IS_CONSISTENT(ht);
|
IS_CONSISTENT(ht);
|
||||||
|
|
||||||
p = ht->pListHead;
|
p = ht->pListHead;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
q = p;
|
if (destruct(p->pData)) {
|
||||||
p = p->pListNext;
|
p = zend_hash_apply_deleter(ht,p);
|
||||||
if (destruct(q->pData)) {
|
} else {
|
||||||
if (q->nKeyLength==0) {
|
p = p->pListNext;
|
||||||
zend_hash_index_del(ht, q->h);
|
}
|
||||||
} else {
|
|
||||||
zend_hash_del(ht, q->arKey, q->nKeyLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument)
|
ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument)
|
||||||
{
|
{
|
||||||
Bucket *p, *q;
|
Bucket *p;
|
||||||
|
|
||||||
IS_CONSISTENT(ht);
|
IS_CONSISTENT(ht);
|
||||||
|
|
||||||
p = ht->pListHead;
|
p = ht->pListHead;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
q = p;
|
if (destruct(p->pData, argument)) {
|
||||||
p = p->pListNext;
|
p = zend_hash_apply_deleter(ht,p);
|
||||||
if (destruct(q->pData, argument)) {
|
} else {
|
||||||
if (q->nKeyLength==0) {
|
p = p->pListNext;
|
||||||
zend_hash_index_del(ht, q->h);
|
|
||||||
} else {
|
|
||||||
zend_hash_del(ht, q->arKey, q->nKeyLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -752,7 +761,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void
|
||||||
|
|
||||||
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void *, int, va_list, zend_hash_key *), int num_args, ...)
|
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void *, int, va_list, zend_hash_key *), int num_args, ...)
|
||||||
{
|
{
|
||||||
Bucket *p, *q;
|
Bucket *p;
|
||||||
va_list args;
|
va_list args;
|
||||||
zend_hash_key hash_key;
|
zend_hash_key hash_key;
|
||||||
|
|
||||||
|
@ -762,17 +771,13 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void
|
||||||
|
|
||||||
p = ht->pListHead;
|
p = ht->pListHead;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
q = p;
|
hash_key.arKey = p->arKey;
|
||||||
p = p->pListNext;
|
hash_key.nKeyLength = p->nKeyLength;
|
||||||
hash_key.arKey = q->arKey;
|
hash_key.h = p->h;
|
||||||
hash_key.nKeyLength = q->nKeyLength;
|
if (destruct(p->pData, num_args, args, &hash_key)) {
|
||||||
hash_key.h = q->h;
|
p = zend_hash_apply_deleter(ht,p);
|
||||||
if (destruct(q->pData, num_args, args, &hash_key)) {
|
} else {
|
||||||
if (q->nKeyLength==0) {
|
p = p->pListNext;
|
||||||
zend_hash_index_del(ht, q->h);
|
|
||||||
} else {
|
|
||||||
zend_hash_del(ht, q->arKey, q->nKeyLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,7 +793,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyC
|
||||||
IS_CONSISTENT(source);
|
IS_CONSISTENT(source);
|
||||||
IS_CONSISTENT(target);
|
IS_CONSISTENT(target);
|
||||||
|
|
||||||
p = source->pListHead;
|
p = source->pListHead;
|
||||||
while (p) {
|
while (p) {
|
||||||
memcpy(tmp, p->pData, size);
|
memcpy(tmp, p->pData, size);
|
||||||
if (pCopyConstructor) {
|
if (pCopyConstructor) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct bucket {
|
||||||
struct bucket *pListNext;
|
struct bucket *pListNext;
|
||||||
struct bucket *pListLast;
|
struct bucket *pListLast;
|
||||||
struct bucket *pNext;
|
struct bucket *pNext;
|
||||||
|
struct bucket *pLast;
|
||||||
char arKey[1]; /* Must be last element */
|
char arKey[1]; /* Must be last element */
|
||||||
} Bucket;
|
} Bucket;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue