Skip to content

Commit

Permalink
get/set/unset functions using zend_literal
Browse files Browse the repository at this point in the history
  • Loading branch information
sjinks committed Jan 30, 2014
1 parent 925e157 commit f2130da
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 14 deletions.
184 changes: 173 additions & 11 deletions ext/kernel/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,32 +181,32 @@ int phalcon_has_numeric_keys(const zval *data)
* @param ht Hash table
* @param[in] key Key
* @param[in] value Value
* @return Whether the operation succeeded
* @retval SUCCESS
* @retval FAILURE
* @note @a value's reference count in not updated
* @note If @a key is @c NULL or is @c IS_NULL, @a value is appended to @a ht
* @throw E_WARNING if @a key type is not supported
*/
void phalcon_hash_update_or_insert(HashTable *ht, zval *key, zval *value)
int phalcon_hash_update_or_insert(HashTable *ht, const zval *key, zval *value)
{
if (!key || Z_TYPE_P(key) == IS_NULL) {
zend_hash_next_index_insert(ht, (void**)&value, sizeof(zval*), NULL);
return;
return zend_hash_next_index_insert(ht, (void**)&value, sizeof(zval*), NULL);
}

switch (Z_TYPE_P(key)) {
case IS_STRING:
zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key)+1, (void**)&value, sizeof(zval*), NULL);
return;
return zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key)+1, (void**)&value, sizeof(zval*), NULL);

case IS_RESOURCE:
case IS_DOUBLE:
case IS_BOOL:
case IS_LONG:
zend_hash_index_update(ht, ((Z_TYPE_P(key) == IS_DOUBLE) ? (ulong)Z_DVAL_P(key) : (ulong)Z_LVAL_P(key)), (void*)&value, sizeof(zval*), NULL);
return;
return zend_hash_index_update(ht, ((Z_TYPE_P(key) == IS_DOUBLE) ? (ulong)Z_DVAL_P(key) : (ulong)Z_LVAL_P(key)), (void*)&value, sizeof(zval*), NULL);

default:
zend_error(E_WARNING, "Illegal offset type");
return;
return FAILURE;
}
}

Expand All @@ -219,14 +219,14 @@ void phalcon_hash_update_or_insert(HashTable *ht, zval *key, zval *value)
* @retval <tt>&EG(error_zval_ptr)</tt> when @a key was not found and @a type is one of @c BP_VAR_W, @c BP_VAR_RW
* @retval <tt>&EG(uninitialized_zval_ptr)</tt> when @a key was not found and @a type is one of @c BP_VAR_R, @c BP_VAR_UNSET, @c BP_VAR_IS
* @retval @c NULL when @a key was not found and @a type is not any of the above
* @throw @c E_WARNING when @a key is of not supported typel in this case the function never returns @c NULL
* @throw @c E_WARNING when @a key is of not supported type; in this case the function never returns @c NULL
* @throw @c E_STRICT when @a key is a resource
* @throw @c E_NOTICE if @a key was not found and @a type is @c BP_VAR_R or @c BP_VAR_RW
* @note Reference count of the returned item is not modified
* @note The implementation is suitable for @c read_property, @c get_property_ptr_ptr and @c read_dimension object handlers
* @warning If @a type is @c BP_VAR_W or @c BP_VAR_RW and @a key was not found, it is added to @a ht and its value is set to @c IS_NULL
*/
zval** phalcon_hash_get(HashTable *ht, zval *key, int type)
zval** phalcon_hash_get(HashTable *ht, const zval *key, int type)
{
zval **ret = NULL;

Expand Down Expand Up @@ -306,7 +306,7 @@ zval** phalcon_hash_get(HashTable *ht, zval *key, int type)
* @param key
* @return
*/
int phalcon_hash_unset(HashTable *ht, zval *key)
int phalcon_hash_unset(HashTable *ht, const zval *key)
{
switch (Z_TYPE_P(key)) {
case IS_LONG:
Expand All @@ -323,3 +323,165 @@ int phalcon_hash_unset(HashTable *ht, zval *key)
return 0;
}
}

#if PHP_VERSION_ID >= 50400
/**
* @brief Returns the entry @a ht identified by @a key (<tt>key->constant</tt>)
* @param[in] ht Hash table
* @param[in] type One of @c BP_VAR_XXX values
* @param[in] key Zend literal key
* @return Pointer to the stored value or a pointer to the special variable / @c NULL if the key was not found
* @retval <tt>&EG(error_zval_ptr)</tt> when the key was not found and @a type is one of @c BP_VAR_W, @c BP_VAR_RW
* @retval <tt>&EG(uninitialized_zval_ptr)</tt> when the key was not found and @a type is one of @c BP_VAR_R, @c BP_VAR_UNSET, @c BP_VAR_IS
* @retval @c NULL when the key was not found and @a type is not any of the above
* @throw @c E_WARNING when the key is of not supported type; in this case the function never returns @c NULL
* @throw @c E_NOTICE if @a key was not found and @a type is @c BP_VAR_R or @c BP_VAR_RW
* @note Reference count of the returned item is not modified
* @note The implementation is suitable for @c read_property, @c get_property_ptr_ptr and @c read_dimension object handlers
* @warning If @a type is @c BP_VAR_W or @c BP_VAR_RW and the key was not found, it is added to @a ht and its value is set to @c IS_NULL
*/
zval** phalcon_hash_fast_get(HashTable *ht, int type, const zend_literal* key)
{
zval **ret = NULL;

switch (Z_TYPE(key->constant)) {
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL(key->constant), Z_LVAL(key->constant));
/* no break */
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL: {
ulong index = (Z_TYPE(key->constant) == IS_DOUBLE) ? ((long int)Z_DVAL(key->constant)) : Z_LVAL(key->constant);
if (FAILURE == zend_hash_index_find(ht, index, (void**)&ret)) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE, "Undefined offset: %ld", index);
/* no break */
case BP_VAR_UNSET:
case BP_VAR_IS: {
TSRMLS_FETCH();
ret = &EG(uninitialized_zval_ptr);
break;
}

case BP_VAR_RW:
zend_error(E_NOTICE, "Undefined offset: %ld", index);
/* no break */
case BP_VAR_W: {
zval *value;
ALLOC_INIT_ZVAL(value);
zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), (void**)&ret);
break;
}
}
}

return ret;
}

case IS_STRING:
if (*(Z_STRVAL(key->constant)) >= '0' && *(Z_STRVAL(key->constant)) <= '9') {
return phalcon_hash_get(ht, &key->constant, type);
}

if (FAILURE == zend_hash_quick_find(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1, key->hash_value, (void**)&ret)) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE, "Undefined offset: %s", Z_STRVAL(key->constant));
/* no break */
case BP_VAR_UNSET:
case BP_VAR_IS: {
TSRMLS_FETCH();
ret = &EG(uninitialized_zval_ptr);
break;
}

case BP_VAR_RW:
zend_error(E_NOTICE, "Undefined offset: %s", Z_STRVAL(key->constant));
/* no break */
case BP_VAR_W: {
zval *value;
ALLOC_INIT_ZVAL(value);
zend_hash_quick_update(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1, key->hash_value, (void**)&value, sizeof(void*), (void**)&ret);
break;
}
}
}

return ret;

default: {
TSRMLS_FETCH();
zend_error(E_WARNING, "Illegal offset type");
return (type == BP_VAR_W || type == BP_VAR_RW) ? &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
}
}
}

/**
* @brief Adds or updates item @a key in the hash table @a ht
* @param ht Hash table
* @param[in] key Literal key
* @param[in] value Value
* @return Whether the operation succeeded
* @retval SUCCESS
* @retval FAILURE
* @note @a value's reference count in not updated
* @note If <tt>key->constant</tt> is @c IS_NULL, @a value is appended to @a ht
* @throw E_WARNING if @a key type is not supported
*/
int phalcon_hash_quick_update_or_insert(HashTable *ht, zval *value, const zend_literal *key)
{
if (Z_TYPE(key->constant) == IS_NULL) {
return zend_hash_next_index_insert(ht, (void**)&value, sizeof(zval*), NULL);
}

switch (Z_TYPE(key->constant)) {
case IS_STRING:
if (*(Z_STRVAL(key->constant)) >= '0' && *(Z_STRVAL(key->constant)) <= '9') {
return zend_symtable_update(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1, (void**)&value, sizeof(zval*), NULL);
}

return zend_hash_quick_update(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1, key->hash_value, (void**)&value, sizeof(zval*), NULL);

case IS_RESOURCE:
case IS_DOUBLE:
case IS_BOOL:
case IS_LONG:
return zend_hash_index_update(ht, ((Z_TYPE(key->constant) == IS_DOUBLE) ? (ulong)Z_DVAL(key->constant) : (ulong)Z_LVAL(key->constant)), (void*)&value, sizeof(zval*), NULL);

default:
zend_error(E_WARNING, "Illegal offset type");
return FAILURE;
}
}

/**
* @brief Unset key identified by @a key from @a ht
* @param ht
* @param key
* @return
*/
int phalcon_hash_fast_unset(HashTable *ht, const zend_literal *key)
{
switch (Z_TYPE(key->constant)) {
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
case IS_RESOURCE:
return (zend_hash_index_del(ht, (Z_TYPE(key->constant) == IS_DOUBLE) ? ((ulong)Z_DVAL(key->constant)) : (ulong)Z_LVAL(key->constant)) == SUCCESS);

case IS_STRING:
if (*(Z_STRVAL(key->constant)) >= '0' && *(Z_STRVAL(key->constant)) <= '9') {
return (zend_symtable_del(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1) == SUCCESS);
}

return (zend_hash_quick_del(ht, Z_STRVAL(key->constant), Z_STRLEN(key->constant)+1, key->hash_value) == SUCCESS);

default:
zend_error(E_WARNING, "Illegal offset type");
return 0;
}
}

#endif
14 changes: 11 additions & 3 deletions ext/kernel/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef PHALCON_KERNEL_HASH_H
#define PHALCON_KERNEL_HASH_H

#include <main/php_config.h>
#include <Zend/zend.h>

int phalcon_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength);
Expand All @@ -29,8 +30,15 @@ int phalcon_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLen
void phalcon_get_current_key(zval **key, const HashTable *hash_table, HashPosition *hash_position TSRMLS_DC);
zval phalcon_get_current_key_w(const HashTable *hash_table, HashPosition *hash_position);
int phalcon_has_numeric_keys(const zval *data);
void phalcon_hash_update_or_insert(HashTable *ht, zval *offset, zval *value);
zval** phalcon_hash_get(HashTable *ht, zval *key, int type);
int phalcon_hash_unset(HashTable *ht, zval *offset);
int phalcon_hash_update_or_insert(HashTable *ht, const zval *offset, zval *value);

#if PHP_VERSION_ID >= 50400
zval** phalcon_hash_fast_get(HashTable *ht, int type, const zend_literal *key) PHALCON_ATTR_NONNULL;
int phalcon_hash_quick_update_or_insert(HashTable *ht, zval *value, const zend_literal *key) PHALCON_ATTR_NONNULL;
int phalcon_hash_fast_unset(HashTable *ht, const zend_literal *key) PHALCON_ATTR_NONNULL;
#endif

zval** phalcon_hash_get(HashTable *ht, const zval *key, int type);
int phalcon_hash_unset(HashTable *ht, const zval *offset);

#endif /* PHALCON_KERNEL_HASH_H */

0 comments on commit f2130da

Please sign in to comment.