mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Improve infrastructure of numeric handling of elements in symbol tables.
When you want to work with a symbol table, and you don't know whether you have a numeric ("string that looks like a number") or a string element in your hands, use zend_symtable_*() functions, in place of zend_hash_*() functions.
This commit is contained in:
parent
5fcff2d872
commit
cf90932a05
5 changed files with 112 additions and 83 deletions
|
@ -666,7 +666,6 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, znode *op
|
|||
zval **retval;
|
||||
char *offset_key;
|
||||
int offset_key_length;
|
||||
long index;
|
||||
|
||||
switch (dim->type) {
|
||||
case IS_NULL:
|
||||
|
@ -674,15 +673,12 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, znode *op
|
|||
offset_key_length = 0;
|
||||
goto fetch_string_dim;
|
||||
case IS_STRING:
|
||||
if (zend_is_numeric_key(dim, &index)) {
|
||||
goto fetch_int_dim;
|
||||
}
|
||||
|
||||
offset_key = dim->value.str.val;
|
||||
offset_key_length = dim->value.str.len;
|
||||
|
||||
fetch_string_dim:
|
||||
if (zend_hash_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
|
||||
if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
zend_error(E_NOTICE,"Undefined index: %s", offset_key);
|
||||
|
@ -706,31 +702,33 @@ fetch_string_dim:
|
|||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (dim->type == IS_DOUBLE) {
|
||||
index = (long)dim->value.dval;
|
||||
} else {
|
||||
index = dim->value.lval;
|
||||
}
|
||||
fetch_int_dim:
|
||||
if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
zend_error(E_NOTICE,"Undefined offset: %d", index);
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_IS:
|
||||
retval = &EG(uninitialized_zval_ptr);
|
||||
break;
|
||||
case BP_VAR_RW:
|
||||
zend_error(E_NOTICE,"Undefined offset: %d", index);
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_W: {
|
||||
zval *new_zval = &EG(uninitialized_zval);
|
||||
case IS_LONG: {
|
||||
long index;
|
||||
|
||||
new_zval->refcount++;
|
||||
zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
|
||||
if (dim->type == IS_DOUBLE) {
|
||||
index = (long)dim->value.dval;
|
||||
} else {
|
||||
index = dim->value.lval;
|
||||
}
|
||||
if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
|
||||
switch (type) {
|
||||
case BP_VAR_R:
|
||||
zend_error(E_NOTICE,"Undefined offset: %d", index);
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_IS:
|
||||
retval = &EG(uninitialized_zval_ptr);
|
||||
break;
|
||||
case BP_VAR_RW:
|
||||
zend_error(E_NOTICE,"Undefined offset: %d", index);
|
||||
/* break missing intentionally */
|
||||
case BP_VAR_W: {
|
||||
zval *new_zval = &EG(uninitialized_zval);
|
||||
|
||||
new_zval->refcount++;
|
||||
zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -3309,16 +3307,9 @@ inline int zend_init_add_array_helper(ZEND_OPCODE_HANDLER_ARGS)
|
|||
case IS_BOOL:
|
||||
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
|
||||
break;
|
||||
case IS_STRING: {
|
||||
long idx;
|
||||
|
||||
if (zend_is_numeric_key(offset, &idx)) {
|
||||
zend_hash_index_update(array_ptr->value.ht, idx, &expr_ptr, sizeof(zval *), NULL);
|
||||
} else {
|
||||
zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
|
||||
}
|
||||
case IS_STRING:
|
||||
zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
|
||||
break;
|
||||
}
|
||||
case IS_NULL:
|
||||
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
|
||||
break;
|
||||
|
@ -3559,11 +3550,7 @@ int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS)
|
|||
zend_hash_index_del(ht, index);
|
||||
break;
|
||||
case IS_STRING:
|
||||
if (zend_is_numeric_key(offset, &index)) {
|
||||
zend_hash_index_del(ht, index);
|
||||
} else {
|
||||
zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1);
|
||||
}
|
||||
zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1);
|
||||
break;
|
||||
case IS_NULL:
|
||||
zend_hash_del(ht, "", sizeof(""));
|
||||
|
@ -3778,11 +3765,7 @@ int zend_isset_isempty_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS)
|
|||
}
|
||||
break;
|
||||
case IS_STRING:
|
||||
if (zend_is_numeric_key(offset, &index)) {
|
||||
if (zend_hash_index_find(ht, index, (void **) &value) == SUCCESS) {
|
||||
isset = 1;
|
||||
}
|
||||
} else if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
|
||||
if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
|
||||
isset = 1;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -130,6 +130,38 @@ ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength)
|
|||
}
|
||||
|
||||
|
||||
ZEND_API zend_bool zend_is_numeric_key(char *arKey, uint nKeyLength, long *val)
|
||||
{
|
||||
char *tmp = arKey;
|
||||
|
||||
if ((*tmp>='0' && *tmp<='9')) { /* possibly a numeric index */
|
||||
char *end=tmp+nKeyLength-1;
|
||||
ulong idx;
|
||||
|
||||
if (*tmp++=='0' && nKeyLength>2) { /* don't accept numbers with leading zeros */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (tmp<end) {
|
||||
if (!(*tmp>='0' && *tmp<='9')) {
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if (tmp==end && *tmp=='\0') { /* a numeric index */
|
||||
idx = strtol(arKey, NULL, 10);
|
||||
if (idx!=LONG_MAX) {
|
||||
*val = idx;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
|
|
@ -89,6 +89,8 @@ typedef Bucket* HashPosition;
|
|||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
ZEND_API zend_bool zend_is_numeric_key(char *arKey, uint nKeyLength, long *val);
|
||||
|
||||
/* startup/shutdown */
|
||||
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);
|
||||
ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
|
||||
|
@ -163,6 +165,7 @@ ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength,
|
|||
ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h);
|
||||
ZEND_API ulong zend_hash_next_free_element(HashTable *ht);
|
||||
|
||||
|
||||
/* traversing */
|
||||
#define zend_hash_has_more_elements_ex(ht, pos) \
|
||||
(zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTANT ? FAILURE : SUCCESS)
|
||||
|
@ -283,6 +286,53 @@ END_EXTERN_C()
|
|||
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
|
||||
|
||||
|
||||
static inline int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (zend_is_numeric_key(arKey, nKeyLength, &idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData, nDataSize, pDest);
|
||||
} else {
|
||||
return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (zend_is_numeric_key(arKey, nKeyLength, &idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_del(ht, arKey, nKeyLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (zend_is_numeric_key(arKey, nKeyLength, &idx)) {
|
||||
return zend_hash_index_find(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_find(ht, arKey, nKeyLength, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (zend_is_numeric_key(arKey, nKeyLength, &idx)) {
|
||||
return zend_hash_index_exists(ht, idx);
|
||||
} else {
|
||||
return zend_hash_exists(ht, arKey, nKeyLength);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ZEND_HASH_H */
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,41 +33,6 @@
|
|||
#include "ext/bcmath/number.h"
|
||||
#endif
|
||||
|
||||
ZEND_API zend_bool zend_is_numeric_key(zval *zvalue, long *val)
|
||||
{
|
||||
char *tmp;
|
||||
long length;
|
||||
|
||||
tmp = zvalue->value.str.val;
|
||||
length = zvalue->value.str.len;
|
||||
|
||||
if ((*tmp>='0' && *tmp<='9')) { /* possibly a numeric index */
|
||||
char *end=tmp+length;
|
||||
ulong idx;
|
||||
|
||||
if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (tmp<end) {
|
||||
if (!(*tmp>='0' && *tmp<='9')) {
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if (tmp==end && *tmp=='\0') { /* a numeric index */
|
||||
idx = strtol(zvalue->value.str.val, NULL, 10);
|
||||
if (idx!=LONG_MAX) {
|
||||
*val = idx;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZEND_API int zend_atoi(const char *str, int str_len)
|
||||
{
|
||||
int retval;
|
||||
|
|
|
@ -60,7 +60,6 @@ ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
|||
ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, zend_class_entry *ce TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_is_numeric_key(zval *, long *);
|
||||
|
||||
static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue