Skip to content

Commit

Permalink
Merge pull request #830 from sjinks/faster-merge
Browse files Browse the repository at this point in the history
Faster phalcon_array_merge_recursive_n()
  • Loading branch information
Phalcon committed Jul 12, 2013
2 parents 78dfb6d + 9ec1f6d commit e84de39
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 48 deletions.
38 changes: 3 additions & 35 deletions ext/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,38 +292,6 @@ PHP_METHOD(Phalcon_Config, offsetUnset){
RETURN_TRUE;
}

static void array_merge_recursive_n(zval **a1, zval *a2 TSRMLS_DC)
{
HashTable *ah2;
HashPosition hp2;
zval **hd;
zval *key = NULL, *value = NULL;
zval *tmp1 = NULL, *tmp2 = NULL;

PHALCON_MM_GROW();

phalcon_is_iterable(a2, &ah2, &hp2, 0, 0);
while (zend_hash_get_current_data_ex(ah2, (void**) &hd, &hp2) == SUCCESS) {
PHALCON_GET_HKEY(key, ah2, hp2);
PHALCON_GET_HVALUE(value);

if (!phalcon_array_isset(*a1, key) || Z_TYPE_P(value) != IS_ARRAY) {
phalcon_array_update_zval(a1, key, &value, PH_COPY | PH_SEPARATE);
}
else {
PHALCON_INIT_NVAR(tmp1);
PHALCON_INIT_NVAR(tmp2);
phalcon_array_fetch(&tmp1, *a1, key, PH_NOISY);
phalcon_array_fetch(&tmp2, a2, key, PH_NOISY);
array_merge_recursive_n(&tmp1, tmp2 TSRMLS_CC);
}

zend_hash_move_forward_ex(ah2, &hp2);
}

PHALCON_MM_RESTORE();
}

/**
* Merges a configuration into the current one
*
Expand Down Expand Up @@ -380,17 +348,17 @@ PHP_METHOD(Phalcon_Config, merge){
else if (Z_TYPE_P(value) == IS_OBJECT && Z_TYPE_P(active_value) == IS_ARRAY) { /* Path AB in the test */
PHALCON_INIT_NVAR(other_array);
phalcon_call_func_p1(other_array, "get_object_vars", value);
array_merge_recursive_n(&active_value, other_array TSRMLS_CC);
phalcon_array_merge_recursive_n(&active_value, other_array);
phalcon_update_property_zval_zval(this_ptr, key, active_value TSRMLS_CC);
}
else if (Z_TYPE_P(value) == IS_ARRAY && Z_TYPE_P(active_value) == IS_OBJECT) { /* Path AC in the test */
PHALCON_INIT_NVAR(other_array);
phalcon_call_func_p1(other_array, "get_object_vars", active_value);
array_merge_recursive_n(&other_array, value TSRMLS_CC);
phalcon_array_merge_recursive_n(&other_array, value);
phalcon_update_property_zval_zval(this_ptr, key, other_array TSRMLS_CC);
}
else if (Z_TYPE_P(value) == IS_ARRAY && Z_TYPE_P(active_value) == IS_ARRAY) { /* Path AD in the test */
array_merge_recursive_n(&active_value, value TSRMLS_CC);
phalcon_array_merge_recursive_n(&active_value, value);
phalcon_update_property_zval_zval(this_ptr, key, active_value TSRMLS_CC);
}
else { /* Path AE in the test */
Expand Down
19 changes: 8 additions & 11 deletions ext/kernel/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -1362,30 +1362,27 @@ void phalcon_fast_array_merge(zval *return_value, zval **array1, zval **array2 T
*
* Equivalent to <tt>$a1 = array_merge_recursive($a1, $a2)</tt> in PHP with the only exception
* that Phalcon's version preserves numeric keys
*
* @todo @c PHALCON_GET_HVALUE() calls @c PHALCON_OBSERVE_VAR; does it mean that the calling function needs a memory frame? Are there any limitations?
*/
void phalcon_array_merge_recursive_n(zval **a1, zval *a2 TSRMLS_DC)
void phalcon_array_merge_recursive_n(zval **a1, zval *a2)
{
HashTable *ah2;
HashPosition hp2;
zval **hd;
zval *key = NULL, *value = NULL;
zval key;
zval *tmp1 = NULL, *tmp2 = NULL;

phalcon_is_iterable(a2, &ah2, &hp2, 0, 0);

while (zend_hash_get_current_data_ex(ah2, (void**) &hd, &hp2) == SUCCESS) {

PHALCON_GET_HKEY(key, ah2, hp2);
PHALCON_GET_HVALUE(value);
key = phalcon_get_current_key_w(ah2, &hp2);

if (!phalcon_array_isset(*a1, key) || Z_TYPE_P(value) != IS_ARRAY) {
phalcon_array_update_zval(a1, key, &value, PH_COPY | PH_SEPARATE);
if (!phalcon_array_isset(*a1, &key) || Z_TYPE_PP(hd) != IS_ARRAY) {
phalcon_array_update_zval(a1, &key, hd, PH_COPY | PH_SEPARATE);
} else {
phalcon_array_fetch(&tmp1, *a1, key, PH_NOISY);
phalcon_array_fetch(&tmp2, a2, key, PH_NOISY);
phalcon_array_merge_recursive_n(&tmp1, tmp2 TSRMLS_CC);
phalcon_array_fetch(&tmp1, *a1, &key, PH_NOISY);
phalcon_array_fetch(&tmp2, a2, &key, PH_NOISY);
phalcon_array_merge_recursive_n(&tmp1, tmp2);
zval_ptr_dtor(&tmp1);
zval_ptr_dtor(&tmp2);
tmp1 = NULL;
Expand Down
2 changes: 1 addition & 1 deletion ext/kernel/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ extern int phalcon_fast_in_array(zval *needle, zval *haystack TSRMLS_DC);
extern 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 TSRMLS_DC);
extern void phalcon_array_merge_recursive_n(zval **a1, zval *a2);
21 changes: 20 additions & 1 deletion ext/kernel/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,25 @@ void phalcon_get_current_key(zval **key, const HashTable *hash_table, HashPositi

}

zval phalcon_get_current_key_w(const HashTable *hash_table, HashPosition *hash_position)
{
Bucket *p;
zval result;

INIT_ZVAL(result);
p = hash_position ? (*hash_position) : hash_table->pInternalPointer;

if (p) {
if (p->nKeyLength) {
ZVAL_STRINGL(&result, (char *) p->arKey, p->nKeyLength - 1, 0);
} else {
ZVAL_LONG(&result, p->h);
}
}

return result;
}

/**
* Traverses the hash checking if at least one of the keys is numeric
*/
Expand All @@ -159,4 +178,4 @@ int phalcon_has_numeric_keys(const zval *data)
}

return 0;
}
}
1 change: 1 addition & 0 deletions ext/kernel/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ int phalcon_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyL
int phalcon_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
int phalcon_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData);
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);

0 comments on commit e84de39

Please sign in to comment.