static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
{
+ HANDLE_BLOCK_INTERRUPTIONS();
if (!(ht->u.flags & HASH_FLAG_PACKED)) {
if (prev) {
Z_NEXT(prev->val) = Z_NEXT(p->val);
} else {
ZVAL_UNDEF(&p->val);
}
+ HANDLE_UNBLOCK_INTERRUPTIONS();
}
static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
p->key &&
p->key->len == key->len &&
memcmp(p->key->val, key->val, key->len) == 0)) {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, idx, p, prev);
- HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
}
prev = p;
ZVAL_UNDEF(data);
}
} else {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, idx, p, prev);
- HANDLE_UNBLOCK_INTERRUPTIONS();
}
return SUCCESS;
}
ZVAL_UNDEF(data);
}
} else {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, idx, p, prev);
- HANDLE_UNBLOCK_INTERRUPTIONS();
}
return SUCCESS;
}
&& p->key
&& (p->key->len == len)
&& !memcmp(p->key->val, str, len)) {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, idx, p, prev);
- HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
}
prev = p;
if (h < ht->nNumUsed) {
p = ht->arData + h;
if (Z_TYPE(p->val) != IS_UNDEF) {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, h, p, NULL);
- HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
}
}
while (idx != INVALID_IDX) {
p = ht->arData + idx;
if ((p->h == h) && (p->key == NULL)) {
- HANDLE_BLOCK_INTERRUPTIONS();
_zend_hash_del_el_ex(ht, idx, p, prev);
- HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
}
prev = p;
}
}
-/* 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
- * returned value will still be valid.
- */
-static void zend_hash_apply_deleter(HashTable *ht, uint32_t idx, Bucket *p)
-{
-
- HANDLE_BLOCK_INTERRUPTIONS();
- _zend_hash_del_el(ht, idx, p);
- HANDLE_UNBLOCK_INTERRUPTIONS();
-}
-
-
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
{
uint32_t idx;
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (ht->nTableMask) {
pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
idx--;
p = ht->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (ht->nTableMask) {
result = apply_func(&p->val);
if (result & ZEND_HASH_APPLY_REMOVE) {
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (result & ZEND_HASH_APPLY_STOP) {
break;
result = apply_func(&p->val, argument);
if (result & ZEND_HASH_APPLY_REMOVE) {
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (result & ZEND_HASH_APPLY_STOP) {
break;
result = apply_func(&p->val, num_args, args, &hash_key);
if (result & ZEND_HASH_APPLY_REMOVE) {
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (result & ZEND_HASH_APPLY_STOP) {
va_end(args);
result = apply_func(&p->val);
if (result & ZEND_HASH_APPLY_REMOVE) {
- zend_hash_apply_deleter(ht, idx, p);
+ _zend_hash_del_el(ht, idx, p);
}
if (result & ZEND_HASH_APPLY_STOP) {
break;
ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
{
register const char *tmp = key;
- const char *end;
- if (*tmp > '9') {
- return 0;
- } else if (*tmp < '0') {
- if (*tmp != '-') {
- return 0;
- }
+ const char *end = key + length;
+ ZEND_ASSERT(*end == '\0');
+
+ if (*tmp == '-') {
tmp++;
- if (*tmp > '9' || *tmp < '0') {
- return 0;
- }
}
- /* possibly a numeric index */
- end = key + length;
-
- if ((*end != '\0') /* not a null terminated string */
- || (*tmp == '0' && length > 1) /* numbers with leading zeros */
+ if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
|| (SIZEOF_ZEND_LONG == 4 &&
end - tmp == MAX_LENGTH_OF_LONG - 1 &&