}
p->h = h;
p->pNext = ht->arBuckets[nIndex];
+ p->pLast = NULL;
+ if (p->pNext) {
+ p->pNext->pLast = p;
+ }
if (pDest) {
*pDest = p->pData;
}
}
p->h = h;
p->pNext = ht->arBuckets[nIndex];
+ p->pLast = NULL;
+ if (p->pNext) {
+ p->pNext->pLast = p;
+ }
if (pDest) {
*pDest = p->pData;
}
}
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;
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;
}
} else {
t->pNext = p->pNext;
}
+ if (p->pNext) {
+ p->pNext->pLast = p->pLast;
+ }
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
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
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);
}
}
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;
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);
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;
}
}
}
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;
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;
}
}
IS_CONSISTENT(source);
IS_CONSISTENT(target);
- p = source->pListHead;
+ p = source->pListHead;
while (p) {
memcpy(tmp, p->pData, size);
if (pCopyConstructor) {