Skip to content

Commit

Permalink
Introduced phalcon_array_isset_fetch functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sjinks committed Aug 2, 2013
1 parent a9c59c4 commit 460be93
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 74 deletions.
110 changes: 93 additions & 17 deletions ext/kernel/array.c
Expand Up @@ -34,28 +34,112 @@
#include "kernel/backtrace.h"

/**
* @brief Checks whether @a index exists in array @a arr
* @brief Fetches @a index if it exists from the array @a arr
* @param[out] fetched <code>&$arr[$index]</code>; @a fetched is modified only when the function returns 1
* @param arr Array
* @param index Index
* @return isset($arr[$index])
* @retval 0 Not exists, @a arr is not an array or @a index is of not supported type
* @retval 1 Exists
* @note @c index will be handled as follows: @c NULL is treated as an empty string, @c double values are cast to @c integer, @c bool or @c resource are treated as @c integer
* @note $arr[$index] is returned as is: no copying occurs, reference copunt is not updated
* @throw E_WARNING if @a offset is not a scalar
*/
int PHALCON_FASTCALL phalcon_array_isset(const zval *arr, zval *index) {
int phalcon_array_isset_fetch(zval ***fetched, const zval *arr, zval *index) {

HashTable *h;
zval **val;
int result;

if (Z_TYPE_P(arr) != IS_ARRAY) {
return 0;
}

h = Z_ARRVAL_P(arr);
if (!zend_hash_num_elements(h)) {
switch (Z_TYPE_P(index)) {
case IS_NULL:
result = phalcon_hash_find(h, ZEND_STRS(""), (void**)&val);
break;

case IS_DOUBLE:
result = zend_hash_index_find(h, (ulong)Z_DVAL_P(index), (void**)&val);
break;

case IS_LONG:
case IS_BOOL:
case IS_RESOURCE:
result = zend_hash_index_find(h, Z_LVAL_P(index), (void**)&val);
break;

case IS_STRING:
result = zend_symtable_find(h, (Z_STRLEN_P(index) ? Z_STRVAL_P(index) : ""), Z_STRLEN_P(index)+1, (void**)&val);
break;

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

if (result == SUCCESS) {
*fetched = val;
return 1;
}

return 0;
}

int phalcon_array_isset_quick_string_fetch(zval ***fetched, zval *arr, char *index, uint index_length, unsigned long key, int silent){

zval **zv;

if (likely(Z_TYPE_P(arr) == IS_ARRAY)) {
if (phalcon_hash_quick_find(Z_ARRVAL_P(arr), index, index_length, key, (void**) &zv) == SUCCESS) {
*fetched = zv;
return 1;
}
}

return 0;
}

int phalcon_array_isset_string_fetch(zval ***fetched, zval *arr, char *index, uint index_length, int silent){

return phalcon_array_isset_quick_string_fetch(fetched, arr, index, index_length + 1, zend_inline_hash_func(index, index_length + 1), silent);
}

int phalcon_array_isset_long_fetch(zval ***fetched, zval *arr, unsigned long index, int silent){

zval **zv;

if (likely(Z_TYPE_P(arr) == IS_ARRAY)) {
if (zend_hash_index_find(Z_ARRVAL_P(arr), index, (void**)&zv) == SUCCESS) {
*fetched = zv;
return 1;
}
}

return 0;
}

/**
* @brief Checks whether @a index exists in array @a arr
* @param arr Array
* @param index Index
* @return isset($arr[$index])
* @retval 0 Not exists, @a arr is not an array or @a index is of not supported type
* @retval 1 Exists
* @note @c index will be handled as follows: @c NULL is treated as an empty string, @c double values are cast to @c integer, @c bool or @c resource are treated as @c integer
* @throw E_WARNING if @a offset is not a scalar
*/
int PHALCON_FASTCALL phalcon_array_isset(const zval *arr, zval *index) {

HashTable *h;

if (Z_TYPE_P(arr) != IS_ARRAY) {
return 0;
}

h = Z_ARRVAL_P(arr);
switch (Z_TYPE_P(index)) {
case IS_NULL:
return phalcon_hash_exists(h, ZEND_STRS(""));
Expand Down Expand Up @@ -105,15 +189,11 @@ int PHALCON_FASTCALL phalcon_array_isset_string(const zval *arr, char *index, ui
*/
int PHALCON_FASTCALL phalcon_array_isset_quick_string(const zval *arr, char *index, uint index_length, unsigned long key) {

if (Z_TYPE_P(arr) != IS_ARRAY) {
return 0;
}

if (!zend_hash_num_elements(Z_ARRVAL_P(arr))) {
return 0;
if (likely(Z_TYPE_P(arr) == IS_ARRAY)) {
return zend_hash_quick_exists(Z_ARRVAL_P(arr), index, index_length, key);
}

return zend_hash_quick_exists(Z_ARRVAL_P(arr), index, index_length, key);
return 0;
}

/**
Expand All @@ -126,15 +206,11 @@ int PHALCON_FASTCALL phalcon_array_isset_quick_string(const zval *arr, char *ind
*/
int PHALCON_FASTCALL phalcon_array_isset_long(const zval *arr, unsigned long index) {

if (Z_TYPE_P(arr) != IS_ARRAY) {
return 0;
}

if (!zend_hash_num_elements(Z_ARRVAL_P(arr))) {
return 0;
if (likely(Z_TYPE_P(arr) == IS_ARRAY)) {
return zend_hash_index_exists(Z_ARRVAL_P(arr), index);
}

return zend_hash_index_exists(Z_ARRVAL_P(arr), index);
return 0;
}

/**
Expand Down
104 changes: 59 additions & 45 deletions ext/kernel/array.h
Expand Up @@ -17,76 +17,90 @@
+------------------------------------------------------------------------+
*/

#ifndef PHALCON_KERNEL_ARRAY_H
#define PHALCON_KERNEL_ARRAY_H

#include "Zend/zend.h"
#include "php_phalcon.h"

/** Combined isset/fetch */
int phalcon_array_isset_fetch(zval ***fetched, const zval *arr, zval *index);
int phalcon_array_isset_quick_string_fetch(zval ***fetched, zval *arr, char *index, uint index_length, unsigned long key, int silent);
int phalcon_array_isset_string_fetch(zval ***fetched, zval *arr, char *index, uint index_length, int silent);
int phalcon_array_isset_long_fetch(zval ***fetched, zval *arr, unsigned long index, int silent);

/** Check for index existence */
extern int PHALCON_FASTCALL phalcon_array_isset(const zval *arr, zval *index);
extern int PHALCON_FASTCALL phalcon_array_isset_long(const zval *arr, unsigned long index);
extern int PHALCON_FASTCALL phalcon_array_isset_string(const zval *arr, char *index, uint index_length);
int PHALCON_FASTCALL phalcon_array_isset(const zval *arr, zval *index);
int PHALCON_FASTCALL phalcon_array_isset_long(const zval *arr, unsigned long index);
int PHALCON_FASTCALL phalcon_array_isset_string(const zval *arr, char *index, uint index_length);

/** Fast index existence checking */
extern int PHALCON_FASTCALL phalcon_array_isset_quick_string(const zval *arr, char *index, uint index_length, unsigned long key);
int PHALCON_FASTCALL phalcon_array_isset_quick_string(const zval *arr, char *index, uint index_length, unsigned long key);

/** Unset existing indexes */
extern int PHALCON_FASTCALL phalcon_array_unset(zval **arr, zval *index, int flags);
extern int PHALCON_FASTCALL phalcon_array_unset_long(zval **arr, unsigned long index, int flags);
extern int PHALCON_FASTCALL phalcon_array_unset_string(zval **arr, char *index, uint index_length, int flags);
int PHALCON_FASTCALL phalcon_array_unset(zval **arr, zval *index, int flags);
int PHALCON_FASTCALL phalcon_array_unset_long(zval **arr, unsigned long index, int flags);
int PHALCON_FASTCALL phalcon_array_unset_string(zval **arr, char *index, uint index_length, int flags);

/** Append elements to arrays */
extern int phalcon_array_append(zval **arr, zval *value, int separate);
extern int phalcon_array_append_long(zval **arr, long value, int separate);
extern int phalcon_array_append_string(zval **arr, char *value, uint value_length, int separate);
int phalcon_array_append(zval **arr, zval *value, int separate);
int phalcon_array_append_long(zval **arr, long value, int separate);
int phalcon_array_append_string(zval **arr, char *value, uint value_length, int separate);

/** Modify arrays */
extern int phalcon_array_update_zval(zval **arr, zval *index, zval **value, int flags);
extern int phalcon_array_update_zval_bool(zval **arr, zval *index, int value, int flags);
extern int phalcon_array_update_zval_long(zval **arr, zval *index, long value, int flags);
extern int phalcon_array_update_zval_string(zval **arr, zval *index, char *value, uint value_length, int flags);
int phalcon_array_update_zval(zval **arr, zval *index, zval **value, int flags);
int phalcon_array_update_zval_bool(zval **arr, zval *index, int value, int flags);
int phalcon_array_update_zval_long(zval **arr, zval *index, long value, int flags);
int phalcon_array_update_zval_string(zval **arr, zval *index, char *value, uint value_length, int flags);

extern int phalcon_array_update_string(zval **arr, char *index, uint index_length, zval **value, int flags);
extern int phalcon_array_update_string_bool(zval **arr, char *index, uint index_length, int value, int flags);
extern int phalcon_array_update_string_long(zval **arr, char *index, uint index_length, long value, int flags);
extern int phalcon_array_update_string_string(zval **arr, char *index, uint index_length, char *value, uint value_length, int flags);
int phalcon_array_update_string(zval **arr, char *index, uint index_length, zval **value, int flags);
int phalcon_array_update_string_bool(zval **arr, char *index, uint index_length, int value, int flags);
int phalcon_array_update_string_long(zval **arr, char *index, uint index_length, long value, int flags);
int phalcon_array_update_string_string(zval **arr, char *index, uint index_length, char *value, uint value_length, int flags);

extern int phalcon_array_update_long(zval **arr, unsigned long index, zval **value, int flags);
extern int phalcon_array_update_long_string(zval **arr, unsigned long index, char *value, uint value_length, int flags);
extern int phalcon_array_update_long_long(zval **arr, unsigned long index, long value, int flags);
extern int phalcon_array_update_long_bool(zval **arr, unsigned long index, int value, int flags);
int phalcon_array_update_long(zval **arr, unsigned long index, zval **value, int flags);
int phalcon_array_update_long_string(zval **arr, unsigned long index, char *value, uint value_length, int flags);
int phalcon_array_update_long_long(zval **arr, unsigned long index, long value, int flags);
int phalcon_array_update_long_bool(zval **arr, unsigned long index, int value, int flags);

/** Update/Append two dimension arrays */
extern void phalcon_array_update_multi_2(zval **config, zval *index1, zval *index2, zval **value, int flags);
extern void phalcon_array_update_string_multi_2(zval **arr, zval *index1, char *index2, uint index2_length, zval **value, int flags);
extern void phalcon_array_update_long_long_multi_2(zval **arr, long index1, long index2, zval **value, int flags);
extern void phalcon_array_update_long_string_multi_2(zval **arr, long index1, char *index2, uint index2_length, zval **value, int flags);
extern void phalcon_array_update_append_multi_2(zval **arr, zval *index1, zval *value, int flags);
void phalcon_array_update_multi_2(zval **config, zval *index1, zval *index2, zval **value, int flags);
void phalcon_array_update_string_multi_2(zval **arr, zval *index1, char *index2, uint index2_length, zval **value, int flags);
void phalcon_array_update_long_long_multi_2(zval **arr, long index1, long index2, zval **value, int flags);
void phalcon_array_update_long_string_multi_2(zval **arr, long index1, char *index2, uint index2_length, zval **value, int flags);
void phalcon_array_update_append_multi_2(zval **arr, zval *index1, zval *value, int flags);

/** Update/Append three dimension arrays */
extern void phalcon_array_update_zval_string_append_multi_3(zval **arr, zval *index1, char *index2, uint index2_length, zval **value, int flags);
extern void phalcon_array_update_zval_zval_zval_multi_3(zval **arr, zval *index1, zval *index2, zval *index3, zval **value, int flags);
extern void phalcon_array_update_string_zval_zval_multi_3(zval **arr, zval *index1, zval *index2, char *index3, uint index3_length, zval **value, int flags);
extern void phalcon_array_update_zval_string_string_multi_3(zval **arr, zval *index1, char *index2, uint index2_length, char *index3, uint index3_length, zval **value, int flags);
void phalcon_array_update_zval_string_append_multi_3(zval **arr, zval *index1, char *index2, uint index2_length, zval **value, int flags);
void phalcon_array_update_zval_zval_zval_multi_3(zval **arr, zval *index1, zval *index2, zval *index3, zval **value, int flags);
void phalcon_array_update_string_zval_zval_multi_3(zval **arr, zval *index1, zval *index2, char *index3, uint index3_length, zval **value, int flags);
void phalcon_array_update_zval_string_string_multi_3(zval **arr, zval *index1, char *index2, uint index2_length, char *index3, uint index3_length, zval **value, int flags);

/** Fetch items from arrays */
extern int phalcon_array_fetch(zval **return_value, zval *arr, zval *index, int silent);
extern int phalcon_array_fetch_string(zval **return_value, zval *arr, char *index, uint index_length, int silent);
extern int phalcon_array_fetch_long(zval **return_value, zval *arr, unsigned long index, int silent);
int phalcon_array_fetch(zval **return_value, zval *arr, zval *index, int silent);
int phalcon_array_fetch_string(zval **return_value, zval *arr, char *index, uint index_length, int silent);
int phalcon_array_fetch_long(zval **return_value, zval *arr, unsigned long index, int silent);

/** Merge+Append */
extern void phalcon_merge_append(zval *left, zval *values);
void phalcon_merge_append(zval *left, zval *values);

/* Traversing Arays */
extern void phalcon_array_get_current(zval *return_value, zval *array);
extern void phalcon_array_next(zval *array);
void phalcon_array_get_current(zval *return_value, zval *array);
void phalcon_array_next(zval *array);

/* In Array */
extern int phalcon_fast_in_array(zval *needle, zval *haystack TSRMLS_DC);
int phalcon_fast_in_array(zval *needle, zval *haystack TSRMLS_DC);

/** Fast Array Merge */
extern void phalcon_fast_array_merge(zval *return_value, zval **array1, zval **array2 TSRMLS_DC);
void phalcon_fast_array_merge(zval *return_value, zval **array1, zval **array2 TSRMLS_DC);

/** Recursive merge */
extern void phalcon_array_merge_recursive_n(zval **a1, zval *a2);
void phalcon_array_merge_recursive_n(zval **a1, zval *a2);

void phalcon_array_unshift(zval *arr, zval *arg);
void phalcon_array_keys(zval *return_value, zval *arr);
void phalcon_array_values(zval *return_value, zval *arr);
int phalcon_array_key_exists(zval *arr, zval *key TSRMLS_DC);
int phalcon_array_is_associative(zval *arr);

extern void phalcon_array_unshift(zval *arr, zval *arg);
extern void phalcon_array_keys(zval *return_value, zval *arr);
extern void phalcon_array_values(zval *return_value, zval *arr);
extern int phalcon_array_key_exists(zval *arr, zval *key TSRMLS_DC);
extern int phalcon_array_is_associative(zval *arr);
#endif /* PHALCON_KERNEL_ARRAY_H */
13 changes: 1 addition & 12 deletions ext/php_phalcon.h
Expand Up @@ -127,13 +127,7 @@ extern zend_module_entry phalcon_module_entry;
#endif

/** Define FASTCALL */
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
# define PHALCON_FASTCALL __attribute__((fastcall))
#elif defined(_MSC_VER) && defined(_M_IX86)
# define PHALCON_FASTCALL __fastcall
#else
# define PHALCON_FASTCALL
#endif
#define PHALCON_FASTCALL ZEND_FASTCALL

#define PHALCON_INIT_CLASS(name) \
int phalcon_ ##name## _init(INIT_FUNC_ARGS)
Expand All @@ -144,13 +138,8 @@ extern zend_module_entry phalcon_module_entry;
}

/** Macros for branch prediction */
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
#else
#define likely(x) EXPECTED(x)
#define unlikely(x) UNEXPECTED(x)
#endif

#if defined(__GNUC__) && (defined(__clang__) || ((__GNUC__ * 100 + __GNUC_MINOR__) >= 405))
#define UNREACHABLE() __builtin_unreachable()
Expand Down

0 comments on commit 460be93

Please sign in to comment.