ZEND_API void zend_hash_destroy(HashTable *ht) { Bucket *p, *q; IS_CONSISTENT(ht); SET_INCONSISTENT(HT_IS_DESTROYING); 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); } if (ht->nTableMask) { pefree(ht->arBuckets, ht->persistent); } SET_INCONSISTENT(HT_DESTROYED); }
ZEND_API void zend_hash_clean(HashTable *ht) { Bucket *p, *q; IS_CONSISTENT(ht); SET_INCONSISTENT(HT_CLEANING); 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); } memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *)); ht->pListHead = NULL; ht->pListTail = NULL; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; ht->pInternalPointer = NULL; SET_INCONSISTENT(HT_OK); }
ZEND_API void _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { uint i = 3; SET_INCONSISTENT(HT_OK); if (nSize >= 0x80000000) { /* prevent overflow */ ht->nTableSize = 0x80000000; } else { while ((1U << i) < nSize) { i++; } ht->nTableSize = 1 << i; } ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */ ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; ht->arData = NULL; ht->arHash = (zend_uint*)&uninitialized_bucket; ht->pDestructor = pDestructor; ht->nInternalPointer = INVALID_IDX; if (persistent) { ht->u.flags = HASH_FLAG_PERSISTENT | HASH_FLAG_APPLY_PROTECTION; } else { ht->u.flags = HASH_FLAG_APPLY_PROTECTION; } }
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { uint i = 3; SET_INCONSISTENT(HT_OK); if (nSize >= 0x80000000) { /* prevent overflow */ ht->nTableSize = 0x80000000; } else { while ((1U << i) < nSize) { i++; } ht->nTableSize = 1 << i; } ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */ ht->pDestructor = pDestructor; ht->arBuckets = (Bucket**)&uninitialized_bucket; ht->pListHead = NULL; ht->pListTail = NULL; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; ht->pInternalPointer = NULL; ht->persistent = persistent; ht->nApplyCount = 0; ht->bApplyProtection = 1; return SUCCESS; }
ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht) { IS_CONSISTENT(ht); while (ht->pListTail != NULL) { zend_hash_bucket_delete(ht, ht->pListTail); } if (ht->nTableMask) { pefree(ht->arBuckets, ht->persistent); } SET_INCONSISTENT(HT_DESTROYED); }
ZEND_API void zend_hash_graceful_destroy(HashTable *ht) { Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { p = zend_hash_apply_deleter(ht, p); } pefree(ht->arBuckets, ht->persistent); SET_INCONSISTENT(HT_DESTROYED); }
// hash_func_t参数不再使用,保留仅是接口兼容. // typedef void (*dtor_func_t)(void *pDest); ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { uint i = 3; Bucket **tmp; SET_INCONSISTENT(HT_OK); if (nSize >= 0x80000000) { /* prevent overflow */ ht->nTableSize = 0x80000000; } else { // round操作 // i有最小值的 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; /* Uses ecalloc() so that Bucket* == NULL */ if (persistent) { tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *)); if (!tmp) { return FAILURE; } ht->arBuckets = tmp; } else { tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *)); if (tmp) { ht->arBuckets = tmp; } } return SUCCESS; }
ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht) { Bucket *p; IS_CONSISTENT(ht); p = ht->pListTail; while (p != NULL) { zend_hash_apply_deleter(ht, p); p = ht->pListTail; } if (ht->nTableMask) { pefree(ht->arBuckets, ht->persistent); } SET_INCONSISTENT(HT_DESTROYED); }