(p)->pDataPtr=NULL; \
}
-
+#define CHECK_INIT(ht) do { \
+ if (UNEXPECTED((ht)->nTableMask == 0)) { \
+ (ht)->nTableMask = (ht)->nTableSize - 1; \
+ (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize, sizeof(Bucket *), (ht)->persistent); \
+ } \
+} while (0)
+
+static const Bucket *uninitialized_bucket = NULL;
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);
ht->nTableSize = 1 << i;
}
- ht->nTableMask = ht->nTableSize - 1;
+ ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */
ht->pDestructor = pDestructor;
- ht->arBuckets = NULL;
+ ht->arBuckets = (Bucket**)&uninitialized_bucket;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
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;
}
return FAILURE;
}
+ CHECK_INIT(ht);
+
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
}
+ CHECK_INIT(ht);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
Bucket *p;
IS_CONSISTENT(ht);
+ CHECK_INIT(ht);
if (flag & HASH_NEXT_INSERT) {
h = ht->nNextFreeElement;
uint nIndex;
IS_CONSISTENT(ht);
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ return SUCCESS;
+ }
memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
p = ht->pListHead;
}
pefree(q, ht->persistent);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
}
pefree(q, ht->persistent);
}
- memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ if (ht->nTableMask) {
+ memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ }
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
while (p != NULL) {
p = zend_hash_apply_deleter(ht, p);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
p = ht->pListTail;
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
p = pos ? (*pos) : ht->pInternalPointer;
IS_CONSISTENT(ht);
+ CHECK_INIT(ht);
if (p) {
if (key_type == HASH_KEY_IS_LONG) {
Bucket *p;
uint i;
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ zend_output_debug_string(0, "The hash is empty");
+ return;
+ }
for (i = 0; i < ht->nTableSize; i++) {
p = ht->arBuckets[i];
while (p != NULL) {