@@ -1907,21 +1907,15 @@ PHP_FUNCTION(shuffle)
1907
1907
}
1908
1908
/* }}} */
1909
1909
1910
- PHPAPI HashTable * php_splice (HashTable * in_hash , int offset , int length , zval * list , int list_count , HashTable * removed ) /* {{{ */
1910
+ static void php_splice (HashTable * in_hash , int offset , int length , HashTable * replace , HashTable * removed ) /* {{{ */
1911
1911
{
1912
- HashTable * out_hash = NULL ; /* Output hashtable */
1912
+ HashTable out_hash ; /* Output hashtable */
1913
1913
int num_in , /* Number of entries in the input hashtable */
1914
- pos , /* Current position in the hashtable */
1915
- i ; /* Loop counter */
1914
+ pos ; /* Current position in the hashtable */
1916
1915
uint idx ;
1917
1916
Bucket * p ; /* Pointer to hash bucket */
1918
1917
zval * entry ; /* Hash entry */
1919
1918
1920
- /* If input hash doesn't exist, we have nothing to do */
1921
- if (!in_hash ) {
1922
- return NULL ;
1923
- }
1924
-
1925
1919
/* Get number of entries in the input hash */
1926
1920
num_in = zend_hash_num_elements (in_hash );
1927
1921
@@ -1940,8 +1934,7 @@ PHPAPI HashTable* php_splice(HashTable *in_hash, int offset, int length, zval *l
1940
1934
}
1941
1935
1942
1936
/* Create and initialize output hash */
1943
- ALLOC_HASHTABLE (out_hash );
1944
- zend_hash_init (out_hash , (length > 0 ? num_in - length : 0 ) + list_count , NULL , ZVAL_PTR_DTOR , 0 );
1937
+ zend_hash_init (& out_hash , (length > 0 ? num_in - length : 0 ) + (replace ? zend_hash_num_elements (replace ) : 0 ), NULL , ZVAL_PTR_DTOR , 0 );
1945
1938
1946
1939
/* Start at the beginning of the input hash and copy entries to output hash until offset is reached */
1947
1940
for (pos = 0 , idx = 0 ; pos < offset && idx < in_hash -> nNumUsed ; idx ++ ) {
@@ -1950,15 +1943,12 @@ PHPAPI HashTable* php_splice(HashTable *in_hash, int offset, int length, zval *l
1950
1943
pos ++ ;
1951
1944
/* Get entry and increase reference count */
1952
1945
entry = & p -> val ;
1953
- if (Z_REFCOUNTED_P (entry )) {
1954
- Z_ADDREF_P (entry );
1955
- }
1956
1946
1957
1947
/* Update output hash depending on key type */
1958
1948
if (p -> key == NULL ) {
1959
- zend_hash_next_index_insert ( out_hash , entry );
1949
+ zend_hash_next_index_insert_new ( & out_hash , entry );
1960
1950
} else {
1961
- zend_hash_update ( out_hash , p -> key , entry );
1951
+ zend_hash_add_new ( & out_hash , p -> key , entry );
1962
1952
}
1963
1953
}
1964
1954
@@ -1973,42 +1963,59 @@ PHPAPI HashTable* php_splice(HashTable *in_hash, int offset, int length, zval *l
1973
1963
Z_ADDREF_P (entry );
1974
1964
}
1975
1965
if (p -> key == NULL ) {
1976
- zend_hash_next_index_insert (removed , entry );
1966
+ zend_hash_next_index_insert_new (removed , entry );
1967
+ zend_hash_index_del (in_hash , p -> h );
1977
1968
} else {
1978
- zend_hash_update (removed , p -> key , entry );
1969
+ zend_hash_add_new (removed , p -> key , entry );
1970
+ if (in_hash == & EG (symbol_table ).ht ) {
1971
+ zend_delete_global_variable (p -> key );
1972
+ } else {
1973
+ zend_hash_del (in_hash , p -> key );
1974
+ }
1979
1975
}
1980
1976
}
1981
1977
} else { /* otherwise just skip those entries */
1982
- for ( ; pos < offset + length && idx < in_hash -> nNumUsed ; pos ++ , idx ++ );
1978
+ for ( ; pos < offset + length && idx < in_hash -> nNumUsed ; idx ++ ) {
1979
+ p = in_hash -> arData + idx ;
1980
+ if (Z_TYPE (p -> val ) == IS_UNDEF ) continue ;
1981
+ pos ++ ;
1982
+ if (p -> key == NULL ) {
1983
+ zend_hash_index_del (in_hash , p -> h );
1984
+ } else {
1985
+ if (in_hash == & EG (symbol_table ).ht ) {
1986
+ zend_delete_global_variable (p -> key );
1987
+ } else {
1988
+ zend_hash_del (in_hash , p -> key );
1989
+ }
1990
+ }
1991
+ }
1983
1992
}
1984
1993
1985
1994
/* If there are entries to insert.. */
1986
- if (list != NULL ) {
1987
- /* ..for each one, create a new zval, copy entry into it and copy it into the output hash */
1988
- for (i = 0 ; i < list_count ; i ++ ) {
1989
- entry = & list [i ];
1995
+ if (replace ) {
1996
+ ZEND_HASH_FOREACH_VAL_IND (replace , entry ) {
1990
1997
if (Z_REFCOUNTED_P (entry )) Z_ADDREF_P (entry );
1991
- zend_hash_next_index_insert ( out_hash , entry );
1992
- }
1998
+ zend_hash_next_index_insert_new ( & out_hash , entry );
1999
+ } ZEND_HASH_FOREACH_END ();
1993
2000
}
1994
2001
1995
2002
/* Copy the remaining input hash entries to the output hash */
1996
2003
for ( ; idx < in_hash -> nNumUsed ; idx ++ ) {
1997
2004
p = in_hash -> arData + idx ;
1998
2005
if (Z_TYPE (p -> val ) == IS_UNDEF ) continue ;
1999
2006
entry = & p -> val ;
2000
- if (Z_REFCOUNTED_P (entry )) {
2001
- Z_ADDREF_P (entry );
2002
- }
2003
2007
if (p -> key == NULL ) {
2004
- zend_hash_next_index_insert ( out_hash , entry );
2008
+ zend_hash_next_index_insert_new ( & out_hash , entry );
2005
2009
} else {
2006
- zend_hash_update ( out_hash , p -> key , entry );
2010
+ zend_hash_add_new ( & out_hash , p -> key , entry );
2007
2011
}
2008
2012
}
2009
2013
2010
- zend_hash_internal_pointer_reset (out_hash );
2011
- return out_hash ;
2014
+ zend_hash_internal_pointer_reset (& out_hash );
2015
+
2016
+ in_hash -> pDestructor = NULL ;
2017
+ zend_hash_destroy (in_hash );
2018
+ * in_hash = out_hash ;
2012
2019
}
2013
2020
/* }}} */
2014
2021
@@ -2224,7 +2231,7 @@ PHP_FUNCTION(array_unshift)
2224
2231
}
2225
2232
zend_hash_next_index_insert_new (& new_hash , & args [i ]);
2226
2233
}
2227
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND (Z_ARRVAL_P (stack ), key , value ) {
2234
+ ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (stack ), key , value ) {
2228
2235
if (key ) {
2229
2236
zend_hash_add_new (& new_hash , key , value );
2230
2237
} else {
@@ -2246,17 +2253,10 @@ PHP_FUNCTION(array_unshift)
2246
2253
PHP_FUNCTION (array_splice )
2247
2254
{
2248
2255
zval * array , /* Input array */
2249
- * repl_array = NULL , /* Replacement array */
2250
- * repl = NULL ; /* Replacement elements */
2251
- HashTable * new_hash = NULL , /* Output array's hash */
2252
- * rem_hash = NULL ; /* Removed elements' hash */
2253
- HashTable old_hash ;
2254
- uint idx ;
2255
- Bucket * p ; /* Bucket used for traversing hash */
2256
- zend_long i ,
2257
- offset ,
2258
- length = 0 ,
2259
- repl_num = 0 ; /* Number of replacement elements */
2256
+ * repl_array = NULL ; /* Replacement array */
2257
+ HashTable * rem_hash = NULL ;
2258
+ zend_long offset ,
2259
+ length = 0 ;
2260
2260
int num_in ; /* Number of elements in the input array */
2261
2261
2262
2262
if (zend_parse_parameters (ZEND_NUM_ARGS (), "a/l|lz/" , & array , & offset , & length , & repl_array ) == FAILURE ) {
@@ -2271,16 +2271,7 @@ PHP_FUNCTION(array_splice)
2271
2271
2272
2272
if (ZEND_NUM_ARGS () == 4 ) {
2273
2273
/* Make sure the last argument, if passed, is an array */
2274
- convert_to_array (repl_array );
2275
-
2276
- /* Create the array of replacement elements */
2277
- repl_num = zend_hash_num_elements (Z_ARRVAL_P (repl_array ));
2278
- repl = (zval * )safe_emalloc (repl_num , sizeof (zval ), 0 );
2279
- for (idx = 0 , i = 0 ; idx < Z_ARRVAL_P (repl_array )-> nNumUsed ; idx ++ ) {
2280
- p = Z_ARRVAL_P (repl_array )-> arData + idx ;
2281
- if (Z_TYPE (p -> val ) == IS_UNDEF ) continue ;
2282
- ZVAL_COPY_VALUE (& repl [i ++ ], & p -> val );
2283
- }
2274
+ convert_to_array_ex (repl_array );
2284
2275
}
2285
2276
2286
2277
/* Don't create the array of removed elements if it's not going
@@ -2308,18 +2299,7 @@ PHP_FUNCTION(array_splice)
2308
2299
}
2309
2300
2310
2301
/* Perform splice */
2311
- new_hash = php_splice (Z_ARRVAL_P (array ), (int )offset , (int )length , repl , (int )repl_num , rem_hash );
2312
-
2313
- /* Replace input array's hashtable with the new one */
2314
- old_hash = * Z_ARRVAL_P (array );
2315
- * Z_ARRVAL_P (array ) = * new_hash ;
2316
- FREE_HASHTABLE (new_hash );
2317
- zend_hash_destroy (& old_hash );
2318
-
2319
- /* Clean up */
2320
- if (ZEND_NUM_ARGS () == 4 ) {
2321
- efree (repl );
2322
- }
2302
+ php_splice (Z_ARRVAL_P (array ), (int )offset , (int )length , repl_array ? Z_ARRVAL_P (repl_array ) : NULL , rem_hash );
2323
2303
}
2324
2304
/* }}} */
2325
2305
@@ -3041,7 +3021,9 @@ PHP_FUNCTION(array_pad)
3041
3021
}
3042
3022
3043
3023
ZEND_HASH_FOREACH_STR_KEY_VAL_IND (Z_ARRVAL_P (input ), key , value ) {
3044
- zval_add_ref (value );
3024
+ if (Z_REFCOUNTED_P (value )) {
3025
+ Z_ADDREF_P (value );
3026
+ }
3045
3027
if (key ) {
3046
3028
zend_hash_add_new (Z_ARRVAL_P (return_value ), key , value );
3047
3029
} else {
0 commit comments