]> granicus.if.org Git - php/commitdiff
- Hopefully fix the hash problem.
authorAndi Gutmans <andi@php.net>
Wed, 19 Jan 2000 19:44:32 +0000 (19:44 +0000)
committerAndi Gutmans <andi@php.net>
Wed, 19 Jan 2000 19:44:32 +0000 (19:44 +0000)
Zend/zend_hash.c
Zend/zend_hash.h

index c3563852a54e224641a7c62597520a4374dc8a11..225e1adf0e6a6b91835bc31a12dc2befb1abe2e3 100644 (file)
@@ -228,6 +228,10 @@ ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength
        }
        p->h = h;
        p->pNext = ht->arBuckets[nIndex];
+       p->pLast = NULL;
+       if (p->pNext) {
+               p->pNext->pLast = p;
+       }
        if (pDest) {
                *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->pNext = ht->arBuckets[nIndex];
+       p->pLast = NULL;
+       if (p->pNext) {
+               p->pNext->pLast = p;
+       }
        if (pDest) {
                *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->pLast = NULL;
+       if (p->pNext) {
+               p->pNext->pLast = p;
+       }
        HANDLE_BLOCK_INTERRUPTIONS();
        if (ht->pInternalPointer == NULL) {
                ht->pInternalPointer = p;
@@ -513,6 +525,10 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
        while (p != NULL) {
                nIndex = p->h % ht->nTableSize;
                p->pNext = ht->arBuckets[nIndex];
+               p->pLast = NULL;
+               if (p->pNext) {
+                       p->pNext->pLast = p;
+               }
                ht->arBuckets[nIndex] = p;
                p = p->pListNext;
        }
@@ -542,6 +558,9 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
                        } else {
                                t->pNext = p->pNext;
                        }
+                       if (p->pNext) {
+                               p->pNext->pLast = p->pLast;
+                       }
                        if (p->pListLast != NULL) {
                                p->pListLast->pListNext = p->pListNext;
                        } else { 
@@ -630,7 +649,6 @@ ZEND_API void zend_hash_clean(HashTable *ht)
        SET_INCONSISTENT(HT_OK);
 }
 
-#if 0
 /* This function is used by the various apply() functions.
  * It deletes the passed bucket, and returns the address of 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)
 {
        Bucket *retval;
-       uint nIndex;
 
        HANDLE_BLOCK_INTERRUPTIONS();
 
-       nIndex = p->h % ht->nTableSize;
-
        if (ht->pDestructor) {
                ht->pDestructor(p->pData);
        }
@@ -653,9 +668,19 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
        }
        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;
        }
+       if (p->pNext) {
+               p->pNext->pLast = p->pLast;
+       } else {
+               /* Nothing to do as this list doesn't have a tail */
+       }
 
        if (p->pListLast != NULL) {
                p->pListLast->pListNext = p->pListNext;
@@ -678,24 +703,16 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
        return retval;
 }
 
-#endif
-
 
 ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
 {
-       Bucket *p, *q;
+       Bucket *p;
 
        IS_CONSISTENT(ht);
 
        p = ht->pListHead;
        while (p != NULL) {
-               q = p;
-               p = p->pListNext;
-               if (q->nKeyLength==0) {
-                       zend_hash_index_del(ht, q->h);
-               } else {
-                       zend_hash_del(ht, q->arKey, q->nKeyLength);
-               }
+               p = zend_hash_apply_deleter(ht,p);
        }
        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 *))
 {
-        Bucket *p, *q;
+        Bucket *p;
 
         IS_CONSISTENT(ht);
 
         p = ht->pListHead;
         while (p != NULL) {
-                q = p;
-                p = p->pListNext;
-               if (destruct(q->pData)) {
-                       if (q->nKeyLength==0) {
-                               zend_hash_index_del(ht, q->h);
-                       } else {
-                               zend_hash_del(ht, q->arKey, q->nKeyLength);
-                       }
-                }
+               if (destruct(p->pData)) {
+                       p = zend_hash_apply_deleter(ht,p); 
+                } else {
+                       p = p->pListNext;
+               }
         }
 }
 
 
 ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument)
 {
-        Bucket *p, *q;
+        Bucket *p;
 
         IS_CONSISTENT(ht);
 
         p = ht->pListHead;
         while (p != NULL) {
-                q = p;  
-                p = p->pListNext;
-                if (destruct(q->pData, argument)) {
-                        if (q->nKeyLength==0) {
-                                zend_hash_index_del(ht, q->h);
-                        } else {
-                                zend_hash_del(ht, q->arKey, q->nKeyLength);
-                        }
+                if (destruct(p->pData, argument)) {
+                        p = zend_hash_apply_deleter(ht,p);
+                } else {
+                        p = p->pListNext;
                 }
         }
 }
@@ -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, ...)
 {
-       Bucket *p, *q;
+       Bucket *p;
        va_list args;
        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;
        while (p != NULL) {
-               q = p;
-               p = p->pListNext;
-               hash_key.arKey = q->arKey;
-               hash_key.nKeyLength = q->nKeyLength;
-               hash_key.h = q->h;
-               if (destruct(q->pData, num_args, args, &hash_key)) {
-                       if (q->nKeyLength==0) {
-                                zend_hash_index_del(ht, q->h);
-                        } else {
-                                zend_hash_del(ht, q->arKey, q->nKeyLength);
-                        }
+               hash_key.arKey = p->arKey;
+               hash_key.nKeyLength = p->nKeyLength;
+               hash_key.h = p->h;
+               if (destruct(p->pData, num_args, args, &hash_key)) {
+                        p = zend_hash_apply_deleter(ht,p);
+                } else {
+                        p = p->pListNext;
                }
        }
 
@@ -788,7 +793,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyC
        IS_CONSISTENT(source);
        IS_CONSISTENT(target);
 
-    p = source->pListHead;
+       p = source->pListHead;
        while (p) {
                memcpy(tmp, p->pData, size);
                if (pCopyConstructor) {
index 95138a8a85f2b7d41ce666f46ff732ae53eb4207..b824cd4bf30e7a59bd6d45e2163e9aa01e8d5cb5 100644 (file)
@@ -49,6 +49,7 @@ typedef struct bucket {
        struct bucket *pListNext;
        struct bucket *pListLast;
        struct bucket *pNext;
+       struct bucket *pLast;
        char arKey[1]; /* Must be last element */
 } Bucket;