mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Add zend_hash_lookup() and zend_hash_index_lookup() functions.
Thet search for an element with given key/index and add an empty one (NULL), if no found.
This commit is contained in:
parent
64e589cab6
commit
340013ad01
3 changed files with 96 additions and 44 deletions
|
@ -2121,6 +2121,7 @@ try_again:
|
|||
if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(dim);
|
||||
num_index:
|
||||
if (type != BP_VAR_W) {
|
||||
ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
|
||||
return retval;
|
||||
num_undef:
|
||||
|
@ -2136,11 +2137,12 @@ num_undef:
|
|||
if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
|
||||
return NULL;
|
||||
}
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_W:
|
||||
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ZEND_HASH_INDEX_LOOKUP(ht, hval, retval);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
|
||||
offset_key = Z_STR_P(dim);
|
||||
if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
|
||||
|
@ -2149,6 +2151,7 @@ num_undef:
|
|||
}
|
||||
}
|
||||
str_index:
|
||||
if (type != BP_VAR_W) {
|
||||
retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
|
||||
if (!retval) {
|
||||
switch (type) {
|
||||
|
@ -2169,11 +2172,11 @@ str_index:
|
|||
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
|
||||
zend_string_release(offset_key);
|
||||
break;
|
||||
case BP_VAR_W:
|
||||
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retval = zend_hash_lookup(ht, offset_key);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(dim) == IS_REFERENCE)) {
|
||||
dim = Z_REFVAL_P(dim);
|
||||
goto try_again;
|
||||
|
|
|
@ -748,7 +748,9 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
|
|||
zval *data;
|
||||
|
||||
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
|
||||
if (flag & HASH_ADD) {
|
||||
if (flag & HASH_LOOKUP) {
|
||||
return &p->val;
|
||||
} else if (flag & HASH_ADD) {
|
||||
if (!(flag & HASH_UPDATE_INDIRECT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -793,7 +795,11 @@ add_to_hash:
|
|||
nIndex = h | ht->nTableMask;
|
||||
Z_NEXT(p->val) = HT_HASH_EX(arData, nIndex);
|
||||
HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx);
|
||||
if (flag & HASH_LOOKUP) {
|
||||
ZVAL_NULL(&p->val);
|
||||
} else {
|
||||
ZVAL_COPY_VALUE(&p->val, pData);
|
||||
}
|
||||
|
||||
return &p->val;
|
||||
}
|
||||
|
@ -821,7 +827,9 @@ static zend_always_inline zval *_zend_hash_str_add_or_update_i(HashTable *ht, co
|
|||
if (p) {
|
||||
zval *data;
|
||||
|
||||
if (flag & HASH_ADD) {
|
||||
if (flag & HASH_LOOKUP) {
|
||||
return &p->val;
|
||||
} else if (flag & HASH_ADD) {
|
||||
if (!(flag & HASH_UPDATE_INDIRECT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -859,7 +867,11 @@ add_to_hash:
|
|||
p->key = key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
|
||||
p->h = ZSTR_H(key) = h;
|
||||
HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
|
||||
if (flag & HASH_LOOKUP) {
|
||||
ZVAL_NULL(&p->val);
|
||||
} else {
|
||||
ZVAL_COPY_VALUE(&p->val, pData);
|
||||
}
|
||||
nIndex = h | ht->nTableMask;
|
||||
Z_NEXT(p->val) = HT_HASH(ht, nIndex);
|
||||
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
|
||||
|
@ -901,6 +913,11 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key,
|
|||
return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW);
|
||||
}
|
||||
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
|
||||
{
|
||||
return _zend_hash_add_or_update_i(ht, key, NULL, HASH_LOOKUP);
|
||||
}
|
||||
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag)
|
||||
{
|
||||
if (flag == HASH_ADD) {
|
||||
|
@ -984,6 +1001,9 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
|
|||
if (h < ht->nNumUsed) {
|
||||
p = ht->arData + h;
|
||||
if (Z_TYPE(p->val) != IS_UNDEF) {
|
||||
if (flag & HASH_LOOKUP) {
|
||||
return &p->val;
|
||||
}
|
||||
replace:
|
||||
if (flag & HASH_ADD) {
|
||||
return NULL;
|
||||
|
@ -1032,6 +1052,9 @@ convert_to_hash:
|
|||
if ((flag & HASH_ADD_NEW) == 0 || ZEND_DEBUG) {
|
||||
p = zend_hash_index_find_bucket(ht, h);
|
||||
if (p) {
|
||||
if (flag & HASH_LOOKUP) {
|
||||
return &p->val;
|
||||
}
|
||||
ZEND_ASSERT((flag & HASH_ADD_NEW) == 0);
|
||||
goto replace;
|
||||
}
|
||||
|
@ -1051,7 +1074,11 @@ add:
|
|||
ht->nNumOfElements++;
|
||||
p->h = h;
|
||||
p->key = NULL;
|
||||
if (flag & HASH_LOOKUP) {
|
||||
ZVAL_NULL(&p->val);
|
||||
} else {
|
||||
ZVAL_COPY_VALUE(&p->val, pData);
|
||||
}
|
||||
|
||||
return &p->val;
|
||||
}
|
||||
|
@ -1099,6 +1126,11 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval
|
|||
return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT);
|
||||
}
|
||||
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h)
|
||||
{
|
||||
return _zend_hash_index_add_or_update_i(ht, h, NULL, HASH_LOOKUP);
|
||||
}
|
||||
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, zend_string *key)
|
||||
{
|
||||
uint32_t nIndex;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define HASH_UPDATE_INDIRECT (1<<2)
|
||||
#define HASH_ADD_NEW (1<<3)
|
||||
#define HASH_ADD_NEXT (1<<4)
|
||||
#define HASH_LOOKUP (1<<5)
|
||||
|
||||
#define HASH_FLAG_CONSISTENCY ((1<<0) | (1<<1))
|
||||
#define HASH_FLAG_PACKED (1<<2)
|
||||
|
@ -206,6 +207,22 @@ static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_stri
|
|||
} while (0)
|
||||
|
||||
|
||||
/* Find or add NULL, if doesn't exist */
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key);
|
||||
ZEND_API zval* ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h);
|
||||
|
||||
#define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret) do { \
|
||||
if (EXPECTED(HT_FLAGS(_ht) & HASH_FLAG_PACKED)) { \
|
||||
if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed)) { \
|
||||
_ret = &_ht->arData[_h].val; \
|
||||
if (EXPECTED(Z_TYPE_P(_ret) != IS_UNDEF)) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
_ret = zend_hash_index_lookup(_ht, _h); \
|
||||
} while (0)
|
||||
|
||||
/* Misc */
|
||||
static zend_always_inline bool zend_hash_exists(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue