PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - array.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 2091
Code covered: 94.4 % Executed lines: 1974
Legend: not executed executed

       1                 : /* 
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Zeev Suraski <zeev@zend.com>                                |
      17                 :    |          Rasmus Lerdorf <rasmus@php.net>                             |
      18                 :    |          Andrei Zmievski <andrei@php.net>                            |
      19                 :    |          Stig Venaas <venaas@php.net>                                |
      20                 :    |          Jason Greene <jason@php.net>                                |
      21                 :    +----------------------------------------------------------------------+
      22                 : */
      23                 : 
      24                 : /* $Id: array.c 287275 2009-08-14 06:20:21Z dmitry $ */
      25                 : 
      26                 : #include "php.h"
      27                 : #include "php_ini.h"
      28                 : #include <stdarg.h>
      29                 : #include <stdlib.h>
      30                 : #include <math.h>
      31                 : #include <time.h>
      32                 : #include <stdio.h>
      33                 : #if HAVE_STRING_H
      34                 : #include <string.h>
      35                 : #else
      36                 : #include <strings.h>
      37                 : #endif
      38                 : #ifdef PHP_WIN32
      39                 : #include "win32/unistd.h"
      40                 : #endif
      41                 : #include "zend_globals.h"
      42                 : #include "zend_interfaces.h"
      43                 : #include "php_globals.h"
      44                 : #include "php_array.h"
      45                 : #include "basic_functions.h"
      46                 : #include "php_string.h"
      47                 : #include "php_rand.h"
      48                 : #include "php_smart_str.h"
      49                 : #ifdef HAVE_SPL
      50                 : #include "ext/spl/spl_array.h"
      51                 : #endif
      52                 : 
      53                 : /* {{{ defines */
      54                 : #define EXTR_OVERWRITE                  0
      55                 : #define EXTR_SKIP                               1
      56                 : #define EXTR_PREFIX_SAME                2
      57                 : #define EXTR_PREFIX_ALL                 3
      58                 : #define EXTR_PREFIX_INVALID             4
      59                 : #define EXTR_PREFIX_IF_EXISTS   5
      60                 : #define EXTR_IF_EXISTS                  6
      61                 : 
      62                 : #define EXTR_REFS                               0x100
      63                 : 
      64                 : #define CASE_LOWER                              0
      65                 : #define CASE_UPPER                              1
      66                 : 
      67                 : #define COUNT_NORMAL                    0
      68                 : #define COUNT_RECURSIVE                 1
      69                 : 
      70                 : #define DIFF_NORMAL                     1
      71                 : #define DIFF_KEY                        2
      72                 : #define DIFF_ASSOC                      6
      73                 : #define DIFF_COMP_DATA_NONE    -1
      74                 : #define DIFF_COMP_DATA_INTERNAL 0
      75                 : #define DIFF_COMP_DATA_USER     1
      76                 : #define DIFF_COMP_KEY_INTERNAL  0
      77                 : #define DIFF_COMP_KEY_USER      1
      78                 : 
      79                 : #define INTERSECT_NORMAL                1
      80                 : #define INTERSECT_KEY                   2
      81                 : #define INTERSECT_ASSOC                 6
      82                 : #define INTERSECT_COMP_DATA_NONE    -1
      83                 : #define INTERSECT_COMP_DATA_INTERNAL 0
      84                 : #define INTERSECT_COMP_DATA_USER     1
      85                 : #define INTERSECT_COMP_KEY_INTERNAL  0
      86                 : #define INTERSECT_COMP_KEY_USER      1
      87                 : 
      88                 : #define DOUBLE_DRIFT_FIX        0.000000000000001
      89                 : /* }}} */
      90                 : 
      91                 : ZEND_DECLARE_MODULE_GLOBALS(array)
      92                 : 
      93                 : /* {{{ php_array_init_globals
      94                 : */
      95                 : static void php_array_init_globals(zend_array_globals *array_globals)
      96           17633 : {
      97           17633 :         memset(array_globals, 0, sizeof(zend_array_globals));
      98           17633 : }
      99                 : /* }}} */
     100                 : 
     101                 : PHP_MINIT_FUNCTION(array) /* {{{ */
     102           17633 : {
     103           17633 :         ZEND_INIT_MODULE_GLOBALS(array, php_array_init_globals, NULL);
     104                 : 
     105           17633 :         REGISTER_LONG_CONSTANT("EXTR_OVERWRITE", EXTR_OVERWRITE, CONST_CS | CONST_PERSISTENT);
     106           17633 :         REGISTER_LONG_CONSTANT("EXTR_SKIP", EXTR_SKIP, CONST_CS | CONST_PERSISTENT);
     107           17633 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_SAME", EXTR_PREFIX_SAME, CONST_CS | CONST_PERSISTENT);
     108           17633 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_ALL", EXTR_PREFIX_ALL, CONST_CS | CONST_PERSISTENT);
     109           17633 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_INVALID", EXTR_PREFIX_INVALID, CONST_CS | CONST_PERSISTENT);
     110           17633 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
     111           17633 :         REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
     112           17633 :         REGISTER_LONG_CONSTANT("EXTR_REFS", EXTR_REFS, CONST_CS | CONST_PERSISTENT);
     113                 : 
     114           17633 :         REGISTER_LONG_CONSTANT("SORT_ASC", PHP_SORT_ASC, CONST_CS | CONST_PERSISTENT);
     115           17633 :         REGISTER_LONG_CONSTANT("SORT_DESC", PHP_SORT_DESC, CONST_CS | CONST_PERSISTENT);
     116                 : 
     117           17633 :         REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
     118           17633 :         REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
     119           17633 :         REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT);
     120           17633 :         REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
     121                 : 
     122           17633 :         REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT);
     123           17633 :         REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT);
     124                 : 
     125           17633 :         REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT);
     126           17633 :         REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT);
     127                 : 
     128           17633 :         return SUCCESS;
     129                 : }
     130                 : /* }}} */
     131                 : 
     132                 : PHP_MSHUTDOWN_FUNCTION(array) /* {{{ */
     133           17665 : {
     134                 : #ifdef ZTS
     135                 :         ts_free_id(array_globals_id);
     136                 : #endif
     137                 : 
     138           17665 :         return SUCCESS;
     139                 : }
     140                 : /* }}} */
     141                 : 
     142                 : static void php_set_compare_func(int sort_type TSRMLS_DC) /* {{{ */
     143            3042 : {
     144            3042 :         switch (sort_type) {
     145                 :                 case PHP_SORT_NUMERIC:
     146             103 :                         ARRAYG(compare_func) = numeric_compare_function;
     147             103 :                         break;
     148                 : 
     149                 :                 case PHP_SORT_STRING:
     150            1453 :                         ARRAYG(compare_func) = string_compare_function;
     151            1453 :                         break;
     152                 : 
     153                 : #if HAVE_STRCOLL
     154                 :                 case PHP_SORT_LOCALE_STRING:
     155               1 :                         ARRAYG(compare_func) = string_locale_compare_function;
     156               1 :                         break;
     157                 : #endif
     158                 : 
     159                 :                 case PHP_SORT_REGULAR:
     160                 :                 default:
     161            1485 :                         ARRAYG(compare_func) = compare_function;
     162                 :                         break;
     163                 :         }
     164            3042 : }
     165                 : /* }}} */
     166                 : 
     167                 : static int php_array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     168            2645 : {
     169                 :         Bucket *f;
     170                 :         Bucket *s;
     171                 :         zval result;
     172                 :         zval first;
     173                 :         zval second;
     174                 : 
     175            2645 :         f = *((Bucket **) a);
     176            2645 :         s = *((Bucket **) b);
     177                 : 
     178            2645 :         if (f->nKeyLength == 0) {
     179            1563 :                 Z_TYPE(first) = IS_LONG;
     180            1563 :                 Z_LVAL(first) = f->h;
     181                 :         } else {
     182            1082 :                 Z_TYPE(first) = IS_STRING;
     183            1082 :                 Z_STRVAL(first) = f->arKey;
     184            1082 :                 Z_STRLEN(first) = f->nKeyLength - 1;
     185                 :         }
     186                 : 
     187            2645 :         if (s->nKeyLength == 0) {
     188            1573 :                 Z_TYPE(second) = IS_LONG;
     189            1573 :                 Z_LVAL(second) = s->h;
     190                 :         } else {
     191            1072 :                 Z_TYPE(second) = IS_STRING;
     192            1072 :                 Z_STRVAL(second) = s->arKey;
     193            1072 :                 Z_STRLEN(second) = s->nKeyLength - 1;
     194                 :         }
     195                 : 
     196            2645 :         if (ARRAYG(compare_func)(&result, &first, &second TSRMLS_CC) == FAILURE) {
     197               0 :                 return 0;
     198                 :         }
     199                 : 
     200            2645 :         if (Z_TYPE(result) == IS_DOUBLE) {
     201               0 :                 if (Z_DVAL(result) < 0) {
     202               0 :                         return -1;
     203               0 :                 } else if (Z_DVAL(result) > 0) {
     204               0 :                         return 1;
     205                 :                 } else {
     206               0 :                         return 0;
     207                 :                 }
     208                 :         }
     209                 : 
     210            2645 :         convert_to_long(&result);
     211                 : 
     212            2645 :         if (Z_LVAL(result) < 0) {
     213            1136 :                 return -1;
     214            1509 :         } else if (Z_LVAL(result) > 0) {
     215            1487 :                 return 1;
     216                 :         }
     217                 : 
     218              22 :         return 0;
     219                 : }
     220                 : /* }}} */
     221                 : 
     222                 : static int php_array_reverse_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     223            1074 : {
     224            1074 :         return php_array_key_compare(a, b TSRMLS_CC) * -1;
     225                 : }
     226                 : /* }}} */
     227                 : 
     228                 : /* {{{ proto bool krsort(array &array_arg [, int sort_flags])
     229                 :    Sort an array by key value in reverse order */
     230                 : PHP_FUNCTION(krsort)
     231             190 : {
     232                 :         zval *array;
     233             190 :         long sort_type = PHP_SORT_REGULAR;
     234                 : 
     235             190 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     236             104 :                 RETURN_FALSE;
     237                 :         }
     238                 : 
     239              86 :         php_set_compare_func(sort_type TSRMLS_CC);
     240                 : 
     241              86 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) {
     242               0 :                 RETURN_FALSE;
     243                 :         }
     244              86 :         RETURN_TRUE;
     245                 : }
     246                 : /* }}} */
     247                 : 
     248                 : /* {{{ proto bool ksort(array &array_arg [, int sort_flags])
     249                 :    Sort an array by key */
     250                 : PHP_FUNCTION(ksort)
     251             424 : {
     252                 :         zval *array;
     253             424 :         long sort_type = PHP_SORT_REGULAR;
     254                 : 
     255             424 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     256             104 :                 RETURN_FALSE;
     257                 :         }
     258                 : 
     259             320 :         php_set_compare_func(sort_type TSRMLS_CC);
     260                 : 
     261             320 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_key_compare, 0 TSRMLS_CC) == FAILURE) {
     262               0 :                 RETURN_FALSE;
     263                 :         }
     264             320 :         RETURN_TRUE;
     265                 : }
     266                 : /* }}} */
     267                 : 
     268                 : static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */
     269           14082 : {
     270           14082 :         long cnt = 0;
     271                 :         zval **element;
     272                 : 
     273           14082 :         if (Z_TYPE_P(array) == IS_ARRAY) {
     274           13893 :                 if (Z_ARRVAL_P(array)->nApplyCount > 1) {
     275               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
     276               1 :                         return 0;
     277                 :                 }
     278                 : 
     279           13892 :                 cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
     280           13892 :                 if (mode == COUNT_RECURSIVE) {
     281                 :                         HashPosition pos;
     282                 : 
     283             103 :                         for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
     284             454 :                                 zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS;
     285                 :                                 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
     286             248 :                         ) {
     287             248 :                                 Z_ARRVAL_P(array)->nApplyCount++;
     288             248 :                                 cnt += php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC);
     289             248 :                                 Z_ARRVAL_P(array)->nApplyCount--;
     290                 :                         }
     291                 :                 }
     292                 :         }
     293                 : 
     294           14081 :         return cnt;
     295                 : }
     296                 : /* }}} */
     297                 : 
     298                 : /* {{{ proto int count(mixed var [, int mode])
     299                 :    Count the number of elements in a variable (usually an array) */
     300                 : PHP_FUNCTION(count)
     301          136431 : {
     302                 :         zval *array;
     303          136431 :         long mode = COUNT_NORMAL;
     304                 : 
     305          136431 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) {
     306              23 :                 return;
     307                 :         }
     308                 : 
     309          136408 :         switch (Z_TYPE_P(array)) {
     310                 :                 case IS_NULL:
     311           99754 :                         RETURN_LONG(0);
     312                 :                         break;
     313                 :                 case IS_ARRAY:
     314           13834 :                         RETURN_LONG (php_count_recursive (array, mode TSRMLS_CC));
     315                 :                         break;
     316                 :                 case IS_OBJECT: {
     317                 : #ifdef HAVE_SPL
     318                 :                         zval *retval;
     319                 : #endif
     320                 :                         /* first, we check if the handler is defined */
     321             103 :                         if (Z_OBJ_HT_P(array)->count_elements) {
     322              63 :                                 RETVAL_LONG(1);
     323              63 :                                 if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value) TSRMLS_CC)) {
     324              61 :                                         return;
     325                 :                                 }
     326                 :                         }
     327                 : #ifdef HAVE_SPL
     328                 :                         /* if not and the object implements Countable we call its count() method */
     329              42 :                         if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) {
     330              25 :                                 zend_call_method_with_0_params(&array, NULL, NULL, "count", &retval);
     331              25 :                                 if (retval) {
     332              23 :                                         convert_to_long_ex(&retval);
     333              23 :                                         RETVAL_LONG(Z_LVAL_P(retval));
     334              23 :                                         zval_ptr_dtor(&retval);
     335                 :                                 }
     336              25 :                                 return;
     337                 :                         }
     338                 : #endif
     339                 :                 }
     340                 :                 default:
     341           22734 :                         RETURN_LONG(1);
     342                 :                         break;
     343                 :         }
     344                 : }
     345                 : /* }}} */
     346                 : 
     347                 : /* Numbers are always smaller than strings int this function as it
     348                 :  * anyway doesn't make much sense to compare two different data types.
     349                 :  * This keeps it consistant and simple.
     350                 :  *
     351                 :  * This is not correct any more, depends on what compare_func is set to.
     352                 :  */
     353                 : static int php_array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     354          818399 : {
     355                 :         Bucket *f;
     356                 :         Bucket *s;
     357                 :         zval result;
     358                 :         zval *first;
     359                 :         zval *second;
     360                 : 
     361          818399 :         f = *((Bucket **) a);
     362          818399 :         s = *((Bucket **) b);
     363                 : 
     364          818399 :         first = *((zval **) f->pData);
     365          818399 :         second = *((zval **) s->pData);
     366                 : 
     367          818399 :         if (ARRAYG(compare_func)(&result, first, second TSRMLS_CC) == FAILURE) {
     368               0 :                 return 0;
     369                 :         }
     370                 : 
     371          818399 :         if (Z_TYPE(result) == IS_DOUBLE) {
     372               0 :                 if (Z_DVAL(result) < 0) {
     373               0 :                         return -1;
     374               0 :                 } else if (Z_DVAL(result) > 0) {
     375               0 :                         return 1;
     376                 :                 } else {
     377               0 :                         return 0;
     378                 :                 }
     379                 :         }
     380                 : 
     381          818399 :         convert_to_long(&result);
     382                 : 
     383          818399 :         if (Z_LVAL(result) < 0) {
     384           86491 :                 return -1;
     385          731908 :         } else if (Z_LVAL(result) > 0) {
     386          716998 :                 return 1;
     387                 :         }
     388                 : 
     389           14910 :         return 0;
     390                 : }
     391                 : /* }}} */
     392                 : 
     393                 : static int php_array_reverse_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     394            1994 : {
     395            1994 :         return php_array_data_compare(a, b TSRMLS_CC) * -1;
     396                 : }
     397                 : /* }}} */
     398                 : 
     399                 : static int php_array_natural_general_compare(const void *a, const void *b, int fold_case) /* {{{ */
     400             455 : {
     401                 :         Bucket *f, *s;
     402                 :         zval *fval, *sval;
     403                 :         zval first, second;
     404                 :         int result;
     405                 : 
     406             455 :         f = *((Bucket **) a);
     407             455 :         s = *((Bucket **) b);
     408                 : 
     409             455 :         fval = *((zval **) f->pData);
     410             455 :         sval = *((zval **) s->pData);
     411             455 :         first = *fval;
     412             455 :         second = *sval;
     413                 : 
     414             455 :         if (Z_TYPE_P(fval) != IS_STRING) {
     415             214 :                 zval_copy_ctor(&first);
     416             214 :                 convert_to_string(&first);
     417                 :         }
     418                 : 
     419             455 :         if (Z_TYPE_P(sval) != IS_STRING) {
     420             214 :                 zval_copy_ctor(&second);
     421             214 :                 convert_to_string(&second);
     422                 :         }
     423                 : 
     424             455 :         result = strnatcmp_ex(Z_STRVAL(first), Z_STRLEN(first), Z_STRVAL(second), Z_STRLEN(second), fold_case);
     425                 : 
     426             455 :         if (Z_TYPE_P(fval) != IS_STRING) {
     427             214 :                 zval_dtor(&first);
     428                 :         }
     429                 : 
     430             455 :         if (Z_TYPE_P(sval) != IS_STRING) {
     431             214 :                 zval_dtor(&second);
     432                 :         }
     433                 : 
     434             455 :         return result;
     435                 : }
     436                 : /* }}} */
     437                 : 
     438                 : static int php_array_natural_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     439              59 : {
     440              59 :         return php_array_natural_general_compare(a, b, 0);
     441                 : }
     442                 : /* }}} */
     443                 : 
     444                 : static int php_array_natural_case_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     445             396 : {
     446             396 :         return php_array_natural_general_compare(a, b, 1);
     447                 : }
     448                 : /* }}} */
     449                 : 
     450                 : static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */
     451              77 : {
     452                 :         zval *array;
     453                 : 
     454              77 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
     455              26 :                 return;
     456                 :         }
     457                 : 
     458              51 :         if (fold_case) {
     459              46 :                 if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) {
     460               0 :                         return;
     461                 :                 }
     462                 :         } else {
     463               5 :                 if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_compare, 0 TSRMLS_CC) == FAILURE) {
     464               0 :                         return;
     465                 :                 }
     466                 :         }
     467                 : 
     468              51 :         RETURN_TRUE;
     469                 : }
     470                 : /* }}} */
     471                 : 
     472                 : /* {{{ proto void natsort(array &array_arg)
     473                 :    Sort an array using natural sort */
     474                 : PHP_FUNCTION(natsort)
     475               5 : {
     476               5 :         php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     477               5 : }
     478                 : /* }}} */
     479                 : 
     480                 : /* {{{ proto void natcasesort(array &array_arg)
     481                 :    Sort an array using case-insensitive natural sort */
     482                 : PHP_FUNCTION(natcasesort)
     483              72 : {
     484              72 :         php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     485              72 : }
     486                 : /* }}} */
     487                 : 
     488                 : /* {{{ proto bool asort(array &array_arg [, int sort_flags])
     489                 :    Sort an array and maintain index association */
     490                 : PHP_FUNCTION(asort)
     491             201 : {
     492                 :         zval *array;
     493             201 :         long sort_type = PHP_SORT_REGULAR;
     494                 : 
     495             201 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     496             104 :                 RETURN_FALSE;
     497                 :         }
     498                 : 
     499              97 :         php_set_compare_func(sort_type TSRMLS_CC);
     500                 : 
     501              97 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_data_compare, 0 TSRMLS_CC) == FAILURE) {
     502               0 :                 RETURN_FALSE;
     503                 :         }
     504              97 :         RETURN_TRUE;
     505                 : }
     506                 : /* }}} */
     507                 : 
     508                 : /* {{{ proto bool arsort(array &array_arg [, int sort_flags])
     509                 :    Sort an array in reverse order and maintain index association */
     510                 : PHP_FUNCTION(arsort)
     511             181 : {
     512                 :         zval *array;
     513             181 :         long sort_type = PHP_SORT_REGULAR;
     514                 : 
     515             181 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     516             104 :                 RETURN_FALSE;
     517                 :         }
     518                 : 
     519              77 :         php_set_compare_func(sort_type TSRMLS_CC);
     520                 : 
     521              77 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_data_compare, 0 TSRMLS_CC) == FAILURE) {
     522               0 :                 RETURN_FALSE;
     523                 :         }
     524              77 :         RETURN_TRUE;
     525                 : }
     526                 : /* }}} */
     527                 : 
     528                 : /* {{{ proto bool sort(array &array_arg [, int sort_flags])
     529                 :    Sort an array */
     530                 : PHP_FUNCTION(sort)
     531             224 : {
     532                 :         zval *array;
     533             224 :         long sort_type = PHP_SORT_REGULAR;
     534                 : 
     535             224 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     536             104 :                 RETURN_FALSE;
     537                 :         }
     538                 : 
     539             120 :         php_set_compare_func(sort_type TSRMLS_CC);
     540                 : 
     541             120 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
     542               0 :                 RETURN_FALSE;
     543                 :         }
     544             120 :         RETURN_TRUE;
     545                 : }
     546                 : /* }}} */
     547                 : 
     548                 : /* {{{ proto bool rsort(array &array_arg [, int sort_flags])
     549                 :    Sort an array in reverse order */
     550                 : PHP_FUNCTION(rsort)
     551             191 : {
     552                 :         zval *array;
     553             191 :         long sort_type = PHP_SORT_REGULAR;
     554                 : 
     555             191 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
     556             105 :                 RETURN_FALSE;
     557                 :         }
     558                 : 
     559              86 :         php_set_compare_func(sort_type TSRMLS_CC);
     560                 : 
     561              86 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_data_compare, 1 TSRMLS_CC) == FAILURE) {
     562               0 :                 RETURN_FALSE;
     563                 :         }
     564              86 :         RETURN_TRUE;
     565                 : }
     566                 : /* }}} */
     567                 : 
     568                 : static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     569          185869 : {
     570                 :         Bucket *f;
     571                 :         Bucket *s;
     572                 :         zval **args[2];
     573          185869 :         zval *retval_ptr = NULL;
     574                 : 
     575          185869 :         f = *((Bucket **) a);
     576          185869 :         s = *((Bucket **) b);
     577                 : 
     578          185869 :         args[0] = (zval **) f->pData;
     579          185869 :         args[1] = (zval **) s->pData;
     580                 : 
     581          185869 :         BG(user_compare_fci).param_count = 2;
     582          185869 :         BG(user_compare_fci).params = args;
     583          185869 :         BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
     584          185869 :         BG(user_compare_fci).no_separation = 0;
     585          185869 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
     586                 :                 long retval;
     587                 : 
     588          185869 :                 convert_to_long_ex(&retval_ptr);
     589          185869 :                 retval = Z_LVAL_P(retval_ptr);
     590          185869 :                 zval_ptr_dtor(&retval_ptr);
     591          185869 :                 return retval < 0 ? -1 : retval > 0 ? 1 : 0;
     592                 :         } else {
     593               0 :                 return 0;
     594                 :         }
     595                 : }
     596                 : /* }}} */
     597                 : 
     598                 : /* check if comparison function is valid */
     599                 : #define PHP_ARRAY_CMP_FUNC_CHECK(func_name)     \
     600                 :         if (!zend_is_callable(*func_name, 0, NULL TSRMLS_CC)) { \
     601                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid comparison function");   \
     602                 :                 BG(user_compare_fci) = old_user_compare_fci; \
     603                 :                 BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
     604                 :                 RETURN_FALSE;   \
     605                 :         }       \
     606                 : 
     607                 :         /* Clear FCI cache otherwise : for example the same or other array with
     608                 :          * (partly) the same key values has been sorted with uasort() or
     609                 :          * other sorting function the comparison is cached, however the the name
     610                 :          * of the function for comparison is not respected. see bug #28739 AND #33295
     611                 :          *
     612                 :          * Following defines will assist in backup / restore values. */
     613                 : 
     614                 : #define PHP_ARRAY_CMP_FUNC_VARS \
     615                 :         zend_fcall_info old_user_compare_fci; \
     616                 :         zend_fcall_info_cache old_user_compare_fci_cache \
     617                 : 
     618                 : #define PHP_ARRAY_CMP_FUNC_BACKUP() \
     619                 :         old_user_compare_fci = BG(user_compare_fci); \
     620                 :         old_user_compare_fci_cache = BG(user_compare_fci_cache); \
     621                 :         BG(user_compare_fci_cache) = empty_fcall_info_cache; \
     622                 : 
     623                 : #define PHP_ARRAY_CMP_FUNC_RESTORE() \
     624                 :         BG(user_compare_fci) = old_user_compare_fci; \
     625                 :         BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
     626                 : 
     627                 : /* {{{ proto bool usort(array array_arg, string cmp_function)
     628                 :    Sort an array by values using a user-defined comparison function */
     629                 : PHP_FUNCTION(usort)
     630              96 : {
     631                 :         zval *array;
     632                 :         int refcount;
     633                 :         PHP_ARRAY_CMP_FUNC_VARS;
     634                 : 
     635              96 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     636                 : 
     637              96 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     638              58 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     639              58 :                 return;
     640                 :         }
     641                 : 
     642                 :         /* Clear the is_ref flag, so the attemts to modify the array in user
     643                 :          * comaprison function will create a copy of array and won't affect the
     644                 :          * original array. The fact of modification is detected using refcount
     645                 :          * comparison. The result of sorting in such case is undefined and the
     646                 :          * function returns FALSE.
     647                 :          */
     648              38 :         Z_UNSET_ISREF_P(array);
     649              38 :         refcount = Z_REFCOUNT_P(array);
     650                 : 
     651              38 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 1 TSRMLS_CC) == FAILURE) {
     652               0 :                 RETVAL_FALSE;
     653                 :         } else {
     654              38 :                 if (refcount > Z_REFCOUNT_P(array)) {
     655               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
     656               1 :                         RETVAL_FALSE;
     657                 :                 } else {
     658              37 :                         RETVAL_TRUE;
     659                 :                 }
     660                 :         }
     661                 :         
     662              38 :         if (Z_REFCOUNT_P(array) > 1) {
     663              37 :                 Z_SET_ISREF_P(array);
     664                 :         }
     665                 : 
     666              38 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     667                 : }
     668                 : /* }}} */
     669                 : 
     670                 : /* {{{ proto bool uasort(array array_arg, string cmp_function)
     671                 :    Sort an array with a user-defined comparison function and maintain index association */
     672                 : PHP_FUNCTION(uasort)
     673              92 : {
     674                 :         zval *array;
     675                 :         int refcount;
     676                 :         PHP_ARRAY_CMP_FUNC_VARS;
     677                 : 
     678              92 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     679                 : 
     680              92 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     681              57 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     682              57 :                 return;
     683                 :         }
     684                 : 
     685                 :         /* Clear the is_ref flag, so the attemts to modify the array in user
     686                 :          * comaprison function will create a copy of array and won't affect the
     687                 :          * original array. The fact of modification is detected using refcount
     688                 :          * comparison. The result of sorting in such case is undefined and the
     689                 :          * function returns FALSE.
     690                 :          */
     691              35 :         Z_UNSET_ISREF_P(array);
     692              35 :         refcount = Z_REFCOUNT_P(array);
     693                 : 
     694              35 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 0 TSRMLS_CC) == FAILURE) {
     695               0 :                 RETVAL_FALSE;
     696                 :         } else {
     697              35 :                 if (refcount > Z_REFCOUNT_P(array)) {
     698               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
     699               0 :                         RETVAL_FALSE;
     700                 :                 } else {
     701              35 :                         RETVAL_TRUE;
     702                 :                 }
     703                 :         }
     704                 : 
     705              35 :         if (Z_REFCOUNT_P(array) > 1) {
     706              35 :                 Z_SET_ISREF_P(array);
     707                 :         }
     708                 : 
     709              35 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     710                 : }
     711                 : /* }}} */
     712                 : 
     713                 : static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
     714            4797 : {
     715                 :         Bucket *f;
     716                 :         Bucket *s;
     717                 :         zval *key1, *key2;
     718                 :         zval **args[2];
     719            4797 :         zval *retval_ptr = NULL;
     720                 :         long result;
     721                 : 
     722            4797 :         ALLOC_INIT_ZVAL(key1);
     723            4797 :         ALLOC_INIT_ZVAL(key2);
     724            4797 :         args[0] = &key1;
     725            4797 :         args[1] = &key2;
     726                 : 
     727            4797 :         f = *((Bucket **) a);
     728            4797 :         s = *((Bucket **) b);
     729                 : 
     730            4797 :         if (f->nKeyLength == 0) {
     731            2191 :                 Z_LVAL_P(key1) = f->h;
     732            2191 :                 Z_TYPE_P(key1) = IS_LONG;
     733                 :         } else {
     734            2606 :                 Z_STRVAL_P(key1) = estrndup(f->arKey, f->nKeyLength - 1);
     735            2606 :                 Z_STRLEN_P(key1) = f->nKeyLength - 1;
     736            2606 :                 Z_TYPE_P(key1) = IS_STRING;
     737                 :         }
     738            4797 :         if (s->nKeyLength == 0) {
     739            2203 :                 Z_LVAL_P(key2) = s->h;
     740            2203 :                 Z_TYPE_P(key2) = IS_LONG;
     741                 :         } else {
     742            2594 :                 Z_STRVAL_P(key2) = estrndup(s->arKey, s->nKeyLength - 1);
     743            2594 :                 Z_STRLEN_P(key2) = s->nKeyLength - 1;
     744            2594 :                 Z_TYPE_P(key2) = IS_STRING;
     745                 :         }
     746                 : 
     747            4797 :         BG(user_compare_fci).param_count = 2;
     748            4797 :         BG(user_compare_fci).params = args;
     749            4797 :         BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
     750            4797 :         BG(user_compare_fci).no_separation = 0;
     751            9594 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
     752            4797 :                 convert_to_long_ex(&retval_ptr);
     753            4797 :                 result = Z_LVAL_P(retval_ptr);
     754            4797 :                 zval_ptr_dtor(&retval_ptr);
     755                 :         } else {
     756               0 :                 result = 0;
     757                 :         }
     758                 : 
     759            4797 :         zval_ptr_dtor(&key1);
     760            4797 :         zval_ptr_dtor(&key2);
     761                 : 
     762            4797 :         return result;
     763                 : }
     764                 : /* }}} */
     765                 : 
     766                 : /* {{{ proto bool uksort(array array_arg, string cmp_function)
     767                 :    Sort an array by keys using a user-defined comparison function */
     768                 : PHP_FUNCTION(uksort)
     769              57 : {
     770                 :         zval *array;
     771                 :         PHP_ARRAY_CMP_FUNC_VARS;
     772                 : 
     773              57 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     774                 : 
     775              57 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     776              53 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     777              53 :                 return;
     778                 :         }
     779                 : 
     780               4 :         if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_key_compare, 0 TSRMLS_CC) == FAILURE) {
     781               0 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     782               0 :                 RETURN_FALSE;
     783                 :         }
     784                 : 
     785               4 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     786               4 :         RETURN_TRUE;
     787                 : }
     788                 : /* }}} */
     789                 : 
     790                 : /* {{{ proto mixed end(array array_arg)
     791                 :    Advances array argument's internal pointer to the last element and return it */
     792                 : PHP_FUNCTION(end)
     793              74 : {
     794                 :         HashTable *array;
     795                 :         zval **entry;
     796                 : 
     797              74 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     798              29 :                 return;
     799                 :         }
     800                 : 
     801              45 :         zend_hash_internal_pointer_end(array);
     802                 : 
     803              45 :         if (return_value_used) {
     804              33 :                 if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
     805               2 :                         RETURN_FALSE;
     806                 :                 }
     807                 : 
     808              31 :                 RETURN_ZVAL(*entry, 1, 0);
     809                 :         }
     810                 : }
     811                 : /* }}} */
     812                 : 
     813                 : /* {{{ proto mixed prev(array array_arg)
     814                 :    Move array argument's internal pointer to the previous element and return it */
     815                 : PHP_FUNCTION(prev)
     816              43 : {
     817                 :         HashTable *array;
     818                 :         zval **entry;
     819                 : 
     820              43 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     821              25 :                 return;
     822                 :         }
     823                 : 
     824              18 :         zend_hash_move_backwards(array);
     825                 : 
     826              18 :         if (return_value_used) {
     827              18 :                 if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
     828               6 :                         RETURN_FALSE;
     829                 :                 }
     830                 : 
     831              12 :                 RETURN_ZVAL(*entry, 1, 0);
     832                 :         }
     833                 : }
     834                 : /* }}} */
     835                 : 
     836                 : /* {{{ proto mixed next(array array_arg)
     837                 :    Move array argument's internal pointer to the next element and return it */
     838                 : PHP_FUNCTION(next)
     839             930 : {
     840                 :         HashTable *array;
     841                 :         zval **entry;
     842                 : 
     843             930 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     844              31 :                 return;
     845                 :         }
     846                 : 
     847             899 :         zend_hash_move_forward(array);
     848                 : 
     849             899 :         if (return_value_used) {
     850             863 :                 if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
     851             164 :                         RETURN_FALSE;
     852                 :                 }
     853                 : 
     854             699 :                 RETURN_ZVAL(*entry, 1, 0);
     855                 :         }
     856                 : }
     857                 : /* }}} */
     858                 : 
     859                 : /* {{{ proto mixed reset(array array_arg)
     860                 :    Set array argument's internal pointer to the first element and return it */
     861                 : PHP_FUNCTION(reset)
     862             255 : {
     863                 :         HashTable *array;
     864                 :         zval **entry;
     865                 : 
     866             255 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     867              31 :                 return;
     868                 :         }
     869                 : 
     870             224 :         zend_hash_internal_pointer_reset(array);
     871                 : 
     872             224 :         if (return_value_used) {
     873              41 :                 if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
     874               3 :                         RETURN_FALSE;
     875                 :                 }
     876                 : 
     877              38 :                 RETURN_ZVAL(*entry, 1, 0);
     878                 :         }
     879                 : }
     880                 : /* }}} */
     881                 : 
     882                 : /* {{{ proto mixed current(array array_arg)
     883                 :    Return the element currently pointed to by the internal array pointer */
     884                 : PHP_FUNCTION(current)
     885            1023 : {
     886                 :         HashTable *array;
     887                 :         zval **entry;
     888                 : 
     889            1023 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     890              31 :                 return;
     891                 :         }
     892                 : 
     893             992 :         if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
     894              26 :                 RETURN_FALSE;
     895                 :         }
     896             966 :         RETURN_ZVAL(*entry, 1, 0);
     897                 : }
     898                 : /* }}} */
     899                 : 
     900                 : /* {{{ proto mixed key(array array_arg)
     901                 :    Return the key of the element currently pointed to by the internal array pointer */
     902                 : PHP_FUNCTION(key)
     903            1039 : {
     904                 :         HashTable *array;
     905                 :         char *string_key;
     906                 :         uint string_length;
     907                 :         ulong num_key;
     908                 : 
     909            1039 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
     910              31 :                 return;
     911                 :         }
     912                 : 
     913            1008 :         switch (zend_hash_get_current_key_ex(array, &string_key, &string_length, &num_key, 0, NULL)) {
     914                 :                 case HASH_KEY_IS_STRING:
     915              54 :                         RETVAL_STRINGL(string_key, string_length - 1, 1);
     916              54 :                         break;
     917                 :                 case HASH_KEY_IS_LONG:
     918             908 :                         RETVAL_LONG(num_key);
     919             908 :                         break;
     920                 :                 case HASH_KEY_NON_EXISTANT:
     921              46 :                         return;
     922                 :         }
     923                 : }
     924                 : /* }}} */
     925                 : 
     926                 : /* {{{ proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]])
     927                 :    Return the lowest value in an array or a series of arguments */
     928                 : PHP_FUNCTION(min)
     929             666 : {
     930                 :         int argc;
     931             666 :         zval ***args = NULL;
     932                 : 
     933             666 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
     934               2 :                 return;
     935                 :         }
     936                 :         
     937             664 :         php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC);
     938                 :         
     939                 :         /* mixed min ( array $values ) */
     940             664 :         if (argc == 1) {
     941                 :                 zval **result;
     942                 :                 
     943              21 :                 if (Z_TYPE_PP(args[0]) != IS_ARRAY) {
     944               4 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "When only one parameter is given, it must be an array");
     945               4 :                         RETVAL_NULL();
     946                 :                 } else {
     947              17 :                         if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) {
     948              15 :                                 RETVAL_ZVAL(*result, 1, 0);
     949                 :                         } else {
     950               2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element");
     951               2 :                                 RETVAL_FALSE;
     952                 :                         }
     953                 :                 }
     954                 :         } else {
     955                 :                 /* mixed min ( mixed $value1 , mixed $value2 [, mixed $value3... ] ) */
     956                 :                 zval **min, result;
     957                 :                 int i;
     958                 : 
     959             643 :                 min = args[0];
     960                 : 
     961            2537 :                 for (i = 1; i < argc; i++) {
     962            1894 :                         is_smaller_function(&result, *args[i], *min TSRMLS_CC);
     963            1894 :                         if (Z_LVAL(result) == 1) {
     964             590 :                                 min = args[i];
     965                 :                         }
     966                 :                 }
     967                 : 
     968             643 :                 RETVAL_ZVAL(*min, 1, 0);        
     969                 :         }
     970                 : 
     971             664 :         if (args) {
     972             664 :                 efree(args);
     973                 :         }
     974                 : }
     975                 : /* }}} */
     976                 : 
     977                 : /* {{{ proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]])
     978                 :    Return the highest value in an array or a series of arguments */
     979                 : PHP_FUNCTION(max)
     980              93 : {
     981              93 :         zval ***args = NULL;
     982                 :         int argc;
     983                 :         
     984              93 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
     985               2 :                 return;
     986                 :         }
     987                 : 
     988              91 :         php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC);
     989                 :         
     990                 :         /* mixed max ( array $values ) */
     991              91 :         if (argc == 1) {
     992                 :                 zval **result;
     993                 : 
     994              65 :                 if (Z_TYPE_PP(args[0]) != IS_ARRAY) {
     995               4 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "When only one parameter is given, it must be an array");
     996               4 :                         RETVAL_NULL();
     997                 :                 } else {
     998              61 :                         if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) {
     999              59 :                                 RETVAL_ZVAL(*result, 1, 0);
    1000                 :                         } else {
    1001               2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element");
    1002               2 :                                 RETVAL_FALSE;
    1003                 :                         }
    1004                 :                 }
    1005                 :         } else {
    1006                 :                 /* mixed max ( mixed $value1 , mixed $value2 [, mixed $value3... ] ) */
    1007                 :                 zval **max, result;
    1008                 :                 int i;
    1009                 : 
    1010              26 :                 max = args[0];
    1011                 : 
    1012            1303 :                 for (i = 1; i < argc; i++) {
    1013            1277 :                         is_smaller_or_equal_function(&result, *args[i], *max TSRMLS_CC);
    1014            1277 :                         if (Z_LVAL(result) == 0) {
    1015              40 :                                 max = args[i];
    1016                 :                         }
    1017                 :                 }
    1018                 : 
    1019              26 :                 RETVAL_ZVAL(*max, 1, 0);
    1020                 :         }
    1021                 :         
    1022              91 :         if (args) {
    1023              91 :                 efree(args);
    1024                 :         }
    1025                 : }
    1026                 : /* }}} */
    1027                 : 
    1028                 : static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive TSRMLS_DC) /* {{{ */
    1029             244 : {
    1030                 :         zval **args[3],                 /* Arguments to userland function */
    1031                 :                   *retval_ptr,          /* Return value - unused */
    1032             244 :                   *key=NULL;            /* Entry key */
    1033                 :         char  *string_key;
    1034                 :         uint   string_key_len;
    1035                 :         ulong  num_key;
    1036                 :         HashPosition pos;
    1037                 : 
    1038                 :         /* Set up known arguments */
    1039             244 :         args[1] = &key;
    1040             244 :         args[2] = userdata;
    1041                 : 
    1042             244 :         zend_hash_internal_pointer_reset_ex(target_hash, &pos);
    1043                 : 
    1044             244 :         BG(array_walk_fci).retval_ptr_ptr = &retval_ptr;
    1045             244 :         BG(array_walk_fci).param_count = userdata ? 3 : 2;
    1046             244 :         BG(array_walk_fci).params = args;
    1047             244 :         BG(array_walk_fci).no_separation = 0;
    1048                 : 
    1049                 :         /* Iterate through hash */
    1050            1309 :         while (!EG(exception) && zend_hash_get_current_data_ex(target_hash, (void **)&args[0], &pos) == SUCCESS) {
    1051             931 :                 if (recursive && Z_TYPE_PP(args[0]) == IS_ARRAY) {
    1052                 :                         HashTable *thash;
    1053                 :                         zend_fcall_info orig_array_walk_fci;
    1054                 :                         zend_fcall_info_cache orig_array_walk_fci_cache;
    1055                 : 
    1056             109 :                         SEPARATE_ZVAL_IF_NOT_REF(args[0]);
    1057             109 :                         thash = Z_ARRVAL_PP(args[0]);
    1058             109 :                         if (thash->nApplyCount > 1) {
    1059               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
    1060               0 :                                 return 0;
    1061                 :                         }
    1062                 : 
    1063                 :                         /* backup the fcall info and cache */
    1064             109 :                         orig_array_walk_fci = BG(array_walk_fci);
    1065             109 :                         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1066                 : 
    1067             109 :                         thash->nApplyCount++;
    1068             109 :                         php_array_walk(thash, userdata, recursive TSRMLS_CC);
    1069             109 :                         thash->nApplyCount--;
    1070                 : 
    1071                 :                         /* restore the fcall info and cache */
    1072             109 :                         BG(array_walk_fci) = orig_array_walk_fci;
    1073             109 :                         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1074                 :                 } else {
    1075                 :                         /* Allocate space for key */
    1076             713 :                         MAKE_STD_ZVAL(key);
    1077                 : 
    1078                 :                         /* Set up the key */
    1079             713 :                         switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, &pos)) {
    1080                 :                                 case HASH_KEY_IS_LONG:
    1081             319 :                                         Z_TYPE_P(key) = IS_LONG;
    1082             319 :                                         Z_LVAL_P(key) = num_key;
    1083             319 :                                         break;
    1084                 :                                 case HASH_KEY_IS_STRING:
    1085             394 :                                         ZVAL_STRINGL(key, string_key, string_key_len - 1, 1);
    1086                 :                                         break;
    1087                 :                         }
    1088                 : 
    1089                 :                         /* Call the userland function */
    1090             713 :                         if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
    1091             712 :                                 if (retval_ptr) {
    1092             709 :                                         zval_ptr_dtor(&retval_ptr);
    1093                 :                                 }
    1094                 :                         } else {
    1095               0 :                                 if (key) {
    1096               0 :                                         zval_ptr_dtor(&key);
    1097               0 :                                         key = NULL;
    1098                 :                                 }
    1099               0 :                                 break;
    1100                 :                         }
    1101                 :                 }
    1102                 : 
    1103             821 :                 if (key) {
    1104             712 :                         zval_ptr_dtor(&key);
    1105             712 :                         key = NULL;
    1106                 :                 }
    1107             821 :                 zend_hash_move_forward_ex(target_hash, &pos);
    1108                 :         }
    1109                 : 
    1110             243 :         return 0;
    1111                 : }
    1112                 : /* }}} */
    1113                 : 
    1114                 : /* {{{ proto bool array_walk(array input, string funcname [, mixed userdata])
    1115                 :    Apply a user function to every member of an array */
    1116                 : PHP_FUNCTION(array_walk)
    1117             192 : {
    1118                 :         HashTable *array;
    1119             192 :         zval *userdata = NULL;
    1120                 :         zend_fcall_info orig_array_walk_fci;
    1121                 :         zend_fcall_info_cache orig_array_walk_fci_cache;
    1122                 : 
    1123             192 :         orig_array_walk_fci = BG(array_walk_fci);
    1124             192 :         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1125                 : 
    1126             192 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
    1127             105 :                 BG(array_walk_fci) = orig_array_walk_fci;
    1128             105 :                 BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1129             105 :                 return;
    1130                 :         }
    1131                 : 
    1132              87 :         php_array_walk(array, userdata ? &userdata : NULL, 0 TSRMLS_CC);
    1133              86 :         BG(array_walk_fci) = orig_array_walk_fci;
    1134              86 :         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1135              86 :         RETURN_TRUE;
    1136                 : }
    1137                 : /* }}} */
    1138                 : 
    1139                 : /* {{{ proto bool array_walk_recursive(array input, string funcname [, mixed userdata])
    1140                 :    Apply a user function recursively to every member of an array */
    1141                 : PHP_FUNCTION(array_walk_recursive)
    1142             152 : {
    1143                 :         HashTable *array;
    1144             152 :         zval *userdata = NULL;
    1145                 :         zend_fcall_info orig_array_walk_fci;
    1146                 :         zend_fcall_info_cache orig_array_walk_fci_cache;
    1147                 : 
    1148             152 :         orig_array_walk_fci = BG(array_walk_fci);
    1149             152 :         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1150                 : 
    1151             152 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
    1152             104 :                 BG(array_walk_fci) = orig_array_walk_fci;
    1153             104 :                 BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1154             104 :                 return;
    1155                 :         }
    1156                 : 
    1157              48 :         php_array_walk(array, userdata ? &userdata : NULL, 1 TSRMLS_CC);
    1158              48 :         BG(array_walk_fci) = orig_array_walk_fci;
    1159              48 :         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1160              48 :         RETURN_TRUE;
    1161                 : }
    1162                 : /* }}} */
    1163                 : 
    1164                 : /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
    1165                 :  * 0 = return boolean
    1166                 :  * 1 = return key
    1167                 :  */
    1168                 : static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
    1169           31668 : {
    1170                 :         zval *value,                            /* value to check for */
    1171                 :                  *array,                                /* array to check in */
    1172                 :                  **entry,                               /* pointer to array entry */
    1173                 :                   res;                                  /* comparison result */
    1174                 :         HashPosition pos;                       /* hash iterator */
    1175           31668 :         zend_bool strict = 0;           /* strict comparison or not */
    1176                 :         ulong num_key;
    1177                 :         uint str_key_len;
    1178                 :         char *string_key;
    1179           31668 :         int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
    1180                 : 
    1181           31668 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {
    1182              16 :                 return;
    1183                 :         }
    1184                 : 
    1185           31652 :         if (strict) {
    1186             325 :                 is_equal_func = is_identical_function;
    1187                 :         }
    1188                 : 
    1189           31652 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
    1190          381937 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
    1191          325741 :                 is_equal_func(&res, value, *entry TSRMLS_CC);
    1192          325741 :                 if (Z_LVAL(res)) {
    1193            7108 :                         if (behavior == 0) {
    1194            6927 :                                 RETURN_TRUE;
    1195                 :                         } else {
    1196                 :                                 /* Return current key */
    1197             181 :                                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {
    1198                 :                                         case HASH_KEY_IS_STRING:
    1199              29 :                                                 RETURN_STRINGL(string_key, str_key_len - 1, 1);
    1200                 :                                                 break;
    1201                 :                                         case HASH_KEY_IS_LONG:
    1202             152 :                                                 RETURN_LONG(num_key);
    1203                 :                                                 break;
    1204                 :                                 }
    1205                 :                         }
    1206                 :                 }
    1207          318633 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
    1208                 :         }
    1209                 : 
    1210           24544 :         RETURN_FALSE;
    1211                 : }
    1212                 : /* }}} */
    1213                 : 
    1214                 : /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict])
    1215                 :    Checks if the given value exists in the array */
    1216                 : PHP_FUNCTION(in_array)
    1217           31156 : {
    1218           31156 :         php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1219           31156 : }
    1220                 : /* }}} */
    1221                 : 
    1222                 : /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict])
    1223                 :    Searches the array for a given value and returns the corresponding key if successful */
    1224                 : PHP_FUNCTION(array_search)
    1225             512 : {
    1226             512 :         php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1227             512 : }
    1228                 : /* }}} */
    1229                 : 
    1230                 : static int php_valid_var_name(char *var_name, int var_name_len) /* {{{ */
    1231             462 : {
    1232                 :         int i, ch;
    1233                 : 
    1234             462 :         if (!var_name || !var_name_len) {
    1235               4 :                 return 0;
    1236                 :         }
    1237                 :         
    1238                 :         /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */
    1239             458 :         ch = (int)((unsigned char *)var_name)[0];
    1240             458 :         if (var_name[0] != '_' &&
    1241                 :                 (ch < 65  /* A    */ || /* Z    */ ch > 90)  &&
    1242                 :                 (ch < 97  /* a    */ || /* z    */ ch > 122) &&
    1243                 :                 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
    1244                 :         ) {
    1245              15 :                 return 0;
    1246                 :         }
    1247                 : 
    1248                 :         /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */
    1249             443 :         if (var_name_len > 1) {
    1250            1875 :                 for (i = 1; i < var_name_len; i++) {
    1251            1491 :                         ch = (int)((unsigned char *)var_name)[i];
    1252            1491 :                         if (var_name[i] != '_' &&
    1253                 :                                 (ch < 48  /* 0    */ || /* 9    */ ch > 57)  &&
    1254                 :                                 (ch < 65  /* A    */ || /* Z    */ ch > 90)  &&
    1255                 :                                 (ch < 97  /* a    */ || /* z    */ ch > 122) &&
    1256                 :                                 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
    1257                 :                         ) {
    1258               6 :                                 return 0;
    1259                 :                         }
    1260                 :                 }
    1261                 :         }
    1262             437 :         return 1;
    1263                 : }
    1264                 : /* }}} */
    1265                 : 
    1266                 : PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, int var_name_len, zend_bool add_underscore TSRMLS_DC) /* {{{ */
    1267             322 : {
    1268             322 :         Z_STRLEN_P(result) = Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0) + var_name_len;
    1269             322 :         Z_TYPE_P(result) = IS_STRING;
    1270             322 :         Z_STRVAL_P(result) = emalloc(Z_STRLEN_P(result) + 1);
    1271             322 :         memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix));
    1272                 : 
    1273             322 :         if (add_underscore) {
    1274             237 :                 Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_';
    1275                 :         }
    1276                 : 
    1277             322 :         memcpy(Z_STRVAL_P(result) + Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1);
    1278                 : 
    1279             322 :         return SUCCESS;
    1280                 : }
    1281                 : /* }}} */
    1282                 : 
    1283                 : /* {{{ proto int extract(array var_array [, int extract_type [, string prefix]])
    1284                 :    Imports variables into symbol table from an array */
    1285                 : PHP_FUNCTION(extract)
    1286             136 : {
    1287             136 :         zval *var_array, *prefix = NULL;
    1288             136 :         long extract_type = EXTR_OVERWRITE;
    1289                 :         zval **entry, *data;
    1290                 :         char *var_name;
    1291                 :         ulong num_key;
    1292                 :         uint var_name_len;
    1293             136 :         int var_exists, key_type, count = 0;
    1294             136 :         int extract_refs = 0;
    1295                 :         HashPosition pos;
    1296                 : 
    1297             136 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) {
    1298               4 :                 return;
    1299                 :         }
    1300                 : 
    1301             132 :         extract_refs = (extract_type & EXTR_REFS);
    1302             132 :         extract_type &= 0xff;
    1303                 : 
    1304             132 :         if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
    1305               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid extract type");
    1306               2 :                 return;
    1307                 :         }
    1308                 : 
    1309             130 :         if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
    1310               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "specified extract type requires the prefix parameter");
    1311               1 :                 return;
    1312                 :         }
    1313                 : 
    1314             129 :         if (prefix) {
    1315              63 :                 convert_to_string(prefix);
    1316              63 :                 if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
    1317               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "prefix is not a valid identifier");
    1318               0 :                         return;
    1319                 :                 }
    1320                 :         }
    1321                 : 
    1322             129 :         if (!EG(active_symbol_table)) {
    1323              12 :                 zend_rebuild_symbol_table(TSRMLS_C);
    1324                 :         }
    1325                 : 
    1326                 :         /* var_array is passed by ref for the needs of EXTR_REFS (needs to
    1327                 :          * work on the original array to create refs to its members)
    1328                 :          * simulate pass_by_value if EXTR_REFS is not used */
    1329             129 :         if (!extract_refs) {
    1330             113 :                 SEPARATE_ARG_IF_REF(var_array);
    1331                 :         }
    1332                 : 
    1333             129 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
    1334             987 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&entry, &pos) == SUCCESS) {
    1335                 :                 zval final_name;
    1336                 : 
    1337             729 :                 ZVAL_NULL(&final_name);
    1338                 : 
    1339             729 :                 key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &var_name, &var_name_len, &num_key, 0, &pos);
    1340             729 :                 var_exists = 0;
    1341                 : 
    1342             729 :                 if (key_type == HASH_KEY_IS_STRING) {
    1343             250 :                         var_name_len--;
    1344             250 :                         var_exists = zend_hash_exists(EG(active_symbol_table), var_name, var_name_len + 1);
    1345             650 :                 } else if (key_type == HASH_KEY_IS_LONG && (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID)) {
    1346                 :                         zval num;
    1347                 : 
    1348             171 :                         ZVAL_LONG(&num, num_key);
    1349             171 :                         convert_to_string(&num);
    1350             171 :                         php_prefix_varname(&final_name, prefix, Z_STRVAL(num), Z_STRLEN(num), 1 TSRMLS_CC);
    1351             171 :                         zval_dtor(&num);
    1352                 :                 } else {
    1353             308 :                         zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
    1354             308 :                         continue;
    1355                 :                 }
    1356                 : 
    1357             421 :                 switch (extract_type) {
    1358                 :                         case EXTR_IF_EXISTS:
    1359              15 :                                 if (!var_exists) break;
    1360                 :                                 /* break omitted intentionally */
    1361                 : 
    1362                 :                         case EXTR_OVERWRITE:
    1363                 :                                 /* GLOBALS protection */
    1364             140 :                                 if (var_exists && var_name_len == sizeof("GLOBALS") && !strcmp(var_name, "GLOBALS")) {
    1365               0 :                                         break;
    1366                 :                                 }
    1367             140 :                                 ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
    1368             140 :                                 break;
    1369                 : 
    1370                 :                         case EXTR_PREFIX_IF_EXISTS:
    1371              15 :                                 if (var_exists) {
    1372              11 :                                         php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
    1373                 :                                 }
    1374              15 :                                 break;
    1375                 : 
    1376                 :                         case EXTR_PREFIX_SAME:
    1377              17 :                                 if (!var_exists && var_name_len != 0) {
    1378               3 :                                         ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
    1379                 :                                 }
    1380                 :                                 /* break omitted intentionally */
    1381                 : 
    1382                 :                         case EXTR_PREFIX_ALL:
    1383             181 :                                 if (Z_TYPE(final_name) == IS_NULL && var_name_len != 0) {
    1384              51 :                                         php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
    1385                 :                                 }
    1386             181 :                                 break;
    1387                 : 
    1388                 :                         case EXTR_PREFIX_INVALID:
    1389              66 :                                 if (Z_TYPE(final_name) == IS_NULL) {
    1390              15 :                                         if (!php_valid_var_name(var_name, var_name_len)) {
    1391               4 :                                                 php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
    1392                 :                                         } else {
    1393              11 :                                                 ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
    1394                 :                                         }
    1395                 :                                 }
    1396              66 :                                 break;
    1397                 : 
    1398                 :                         default:
    1399              15 :                                 if (!var_exists) {
    1400               4 :                                         ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
    1401                 :                                 }
    1402                 :                                 break;
    1403                 :                 }
    1404                 : 
    1405             421 :                 if (Z_TYPE(final_name) != IS_NULL && php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
    1406             374 :                         if (extract_refs) {
    1407                 :                                 zval **orig_var;
    1408                 : 
    1409              88 :                                 SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);
    1410              88 :                                 zval_add_ref(entry);
    1411                 : 
    1412              88 :                                 if (zend_hash_find(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void **) &orig_var) == SUCCESS) {
    1413              42 :                                         zval_ptr_dtor(orig_var);
    1414              42 :                                         *orig_var = *entry;
    1415                 :                                 } else {
    1416              46 :                                         zend_hash_update(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void **) entry, sizeof(zval *), NULL);
    1417                 :                                 }
    1418                 :                         } else {
    1419             286 :                                 MAKE_STD_ZVAL(data);
    1420             286 :                                 *data = **entry;
    1421             286 :                                 zval_copy_ctor(data);
    1422                 : 
    1423             286 :                                 ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, data, 1, 0);
    1424                 :                         }
    1425             374 :                         count++;
    1426                 :                 }
    1427             421 :                 zval_dtor(&final_name);
    1428                 : 
    1429             421 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
    1430                 :         }
    1431                 : 
    1432             129 :         if (!extract_refs) {
    1433             113 :                 zval_ptr_dtor(&var_array);
    1434                 :         }
    1435                 : 
    1436             129 :         RETURN_LONG(count);
    1437                 : }
    1438                 : /* }}} */
    1439                 : 
    1440                 : static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry TSRMLS_DC) /* {{{ */
    1441              76 : {
    1442                 :         zval **value_ptr, *value, *data;
    1443                 : 
    1444              76 :         if (Z_TYPE_P(entry) == IS_STRING) {
    1445              35 :                 if (zend_hash_find(eg_active_symbol_table, Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, (void **)&value_ptr) != FAILURE) {
    1446              31 :                         value = *value_ptr;
    1447              31 :                         ALLOC_ZVAL(data);
    1448              31 :                         *data = *value;
    1449              31 :                         zval_copy_ctor(data);
    1450              31 :                         INIT_PZVAL(data);
    1451                 : 
    1452              31 :                         zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, &data, sizeof(zval *), NULL);
    1453                 :                 }
    1454                 :         }
    1455              41 :         else if (Z_TYPE_P(entry) == IS_ARRAY) {
    1456                 :                 HashPosition pos;
    1457                 : 
    1458              30 :                 if ((Z_ARRVAL_P(entry)->nApplyCount > 1)) {
    1459               5 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
    1460               5 :                         return;
    1461                 :                 }
    1462                 : 
    1463              25 :                 Z_ARRVAL_P(entry)->nApplyCount++;
    1464                 : 
    1465              25 :                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos);
    1466             102 :                 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), (void**)&value_ptr, &pos) == SUCCESS) {
    1467              52 :                         value = *value_ptr;
    1468                 : 
    1469              52 :                         php_compact_var(eg_active_symbol_table, return_value, value TSRMLS_CC);
    1470              52 :                         zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos);
    1471                 :                 }
    1472              25 :                 Z_ARRVAL_P(entry)->nApplyCount--;
    1473                 :         }
    1474                 : }
    1475                 : /* }}} */
    1476                 : 
    1477                 : /* {{{ proto array compact(mixed var_names [, mixed ...])
    1478                 :    Creates a hash containing variables and their values */
    1479                 : PHP_FUNCTION(compact)
    1480              13 : {
    1481              13 :         zval ***args = NULL;    /* function arguments array */
    1482                 :         int num_args, i;
    1483                 : 
    1484              13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
    1485               1 :                 return;
    1486                 :         }
    1487                 : 
    1488              12 :         if (!EG(active_symbol_table)) {
    1489               1 :                 zend_rebuild_symbol_table(TSRMLS_C);
    1490                 :         }
    1491                 : 
    1492                 :         /* compact() is probably most used with a single array of var_names
    1493                 :            or multiple string names, rather than a combination of both.
    1494                 :            So quickly guess a minimum result size based on that */
    1495              20 :         if (ZEND_NUM_ARGS() == 1 && Z_TYPE_PP(args[0]) == IS_ARRAY) {
    1496               8 :                 array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_PP(args[0])));
    1497                 :         } else {
    1498               4 :                 array_init_size(return_value, ZEND_NUM_ARGS());
    1499                 :         }
    1500                 : 
    1501              36 :         for (i=0; i<ZEND_NUM_ARGS(); i++) {
    1502              24 :                 php_compact_var(EG(active_symbol_table), return_value, *args[i] TSRMLS_CC);
    1503                 :         }
    1504                 : 
    1505              12 :         if (args) {
    1506              12 :                 efree(args);
    1507                 :         }
    1508                 : }
    1509                 : /* }}} */
    1510                 : 
    1511                 : /* {{{ proto array array_fill(int start_key, int num, mixed val)
    1512                 :    Create an array containing num elements starting with index start_key each initialized to val */
    1513                 : PHP_FUNCTION(array_fill)
    1514             158 : {
    1515                 :         zval *val;
    1516                 :         long start_key, num;
    1517                 : 
    1518             158 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz", &start_key, &num, &val) == FAILURE) {
    1519              24 :                 return;
    1520                 :         }
    1521                 : 
    1522             134 :         if (num < 1) {
    1523              29 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements must be positive");
    1524              29 :                 RETURN_FALSE;
    1525                 :         }
    1526                 : 
    1527                 :         /* allocate an array for return */
    1528             105 :         array_init_size(return_value, num);
    1529                 : 
    1530             105 :         num--;
    1531             105 :         zval_add_ref(&val);
    1532             105 :         zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL);
    1533                 : 
    1534             297 :         while (num--) {
    1535              87 :                 zval_add_ref(&val);
    1536              87 :                 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL);
    1537                 :         }
    1538                 : }
    1539                 : /* }}} */
    1540                 : 
    1541                 : /* {{{ proto array array_fill_keys(array keys, mixed val)
    1542                 :    Create an array using the elements of the first parameter as keys each initialized to val */
    1543                 : PHP_FUNCTION(array_fill_keys)
    1544              24 : {
    1545                 :         zval *keys, *val, **entry;
    1546                 :         HashPosition pos;
    1547                 : 
    1548              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &keys, &val) == FAILURE) {
    1549               6 :                 return;
    1550                 :         }
    1551                 : 
    1552                 :         /* Initialize return array */
    1553              18 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
    1554                 : 
    1555              18 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
    1556              76 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry, &pos) == SUCCESS) {
    1557                 : 
    1558              40 :                 if (Z_TYPE_PP(entry) == IS_LONG) {
    1559               8 :                         zval_add_ref(&val);
    1560               8 :                         zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &val, sizeof(zval *), NULL);
    1561                 :                 } else {
    1562              32 :                         zval key, *key_ptr = *entry;
    1563                 : 
    1564              32 :                         if (Z_TYPE_PP(entry) != IS_STRING) {
    1565               7 :                                 key = **entry;
    1566               7 :                                 zval_copy_ctor(&key);
    1567               7 :                                 convert_to_string(&key);
    1568               7 :                                 key_ptr = &key;
    1569                 :                         }
    1570                 : 
    1571              32 :                         zval_add_ref(&val);
    1572              32 :                         zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(key_ptr), Z_STRLEN_P(key_ptr) + 1, &val, sizeof(zval *), NULL);
    1573                 : 
    1574              32 :                         if (key_ptr != *entry) {
    1575               7 :                                 zval_dtor(&key);
    1576                 :                         }
    1577                 :                 }
    1578                 : 
    1579              40 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
    1580                 :         }
    1581                 : }
    1582                 : /* }}} */
    1583                 : 
    1584                 : /* {{{ proto array range(mixed low, mixed high[, int step])
    1585                 :    Create an array containing the range of integers or characters from low to high (inclusive) */
    1586                 : PHP_FUNCTION(range)
    1587           90187 : {
    1588           90187 :         zval *zlow, *zhigh, *zstep = NULL;
    1589           90187 :         int err = 0, is_step_double = 0;
    1590           90187 :         double step = 1.0;
    1591                 : 
    1592           90187 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/|z/", &zlow, &zhigh, &zstep) == FAILURE) {
    1593               3 :                 RETURN_FALSE;
    1594                 :         }
    1595                 : 
    1596           90184 :         if (zstep) {
    1597              30 :                 if (Z_TYPE_P(zstep) == IS_DOUBLE ||
    1598                 :                         (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)
    1599                 :                 ) {
    1600               6 :                         is_step_double = 1;
    1601                 :                 }
    1602                 : 
    1603              30 :                 convert_to_double_ex(&zstep);
    1604              30 :                 step = Z_DVAL_P(zstep);
    1605                 : 
    1606                 :                 /* We only want positive step values. */
    1607              30 :                 if (step < 0.0) {
    1608               0 :                         step *= -1;
    1609                 :                 }
    1610                 :         }
    1611                 : 
    1612                 :         /* Initialize the return_value as an array. */
    1613           90184 :         array_init(return_value);
    1614                 : 
    1615                 :         /* If the range is given as strings, generate an array of characters. */
    1616           90191 :         if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) {
    1617                 :                 int type1, type2;
    1618                 :                 unsigned char *low, *high;
    1619              18 :                 long lstep = (long) step;
    1620                 : 
    1621              18 :                 type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0);
    1622              18 :                 type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0);
    1623                 : 
    1624              18 :                 if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) {
    1625                 :                         goto double_str;
    1626              15 :                 } else if (type1 == IS_LONG || type2 == IS_LONG) {
    1627                 :                         goto long_str;
    1628                 :                 }
    1629                 : 
    1630              10 :                 convert_to_string(zlow);
    1631              10 :                 convert_to_string(zhigh);
    1632              10 :                 low = (unsigned char *)Z_STRVAL_P(zlow);
    1633              10 :                 high = (unsigned char *)Z_STRVAL_P(zhigh);
    1634                 : 
    1635              10 :                 if (*low > *high) {          /* Negative Steps */
    1636               2 :                         if (lstep <= 0) {
    1637               1 :                                 err = 1;
    1638               1 :                                 goto err;
    1639                 :                         }
    1640              27 :                         for (; *low >= *high; (*low) -= (unsigned int)lstep) {
    1641              26 :                                 add_next_index_stringl(return_value, (const char *)low, 1, 1);
    1642              26 :                                 if (((signed int)*low - lstep) < 0) {
    1643               0 :                                         break;
    1644                 :                                 }
    1645                 :                         }
    1646               8 :                 } else if (*high > *low) {   /* Positive Steps */
    1647               6 :                         if (lstep <= 0) {
    1648               2 :                                 err = 1;
    1649               2 :                                 goto err;
    1650                 :                         }
    1651              76 :                         for (; *low <= *high; (*low) += (unsigned int)lstep) {
    1652              72 :                                 add_next_index_stringl(return_value, (const char *)low, 1, 1);
    1653              72 :                                 if (((signed int)*low + lstep) > 255) {
    1654               0 :                                         break;
    1655                 :                                 }
    1656                 :                         }
    1657                 :                 } else {
    1658               2 :                         add_next_index_stringl(return_value, (const char *)low, 1, 1);
    1659                 :                 }
    1660                 : 
    1661           90195 :         } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
    1662                 :                 double low, high;
    1663              31 : double_str:
    1664              31 :                 convert_to_double(zlow);
    1665              31 :                 convert_to_double(zhigh);
    1666              31 :                 low = Z_DVAL_P(zlow);
    1667              31 :                 high = Z_DVAL_P(zhigh);
    1668                 : 
    1669              31 :                 if (low > high) {            /* Negative steps */
    1670              13 :                         if (low - high < step || step <= 0) {
    1671               1 :                                 err = 1;
    1672               1 :                                 goto err;
    1673                 :                         }
    1674             116 :                         for (; low >= (high - DOUBLE_DRIFT_FIX); low -= step) {
    1675             104 :                                 add_next_index_double(return_value, low);
    1676                 :                         }
    1677              18 :                 } else if (high > low) {     /* Positive steps */
    1678              17 :                         if (high - low < step || step <= 0) {
    1679               1 :                                 err = 1;
    1680               1 :                                 goto err;
    1681                 :                         }
    1682             152 :                         for (; low <= (high + DOUBLE_DRIFT_FIX); low += step) {
    1683             136 :                                 add_next_index_double(return_value, low);
    1684                 :                         }
    1685                 :                 } else {
    1686               1 :                         add_next_index_double(return_value, low);
    1687                 :                 }
    1688                 :         } else {
    1689                 :                 double low, high;
    1690                 :                 long lstep;
    1691           90143 : long_str:
    1692           90143 :                 convert_to_double(zlow);
    1693           90143 :                 convert_to_double(zhigh);
    1694           90143 :                 low = Z_DVAL_P(zlow);
    1695           90143 :                 high = Z_DVAL_P(zhigh);
    1696           90143 :                 lstep = (long) step;
    1697                 : 
    1698           90143 :                 if (low > high) {            /* Negative steps */
    1699              16 :                         if (low - high < lstep || lstep <= 0) {
    1700               2 :                                 err = 1;
    1701               2 :                                 goto err;
    1702                 :                         }
    1703              77 :                         for (; low >= high; low -= lstep) {
    1704              63 :                                 add_next_index_long(return_value, (long)low);
    1705                 :                         }
    1706           90127 :                 } else if (high > low) {     /* Positive steps */
    1707           90106 :                         if (high - low < lstep || lstep <= 0) {
    1708               6 :                                 err = 1;
    1709               6 :                                 goto err;
    1710                 :                         }
    1711          460810 :                         for (; low <= high; low += lstep) {
    1712          370710 :                                 add_next_index_long(return_value, (long)low);
    1713                 :                         }
    1714                 :                 } else {
    1715              21 :                         add_next_index_long(return_value, (long)low);
    1716                 :                 }
    1717                 :         }
    1718           90184 : err:
    1719           90184 :         if (err) {
    1720              13 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range");
    1721              13 :                 zval_dtor(return_value);
    1722              13 :                 RETURN_FALSE;
    1723                 :         }
    1724                 : }
    1725                 : /* }}} */
    1726                 : 
    1727                 : static void php_array_data_shuffle(zval *array TSRMLS_DC) /* {{{ */
    1728           90047 : {
    1729                 :         Bucket **elems, *temp;
    1730                 :         HashTable *hash;
    1731                 :         int j, n_elems, rnd_idx, n_left;
    1732                 : 
    1733           90047 :         n_elems = zend_hash_num_elements(Z_ARRVAL_P(array));
    1734                 : 
    1735           90047 :         if (n_elems < 1) {
    1736               1 :                 return;
    1737                 :         }
    1738                 : 
    1739           90046 :         elems = (Bucket **)safe_emalloc(n_elems, sizeof(Bucket *), 0);
    1740           90046 :         hash = Z_ARRVAL_P(array);
    1741           90046 :         n_left = n_elems;
    1742                 : 
    1743          451225 :         for (j = 0, temp = hash->pListHead; temp; temp = temp->pListNext)
    1744          361179 :                 elems[j++] = temp;
    1745          451225 :         while (--n_left) {
    1746          271133 :                 rnd_idx = php_rand(TSRMLS_C);
    1747          271133 :                 RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    1748          271133 :                 if (rnd_idx != n_left) {
    1749          173463 :                         temp = elems[n_left];
    1750          173463 :                         elems[n_left] = elems[rnd_idx];
    1751          173463 :                         elems[rnd_idx] = temp;
    1752                 :                 }
    1753                 :         }
    1754                 : 
    1755           90046 :         HANDLE_BLOCK_INTERRUPTIONS();
    1756           90046 :         hash->pListHead = elems[0];
    1757           90046 :         hash->pListTail = NULL;
    1758           90046 :         hash->pInternalPointer = hash->pListHead;
    1759                 : 
    1760          451225 :         for (j = 0; j < n_elems; j++) {
    1761          361179 :                 if (hash->pListTail) {
    1762          271133 :                         hash->pListTail->pListNext = elems[j];
    1763                 :                 }
    1764          361179 :                 elems[j]->pListLast = hash->pListTail;
    1765          361179 :                 elems[j]->pListNext = NULL;
    1766          361179 :                 hash->pListTail = elems[j];
    1767                 :         }
    1768           90046 :         temp = hash->pListHead;
    1769           90046 :         j = 0;
    1770          541271 :         while (temp != NULL) {
    1771          361179 :                 temp->nKeyLength = 0;
    1772          361179 :                 temp->h = j++;
    1773          361179 :                 temp = temp->pListNext;
    1774                 :         }
    1775           90046 :         hash->nNextFreeElement = n_elems;
    1776           90046 :         zend_hash_rehash(hash);
    1777           90046 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1778                 : 
    1779           90046 :         efree(elems);
    1780                 : }
    1781                 : /* }}} */
    1782                 : 
    1783                 : /* {{{ proto bool shuffle(array array_arg)
    1784                 :    Randomly shuffle the contents of an array */
    1785                 : PHP_FUNCTION(shuffle)
    1786           90072 : {
    1787                 :         zval *array;
    1788                 : 
    1789           90072 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
    1790              25 :                 RETURN_FALSE;
    1791                 :         }
    1792                 : 
    1793           90047 :         php_array_data_shuffle(array TSRMLS_CC);
    1794                 : 
    1795           90047 :         RETURN_TRUE;
    1796                 : }
    1797                 : /* }}} */
    1798                 : 
    1799                 : PHPAPI HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, int list_count, HashTable **removed) /* {{{ */
    1800             429 : {
    1801             429 :         HashTable       *out_hash = NULL;       /* Output hashtable */
    1802                 :         int                      num_in,                        /* Number of entries in the input hashtable */
    1803                 :                                  pos,                           /* Current position in the hashtable */
    1804                 :                                  i;                                     /* Loop counter */
    1805                 :         Bucket          *p;                                     /* Pointer to hash bucket */
    1806                 :         zval            *entry;                         /* Hash entry */
    1807                 : 
    1808                 :         /* If input hash doesn't exist, we have nothing to do */
    1809             429 :         if (!in_hash) {
    1810               0 :                 return NULL;
    1811                 :         }
    1812                 : 
    1813                 :         /* Get number of entries in the input hash */
    1814             429 :         num_in = zend_hash_num_elements(in_hash);
    1815                 : 
    1816                 :         /* Clamp the offset.. */
    1817             429 :         if (offset > num_in) {
    1818               0 :                 offset = num_in;
    1819             429 :         } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    1820               0 :                 offset = 0;
    1821                 :         }
    1822                 : 
    1823                 :         /* ..and the length */
    1824             429 :         if (length < 0) {
    1825              15 :                 length = num_in - offset + length;
    1826             414 :         } else if (((unsigned)offset + (unsigned)length) > (unsigned)num_in) {
    1827              10 :                 length = num_in - offset;
    1828                 :         }
    1829                 : 
    1830                 :         /* Create and initialize output hash */
    1831             429 :         ALLOC_HASHTABLE(out_hash);
    1832             429 :         zend_hash_init(out_hash, (length > 0 ? num_in - length : 0) + list_count, NULL, ZVAL_PTR_DTOR, 0);
    1833                 : 
    1834                 :         /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */
    1835             658 :         for (pos = 0, p = in_hash->pListHead; pos < offset && p ; pos++, p = p->pListNext) {
    1836                 :                 /* Get entry and increase reference count */
    1837             229 :                 entry = *((zval **)p->pData);
    1838             229 :                 Z_ADDREF_P(entry);
    1839                 : 
    1840                 :                 /* Update output hash depending on key type */
    1841             229 :                 if (p->nKeyLength == 0) {
    1842             206 :                         zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL);
    1843                 :                 } else {
    1844              23 :                         zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL);
    1845                 :                 }
    1846                 :         }
    1847                 : 
    1848                 :         /* If hash for removed entries exists, go until offset+length and copy the entries to it */
    1849             429 :         if (removed != NULL) {
    1850             145 :                 for ( ; pos < offset + length && p; pos++, p = p->pListNext) {
    1851              93 :                         entry = *((zval **)p->pData);
    1852              93 :                         Z_ADDREF_P(entry);
    1853              93 :                         if (p->nKeyLength == 0) {
    1854              92 :                                 zend_hash_next_index_insert(*removed, &entry, sizeof(zval *), NULL);
    1855                 :                         } else {
    1856               1 :                                 zend_hash_quick_update(*removed, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL);
    1857                 :                         }
    1858                 :                 }
    1859                 :         } else { /* otherwise just skip those entries */
    1860             377 :                 for ( ; pos < offset + length && p; pos++, p = p->pListNext);
    1861                 :         }
    1862                 : 
    1863                 :         /* If there are entries to insert.. */
    1864             429 :         if (list != NULL) {
    1865                 :                 /* ..for each one, create a new zval, copy entry into it and copy it into the output hash */
    1866            1200 :                 for (i = 0; i < list_count; i++) {
    1867             799 :                         entry = *list[i];
    1868             799 :                         Z_ADDREF_P(entry);
    1869             799 :                         zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL);
    1870                 :                 }
    1871                 :         }
    1872                 : 
    1873                 :         /* Copy the remaining input hash entries to the output hash */
    1874            1654 :         for ( ; p ; p = p->pListNext) {
    1875            1225 :                 entry = *((zval **)p->pData);
    1876            1225 :                 Z_ADDREF_P(entry);
    1877            1225 :                 if (p->nKeyLength == 0) {
    1878             892 :                         zend_hash_next_index_insert(out_hash, &entry, sizeof(zval *), NULL);
    1879                 :                 } else {
    1880             333 :                         zend_hash_quick_update(out_hash, p->arKey, p->nKeyLength, p->h, &entry, sizeof(zval *), NULL);
    1881                 :                 }
    1882                 :         }
    1883                 : 
    1884             429 :         zend_hash_internal_pointer_reset(out_hash);
    1885             429 :         return out_hash;
    1886                 : }
    1887                 : /* }}} */
    1888                 : 
    1889                 : /* {{{ proto int array_push(array stack, mixed var [, mixed ...])
    1890                 :    Pushes elements onto the end of the array */
    1891                 : PHP_FUNCTION(array_push)
    1892             191 : {
    1893                 :         zval ***args,           /* Function arguments array */
    1894                 :                    *stack,              /* Input array */
    1895                 :                    *new_var;    /* Variable to be pushed */
    1896                 :         int i,                          /* Loop counter */
    1897                 :                 argc;                   /* Number of function arguments */
    1898                 : 
    1899                 : 
    1900             191 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
    1901              28 :                 return;
    1902                 :         }
    1903                 : 
    1904                 :         /* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */
    1905             346 :         for (i = 0; i < argc; i++) {
    1906             184 :                 new_var = *args[i];
    1907             184 :                 Z_ADDREF_P(new_var);
    1908                 : 
    1909             184 :                 if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var, sizeof(zval *), NULL) == FAILURE) {
    1910               1 :                         Z_DELREF_P(new_var);
    1911               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to the array as the next element is already occupied");
    1912               1 :                         efree(args);
    1913               1 :                         RETURN_FALSE;
    1914                 :                 }
    1915                 :         }
    1916                 : 
    1917                 :         /* Clean up and return the number of values in the stack */
    1918             162 :         efree(args);
    1919             162 :         RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
    1920                 : }
    1921                 : /* }}} */
    1922                 : 
    1923                 : /* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) */
    1924                 : static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
    1925             278 : {
    1926                 :         zval *stack,    /* Input stack */
    1927                 :                  **val;         /* Value to be popped */
    1928             278 :         char *key = NULL;
    1929             278 :         uint key_len = 0;
    1930                 :         ulong index;
    1931                 : 
    1932             278 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &stack) == FAILURE) {
    1933              34 :                 return;
    1934                 :         }
    1935                 : 
    1936             244 :         if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
    1937               5 :                 return;
    1938                 :         }
    1939                 : 
    1940                 :         /* Get the first or last value and copy it into the return value */
    1941             239 :         if (off_the_end) {
    1942              70 :                 zend_hash_internal_pointer_end(Z_ARRVAL_P(stack));
    1943                 :         } else {
    1944             169 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
    1945                 :         }
    1946             239 :         zend_hash_get_current_data(Z_ARRVAL_P(stack), (void **)&val);
    1947             239 :         RETVAL_ZVAL(*val, 1, 0);
    1948                 : 
    1949                 :         /* Delete the first or last value */
    1950             239 :         zend_hash_get_current_key_ex(Z_ARRVAL_P(stack), &key, &key_len, &index, 0, NULL);
    1951             243 :         if (key && Z_ARRVAL_P(stack) == &EG(symbol_table)) {
    1952               4 :                 zend_delete_global_variable(key, key_len - 1 TSRMLS_CC);
    1953                 :         } else {
    1954             235 :                 zend_hash_del_key_or_index(Z_ARRVAL_P(stack), key, key_len, index, (key) ? HASH_DEL_KEY : HASH_DEL_INDEX);
    1955                 :         }
    1956                 : 
    1957                 :         /* If we did a shift... re-index like it did before */
    1958             239 :         if (!off_the_end) {
    1959             169 :                 unsigned int k = 0;
    1960             169 :                 int should_rehash = 0;
    1961             169 :                 Bucket *p = Z_ARRVAL_P(stack)->pListHead;
    1962             714 :                 while (p != NULL) {
    1963             376 :                         if (p->nKeyLength == 0) {
    1964             343 :                                 if (p->h != k) {
    1965             336 :                                         p->h = k++;
    1966             336 :                                         should_rehash = 1;
    1967                 :                                 } else {
    1968               7 :                                         k++;
    1969                 :                                 }
    1970                 :                         }
    1971             376 :                         p = p->pListNext;
    1972                 :                 }
    1973             169 :                 Z_ARRVAL_P(stack)->nNextFreeElement = k;
    1974             169 :                 if (should_rehash) {
    1975             129 :                         zend_hash_rehash(Z_ARRVAL_P(stack));
    1976                 :                 }
    1977              70 :         } else if (!key_len && index >= Z_ARRVAL_P(stack)->nNextFreeElement - 1) {
    1978              60 :                 Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
    1979                 :         }
    1980                 : 
    1981             239 :         zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
    1982                 : }
    1983                 : /* }}} */
    1984                 : 
    1985                 : /* {{{ proto mixed array_pop(array stack)
    1986                 :    Pops an element off the end of the array */
    1987                 : PHP_FUNCTION(array_pop)
    1988              76 : {
    1989              76 :         _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1990              76 : }
    1991                 : /* }}} */
    1992                 : 
    1993                 : /* {{{ proto mixed array_shift(array stack)
    1994                 :    Pops an element off the beginning of the array */
    1995                 : PHP_FUNCTION(array_shift)
    1996             202 : {
    1997             202 :         _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1998             202 : }
    1999                 : /* }}} */
    2000                 : 
    2001                 : /* {{{ proto int array_unshift(array stack, mixed var [, mixed ...])
    2002                 :    Pushes elements onto the beginning of the array */
    2003                 : PHP_FUNCTION(array_unshift)
    2004             309 : {
    2005                 :         zval ***args,                   /* Function arguments array */
    2006                 :                    *stack;                      /* Input stack */
    2007                 :         HashTable *new_hash;    /* New hashtable for the stack */
    2008                 :         HashTable  old_hash;
    2009                 :         int argc;                               /* Number of function arguments */
    2010                 :         
    2011             309 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
    2012              51 :                 return;
    2013                 :         }
    2014                 : 
    2015                 :         /* Use splice to insert the elements at the beginning. Destroy old
    2016                 :          * hashtable and replace it with new one */
    2017             258 :         new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[0], argc, NULL);
    2018             258 :         old_hash = *Z_ARRVAL_P(stack);
    2019             258 :         if (Z_ARRVAL_P(stack) == &EG(symbol_table)) {
    2020               0 :                 zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
    2021                 :         }
    2022             258 :         *Z_ARRVAL_P(stack) = *new_hash;
    2023             258 :         FREE_HASHTABLE(new_hash);
    2024             258 :         zend_hash_destroy(&old_hash);
    2025                 : 
    2026                 :         /* Clean up and return the number of elements in the stack */
    2027             258 :         efree(args);
    2028             258 :         RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
    2029                 : }
    2030                 : /* }}} */
    2031                 : 
    2032                 : /* {{{ proto array array_splice(array input, int offset [, int length [, array replacement]])
    2033                 :    Removes the elements designated by offset and length and replace them with supplied array */
    2034                 : PHP_FUNCTION(array_splice)
    2035              62 : {
    2036                 :         zval *array,                            /* Input array */
    2037              62 :                  *repl_array = NULL,    /* Replacement array */
    2038              62 :                  ***repl = NULL;                /* Replacement elements */
    2039              62 :         HashTable *new_hash = NULL,     /* Output array's hash */
    2040              62 :                  **rem_hash = NULL;     /* Removed elements' hash */
    2041                 :         HashTable  old_hash;
    2042                 :         Bucket *p;                                      /* Bucket used for traversing hash */
    2043                 :         long    i,
    2044                 :                         offset,
    2045              62 :                         length = 0,
    2046              62 :                         repl_num = 0;           /* Number of replacement elements */
    2047                 :         int             num_in;                         /* Number of elements in the input array */
    2048                 : 
    2049              62 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|lz/", &array, &offset, &length, &repl_array) == FAILURE) {
    2050               6 :                 return;
    2051                 :         }
    2052                 : 
    2053              56 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
    2054                 : 
    2055              56 :         if (ZEND_NUM_ARGS() < 3) {
    2056               1 :                 length = num_in;
    2057                 :         }
    2058                 : 
    2059              56 :         if (ZEND_NUM_ARGS() == 4) {
    2060                 :                 /* Make sure the last argument, if passed, is an array */
    2061              28 :                 convert_to_array(repl_array);
    2062                 : 
    2063                 :                 /* Create the array of replacement elements */
    2064              28 :                 repl_num = zend_hash_num_elements(Z_ARRVAL_P(repl_array));
    2065              28 :                 repl = (zval ***)safe_emalloc(repl_num, sizeof(zval **), 0);
    2066              96 :                 for (p = Z_ARRVAL_P(repl_array)->pListHead, i = 0; p; p = p->pListNext, i++) {
    2067              68 :                         repl[i] = ((zval **)p->pData);
    2068                 :                 }
    2069                 :         }
    2070                 : 
    2071                 :         /* Don't create the array of removed elements if it's not going
    2072                 :          * to be used; e.g. only removing and/or replacing elements */
    2073              56 :         if (return_value_used) {
    2074              52 :                 int size = length;
    2075                 : 
    2076                 :                 /* Clamp the offset.. */
    2077              52 :                 if (offset > num_in) {
    2078               0 :                         offset = num_in;
    2079              52 :                 } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    2080               0 :                         offset = 0;
    2081                 :                 }
    2082                 : 
    2083                 :                 /* ..and the length */
    2084              52 :                 if (length < 0) {
    2085              15 :                         size = num_in - offset + length;
    2086              37 :                 } else if (((unsigned long) offset + (unsigned long) length) > (unsigned) num_in) {
    2087              10 :                         size = num_in - offset;
    2088                 :                 }
    2089                 : 
    2090                 :                 /* Initialize return value */
    2091              52 :                 array_init_size(return_value, size > 0 ? size : 0);
    2092              52 :                 rem_hash = &Z_ARRVAL_P(return_value);
    2093                 :         }
    2094                 : 
    2095                 :         /* Perform splice */
    2096              56 :         new_hash = php_splice(Z_ARRVAL_P(array), offset, length, repl, repl_num, rem_hash);
    2097                 : 
    2098                 :         /* Replace input array's hashtable with the new one */
    2099              56 :         old_hash = *Z_ARRVAL_P(array);
    2100              56 :         if (Z_ARRVAL_P(array) == &EG(symbol_table)) {
    2101               1 :                 zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
    2102                 :         }
    2103              56 :         *Z_ARRVAL_P(array) = *new_hash;
    2104              56 :         FREE_HASHTABLE(new_hash);
    2105              56 :         zend_hash_destroy(&old_hash);
    2106                 : 
    2107                 :         /* Clean up */
    2108              56 :         if (ZEND_NUM_ARGS() == 4) {
    2109              28 :                 efree(repl);
    2110                 :         }
    2111                 : }
    2112                 : /* }}} */
    2113                 : 
    2114                 : /* {{{ proto array array_slice(array input, int offset [, int length [, bool preserve_keys]])
    2115                 :    Returns elements specified by offset and length */
    2116                 : PHP_FUNCTION(array_slice)
    2117             377 : {
    2118                 :         zval     *input,                /* Input array */
    2119             377 :                         **z_length = NULL, /* How many elements to get */ 
    2120                 :                         **entry;                /* An array entry */
    2121                 :         long     offset,                /* Offset to get elements from */
    2122             377 :                          length = 0;    
    2123             377 :         zend_bool preserve_keys = 0; /* Whether to preserve keys while copying to the new array or not */
    2124                 :         int              num_in,                /* Number of elements in the input array */
    2125                 :                          pos;                   /* Current position in the array */
    2126                 :         char *string_key;
    2127                 :         uint string_key_len;
    2128                 :         ulong num_key;
    2129                 :         HashPosition hpos;
    2130                 : 
    2131             377 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|Zb", &input, &offset, &z_length, &preserve_keys) == FAILURE) {
    2132              39 :                 return;
    2133                 :         }
    2134                 : 
    2135                 :         /* Get number of entries in the input hash */
    2136             338 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
    2137                 : 
    2138                 :         /* We want all entries from offset to the end if length is not passed or is null */
    2139             414 :         if (ZEND_NUM_ARGS() < 3 || Z_TYPE_PP(z_length) == IS_NULL) {
    2140              76 :                 length = num_in;
    2141                 :         } else {
    2142             262 :                 convert_to_long_ex(z_length);
    2143             262 :                 length = Z_LVAL_PP(z_length);
    2144                 :         }
    2145                 : 
    2146                 :         /* Clamp the offset.. */
    2147             338 :         if (offset > num_in) {
    2148              13 :                 array_init(return_value);
    2149              13 :                 return;
    2150             325 :         } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    2151              13 :                 offset = 0;
    2152                 :         }
    2153                 : 
    2154                 :         /* ..and the length */
    2155             325 :         if (length < 0) {
    2156              69 :                 length = num_in - offset + length;
    2157             256 :         } else if (((unsigned long) offset + (unsigned long) length) > (unsigned) num_in) {
    2158              92 :                 length = num_in - offset;
    2159                 :         }
    2160                 : 
    2161                 :         /* Initialize returned array */
    2162             325 :         array_init_size(return_value, length > 0 ? length : 0);
    2163                 : 
    2164             325 :         if (length <= 0) {
    2165             104 :                 return;
    2166                 :         }
    2167                 : 
    2168                 :         /* Start at the beginning and go until we hit offset */
    2169             221 :         pos = 0;
    2170             221 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &hpos);
    2171             655 :         while (pos < offset && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) {
    2172             213 :                 pos++;
    2173             213 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos);
    2174                 :         }
    2175                 : 
    2176                 :         /* Copy elements from input array to the one that's returned */
    2177            1086 :         while (pos < offset + length && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) {
    2178                 : 
    2179             644 :                 zval_add_ref(entry);
    2180                 : 
    2181             644 :                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &hpos)) {
    2182                 :                         case HASH_KEY_IS_STRING:
    2183             153 :                                 zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL);
    2184             153 :                                 break;
    2185                 : 
    2186                 :                         case HASH_KEY_IS_LONG:
    2187             491 :                                 if (preserve_keys) {
    2188             150 :                                         zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL);
    2189                 :                                 } else {
    2190             341 :                                         zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
    2191                 :                                 }
    2192                 :                                 break;
    2193                 :                 }
    2194             644 :                 pos++;
    2195             644 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos);
    2196                 :         }
    2197                 : }
    2198                 : /* }}} */
    2199                 : 
    2200                 : PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC) /* {{{ */
    2201             591 : {
    2202                 :         zval **src_entry, **dest_entry;
    2203                 :         char *string_key;
    2204                 :         uint string_key_len;
    2205                 :         ulong num_key;
    2206                 :         HashPosition pos;
    2207                 : 
    2208             591 :         zend_hash_internal_pointer_reset_ex(src, &pos);
    2209           24876 :         while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
    2210           23704 :                 switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
    2211                 :                         case HASH_KEY_IS_STRING:
    2212            1018 :                                 if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) {
    2213              38 :                                         HashTable *thash = Z_TYPE_PP(dest_entry) == IS_ARRAY ? Z_ARRVAL_PP(dest_entry) : NULL;
    2214                 : 
    2215              38 :                                         if ((thash && thash->nApplyCount > 1) || (*src_entry == *dest_entry && Z_ISREF_PP(dest_entry) && (Z_REFCOUNT_PP(dest_entry) % 2))) {
    2216               2 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
    2217               2 :                                                 return 0;
    2218                 :                                         }
    2219              36 :                                         SEPARATE_ZVAL(dest_entry);
    2220              36 :                                         SEPARATE_ZVAL(src_entry);
    2221                 : 
    2222              36 :                                         if (Z_TYPE_PP(dest_entry) == IS_NULL) {
    2223               2 :                                                 convert_to_array_ex(dest_entry);
    2224               2 :                                                 add_next_index_null(*dest_entry);
    2225                 :                                         } else {
    2226              34 :                                                 convert_to_array_ex(dest_entry);
    2227                 :                                         }
    2228              36 :                                         if (Z_TYPE_PP(src_entry) == IS_NULL) {
    2229               1 :                                                 convert_to_array_ex(src_entry);
    2230               1 :                                                 add_next_index_null(*src_entry);
    2231                 :                                         } else {
    2232              35 :                                                 convert_to_array_ex(src_entry);
    2233                 :                                         }
    2234              36 :                                         if (thash) {
    2235              16 :                                                 thash->nApplyCount++;
    2236                 :                                         }
    2237              36 :                                         if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) {
    2238               8 :                                                 if (thash) {
    2239               8 :                                                         thash->nApplyCount--;
    2240                 :                                                 }
    2241               8 :                                                 return 0;
    2242                 :                                         }
    2243              28 :                                         if (thash) {
    2244               8 :                                                 thash->nApplyCount--;
    2245                 :                                         }
    2246                 :                                 } else {
    2247             952 :                                         Z_ADDREF_PP(src_entry);
    2248             952 :                                         zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
    2249                 :                                 }
    2250             980 :                                 break;
    2251                 : 
    2252                 :                         case HASH_KEY_IS_LONG:
    2253           22714 :                                 Z_ADDREF_PP(src_entry);
    2254           22714 :                                 zend_hash_next_index_insert(dest, src_entry, sizeof(zval *), NULL);
    2255                 :                                 break;
    2256                 :                 }
    2257           23694 :                 zend_hash_move_forward_ex(src, &pos);
    2258                 :         }
    2259             581 :         return 1;
    2260                 : }
    2261                 : /* }}} */
    2262                 : 
    2263                 : PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC) /* {{{ */
    2264               5 : {
    2265                 :         zval **src_entry, **dest_entry;
    2266                 :         char *string_key;
    2267                 :         uint string_key_len;
    2268                 :         ulong num_key;
    2269                 :         HashPosition pos;
    2270                 : 
    2271               5 :         for (zend_hash_internal_pointer_reset_ex(src, &pos);
    2272              14 :              zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS;
    2273               4 :              zend_hash_move_forward_ex(src, &pos)) {
    2274               7 :                 switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
    2275                 :                         case HASH_KEY_IS_STRING:
    2276               3 :                                 if (Z_TYPE_PP(src_entry) != IS_ARRAY ||
    2277                 :                                         zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == FAILURE ||
    2278                 :                                         Z_TYPE_PP(dest_entry) != IS_ARRAY) {
    2279                 : 
    2280               2 :                                         Z_ADDREF_PP(src_entry);
    2281               2 :                                         zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
    2282                 : 
    2283               2 :                                         continue;
    2284                 :                                 }
    2285               1 :                                 break;
    2286                 : 
    2287                 :                         case HASH_KEY_IS_LONG:
    2288               4 :                                 if (Z_TYPE_PP(src_entry) != IS_ARRAY ||
    2289                 :                                         zend_hash_index_find(dest, num_key, (void **)&dest_entry) == FAILURE ||
    2290                 :                                         Z_TYPE_PP(dest_entry) != IS_ARRAY) {
    2291                 : 
    2292               1 :                                         Z_ADDREF_PP(src_entry);
    2293               1 :                                         zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
    2294                 : 
    2295               1 :                                         continue;
    2296                 :                                 }
    2297                 :                                 break;
    2298                 :                 }
    2299                 : 
    2300               4 :                 if (Z_ARRVAL_PP(dest_entry)->nApplyCount > 1 || Z_ARRVAL_PP(src_entry)->nApplyCount > 1 || (*src_entry == *dest_entry && Z_ISREF_PP(dest_entry) && (Z_REFCOUNT_PP(dest_entry) % 2))) {
    2301               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
    2302               1 :                         return 0;
    2303                 :                 }
    2304               3 :                 SEPARATE_ZVAL(dest_entry);
    2305               3 :                 Z_ARRVAL_PP(dest_entry)->nApplyCount++;
    2306               3 :                 Z_ARRVAL_PP(src_entry)->nApplyCount++;
    2307                 :                 
    2308                 : 
    2309               3 :                 if (!php_array_replace_recursive(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC)) {
    2310               2 :                         Z_ARRVAL_PP(dest_entry)->nApplyCount--;
    2311               2 :                         Z_ARRVAL_PP(src_entry)->nApplyCount--;
    2312               2 :                         return 0;
    2313                 :                 }
    2314               1 :                 Z_ARRVAL_PP(dest_entry)->nApplyCount--;
    2315               1 :                 Z_ARRVAL_PP(src_entry)->nApplyCount--;
    2316                 :         }
    2317                 : 
    2318               2 :         return 1;
    2319                 : }
    2320                 : /* }}} */
    2321                 : 
    2322                 : static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace) /* {{{ */
    2323             426 : {
    2324             426 :         zval ***args = NULL;
    2325             426 :         int argc, i, init_size = 0;
    2326                 : 
    2327             426 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
    2328               3 :                 return;
    2329                 :         }
    2330                 : 
    2331            1036 :         for (i = 0; i < argc; i++) {
    2332             736 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
    2333             123 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
    2334             123 :                         efree(args);
    2335             123 :                         RETURN_NULL();
    2336                 :                 } else {
    2337             613 :                         int num = zend_hash_num_elements(Z_ARRVAL_PP(args[i]));
    2338                 : 
    2339             613 :                         if (num > init_size) {
    2340             443 :                                 init_size = num;
    2341                 :                         }
    2342                 :                 }
    2343                 :         }
    2344                 : 
    2345             300 :         array_init_size(return_value, init_size);
    2346                 : 
    2347             861 :         for (i = 0; i < argc; i++) {
    2348             561 :                 SEPARATE_ZVAL(args[i]);
    2349             561 :                 if (!replace) {
    2350             555 :                         php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC);
    2351               8 :                 } else if (recursive && i > 0) { /* First array will be copied directly instead */
    2352               2 :                         php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]) TSRMLS_CC);
    2353                 :                 } else {
    2354               4 :                         zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1);
    2355                 :                 }
    2356                 :         }
    2357                 : 
    2358             300 :         efree(args);
    2359                 : }
    2360                 : /* }}} */
    2361                 : 
    2362                 : /* {{{ proto array array_merge(array arr1, array arr2 [, array ...])
    2363                 :    Merges elements from passed arrays into one array */
    2364                 : PHP_FUNCTION(array_merge)
    2365             245 : {
    2366             245 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
    2367             245 : }
    2368                 : /* }}} */
    2369                 : 
    2370                 : /* {{{ proto array array_merge_recursive(array arr1, array arr2 [, array ...])
    2371                 :    Recursively merges elements from passed arrays into one array */
    2372                 : PHP_FUNCTION(array_merge_recursive)
    2373             178 : {
    2374             178 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
    2375             178 : }
    2376                 : /* }}} */
    2377                 : 
    2378                 : /* {{{ proto array array_replace(array arr1, array arr2 [, array ...])
    2379                 :    Replaces elements from passed arrays into one array */
    2380                 : PHP_FUNCTION(array_replace)
    2381               1 : {
    2382               1 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
    2383               1 : }
    2384                 : /* }}} */
    2385                 : 
    2386                 : /* {{{ proto array array_replace_recursive(array arr1, array arr2 [, array ...])
    2387                 :    Recursively replaces elements from passed arrays into one array */
    2388                 : PHP_FUNCTION(array_replace_recursive)
    2389               2 : {
    2390               2 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
    2391               2 : }
    2392                 : /* }}} */
    2393                 : 
    2394                 : /* {{{ proto array array_keys(array input [, mixed search_value[, bool strict]])
    2395                 :    Return just the keys from the input array, optionally only for the specified search_value */
    2396                 : PHP_FUNCTION(array_keys)
    2397              78 : {
    2398                 :         zval *input,                            /* Input array */
    2399              78 :              *search_value = NULL,      /* Value to search for */
    2400                 :              **entry,                           /* An entry in the input array */
    2401                 :                res,                                     /* Result of comparison */
    2402                 :               *new_val;                         /* New value */
    2403                 :         int    add_key;                         /* Flag to indicate whether a key should be added */
    2404                 :         char  *string_key;                      /* String key */
    2405                 :         uint   string_key_len;
    2406                 :         ulong  num_key;                         /* Numeric key */
    2407              78 :         zend_bool strict = 0;           /* do strict comparison */
    2408                 :         HashPosition pos;
    2409              78 :         int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
    2410                 : 
    2411              78 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) {
    2412               5 :                 return;
    2413                 :         }
    2414                 : 
    2415              73 :         if (strict) {
    2416              14 :                 is_equal_func = is_identical_function;
    2417                 :         }
    2418                 : 
    2419                 :         /* Initialize return array */
    2420              73 :         if (search_value != NULL) {
    2421              28 :                 array_init(return_value);
    2422                 :         } else {
    2423              45 :                 array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    2424                 :         }
    2425              73 :         add_key = 1;
    2426                 : 
    2427                 :         /* Go through input array and add keys to the return array */
    2428              73 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    2429            1612 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
    2430            1466 :                 if (search_value != NULL) {
    2431             176 :                         is_equal_func(&res, search_value, *entry TSRMLS_CC);
    2432             176 :                         add_key = zval_is_true(&res);
    2433                 :                 }
    2434                 : 
    2435            1466 :                 if (add_key) {
    2436            1325 :                         MAKE_STD_ZVAL(new_val);
    2437                 : 
    2438            1325 :                         switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 1, &pos)) {
    2439                 :                                 case HASH_KEY_IS_STRING:
    2440            1249 :                                         ZVAL_STRINGL(new_val, string_key, string_key_len - 1, 0);
    2441            1249 :                                         zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
    2442            1249 :                                         break;
    2443                 : 
    2444                 :                                 case HASH_KEY_IS_LONG:
    2445              76 :                                         Z_TYPE_P(new_val) = IS_LONG;
    2446              76 :                                         Z_LVAL_P(new_val) = num_key;
    2447              76 :                                         zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
    2448                 :                                         break;
    2449                 :                         }
    2450                 :                 }
    2451                 : 
    2452            1466 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
    2453                 :         }
    2454                 : }
    2455                 : /* }}} */
    2456                 : 
    2457                 : /* {{{ proto array array_values(array input)
    2458                 :    Return just the values from the input array */
    2459                 : PHP_FUNCTION(array_values)
    2460              85 : {
    2461                 :         zval     *input,                /* Input array */
    2462                 :                         **entry;                /* An entry in the input array */
    2463                 :         HashPosition pos;
    2464                 : 
    2465              85 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
    2466              31 :                 return;
    2467                 :         }
    2468                 : 
    2469                 :         /* Initialize return array */
    2470              54 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    2471                 : 
    2472                 :         /* Go through input array and add values to the return array */
    2473              54 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    2474             247 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
    2475             139 :                 zval_add_ref(entry);
    2476             139 :                 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
    2477             139 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
    2478                 :         }
    2479                 : }
    2480                 : /* }}} */
    2481                 : 
    2482                 : /* {{{ proto array array_count_values(array input)
    2483                 :    Return the value as key and the frequency of that value in input as value */
    2484                 : PHP_FUNCTION(array_count_values)
    2485              19 : {
    2486                 :         zval    *input,                 /* Input array */
    2487                 :                         **entry,                /* An entry in the input array */
    2488                 :                         **tmp;
    2489                 :         HashTable *myht;
    2490                 :         HashPosition pos;
    2491                 : 
    2492              19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
    2493               3 :                 return;
    2494                 :         }
    2495                 : 
    2496                 :         /* Initialize return array */
    2497              16 :         array_init(return_value);
    2498                 : 
    2499                 :         /* Go through input array and add values to the return array */
    2500              16 :         myht = Z_ARRVAL_P(input);
    2501              16 :         zend_hash_internal_pointer_reset_ex(myht, &pos);
    2502              89 :         while (zend_hash_get_current_data_ex(myht, (void **)&entry, &pos) == SUCCESS) {
    2503              57 :                 if (Z_TYPE_PP(entry) == IS_LONG) {
    2504              17 :                         if (zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), (void **)&tmp) == FAILURE) {
    2505                 :                                 zval *data;
    2506              13 :                                 MAKE_STD_ZVAL(data);
    2507              13 :                                 ZVAL_LONG(data, 1);
    2508              13 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL);
    2509                 :                         } else {
    2510               4 :                                 Z_LVAL_PP(tmp)++;
    2511                 :                         }
    2512              40 :                 } else if (Z_TYPE_PP(entry) == IS_STRING) {
    2513              31 :                         if (zend_symtable_find(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, (void**)&tmp) == FAILURE) {
    2514                 :                                 zval *data;
    2515              22 :                                 MAKE_STD_ZVAL(data);
    2516              22 :                                 ZVAL_LONG(data, 1);
    2517              22 :                                 zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &data, sizeof(data), NULL);
    2518                 :                         } else {
    2519               9 :                                 Z_LVAL_PP(tmp)++;
    2520                 :                         }
    2521                 :                 } else {
    2522               9 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only count STRING and INTEGER values!");
    2523                 :                 }
    2524                 : 
    2525              57 :                 zend_hash_move_forward_ex(myht, &pos);
    2526                 :         }
    2527                 : }
    2528                 : /* }}} */
    2529                 : 
    2530                 : /* {{{ proto array array_reverse(array input [, bool preserve keys])
    2531                 :    Return input as a new array with the order of the entries reversed */
    2532                 : PHP_FUNCTION(array_reverse)
    2533             234 : {
    2534                 :         zval     *input,                                /* Input array */
    2535                 :                         **entry;                                /* An entry in the input array */
    2536                 :         char     *string_key;
    2537                 :         uint      string_key_len;
    2538                 :         ulong     num_key;
    2539             234 :         zend_bool preserve_keys = 0;    /* whether to preserve keys */
    2540                 :         HashPosition pos;
    2541                 : 
    2542             234 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &input, &preserve_keys) == FAILURE) {
    2543              82 :                 return;
    2544                 :         }
    2545                 : 
    2546                 :         /* Initialize return array */
    2547             152 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    2548                 : 
    2549             152 :         zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(input), &pos);
    2550             816 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
    2551             512 :                 zval_add_ref(entry);
    2552                 : 
    2553             512 :                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) {
    2554                 :                         case HASH_KEY_IS_STRING:
    2555             175 :                                 zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL);
    2556             175 :                                 break;
    2557                 : 
    2558                 :                         case HASH_KEY_IS_LONG:
    2559             337 :                                 if (preserve_keys) {
    2560             129 :                                         zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL);
    2561                 :                                 } else {
    2562             208 :                                         zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
    2563                 :                                 }
    2564                 :                                 break;
    2565                 :                 }
    2566                 : 
    2567             512 :                 zend_hash_move_backwards_ex(Z_ARRVAL_P(input), &pos);
    2568                 :         }
    2569                 : }
    2570                 : /* }}} */
    2571                 : 
    2572                 : /* {{{ proto array array_pad(array input, int pad_size, mixed pad_value)
    2573                 :    Returns a copy of input array padded with pad_value to size pad_size */
    2574                 : PHP_FUNCTION(array_pad)
    2575             199 : {
    2576                 :         zval  *input;           /* Input array */
    2577                 :         zval  *pad_value;       /* Padding value obviously */
    2578                 :         zval ***pads;           /* Array to pass to splice */
    2579                 :         HashTable *new_hash;/* Return value from splice */
    2580                 :         HashTable  old_hash;
    2581                 :         long pad_size;          /* Size to pad to */
    2582                 :         long pad_size_abs;      /* Absolute value of pad_size */
    2583                 :         int     input_size;             /* Size of the input array */
    2584                 :         int     num_pads;               /* How many pads do we need */
    2585                 :         int     do_pad;                 /* Whether we should do padding at all */
    2586                 :         int     i;
    2587                 : 
    2588             199 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "alz", &input, &pad_size, &pad_value) == FAILURE) {
    2589              66 :                 return;
    2590                 :         }
    2591                 : 
    2592                 :         /* Do some initial calculations */
    2593             133 :         input_size = zend_hash_num_elements(Z_ARRVAL_P(input));
    2594             133 :         pad_size_abs = abs(pad_size);
    2595             133 :         if (pad_size_abs < 0) {
    2596               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time");
    2597               0 :                 zval_dtor(return_value);
    2598               0 :                 RETURN_FALSE;
    2599                 :         }
    2600             133 :         do_pad = (input_size >= pad_size_abs) ? 0 : 1;
    2601                 : 
    2602                 :         /* Copy the original array */
    2603             133 :         RETVAL_ZVAL(input, 1, 0);
    2604                 : 
    2605                 :         /* If no need to pad, no need to continue */
    2606             133 :         if (!do_pad) {
    2607              15 :                 return;
    2608                 :         }
    2609                 : 
    2610                 :         /* Populate the pads array */
    2611             118 :         num_pads = pad_size_abs - input_size;
    2612             118 :         if (num_pads > 1048576) {
    2613               3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time");
    2614               3 :                 zval_dtor(return_value);
    2615               3 :                 RETURN_FALSE;
    2616                 :         }
    2617             115 :         pads = (zval ***)safe_emalloc(num_pads, sizeof(zval **), 0);
    2618             400 :         for (i = 0; i < num_pads; i++) {
    2619             285 :                 pads[i] = &pad_value;
    2620                 :         }
    2621                 : 
    2622                 :         /* Pad on the right or on the left */
    2623             115 :         if (pad_size > 0) {
    2624              58 :                 new_hash = php_splice(Z_ARRVAL_P(return_value), input_size, 0, pads, num_pads, NULL);
    2625                 :         } else {
    2626              57 :                 new_hash = php_splice(Z_ARRVAL_P(return_value), 0, 0, pads, num_pads, NULL);
    2627                 :         }
    2628                 : 
    2629                 :         /* Copy the result hash into return value */
    2630             115 :         old_hash = *Z_ARRVAL_P(return_value);
    2631             115 :         if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
    2632               0 :                 zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
    2633                 :         }
    2634             115 :         *Z_ARRVAL_P(return_value) = *new_hash;
    2635             115 :         FREE_HASHTABLE(new_hash);
    2636             115 :         zend_hash_destroy(&old_hash);
    2637                 : 
    2638                 :         /* Clean up */
    2639             115 :         efree(pads);
    2640                 : }
    2641                 : /* }}} */
    2642                 : 
    2643                 : /* {{{ proto array array_flip(array input)
    2644                 :    Return array with key <-> value flipped */
    2645                 : PHP_FUNCTION(array_flip)
    2646              49 : {
    2647                 :         zval *array, **entry, *data;
    2648                 :         char *string_key;
    2649                 :         uint str_key_len;
    2650                 :         ulong num_key;
    2651                 :         HashPosition pos;
    2652                 : 
    2653              49 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
    2654              25 :                 return;
    2655                 :         }
    2656                 : 
    2657              24 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
    2658                 : 
    2659              24 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
    2660             197 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
    2661             149 :                 MAKE_STD_ZVAL(data);
    2662             149 :                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 1, &pos)) {
    2663                 :                         case HASH_KEY_IS_STRING:
    2664              67 :                                 ZVAL_STRINGL(data, string_key, str_key_len - 1, 0);
    2665              67 :                                 break;
    2666                 :                         case HASH_KEY_IS_LONG:
    2667              82 :                                 Z_TYPE_P(data) = IS_LONG;
    2668              82 :                                 Z_LVAL_P(data) = num_key;
    2669                 :                                 break;
    2670                 :                 }
    2671                 : 
    2672             149 :                 if (Z_TYPE_PP(entry) == IS_LONG) {
    2673              80 :                         zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL);
    2674              69 :                 } else if (Z_TYPE_PP(entry) == IS_STRING) {
    2675              54 :                         zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &data, sizeof(data), NULL);
    2676                 :                 } else {
    2677              15 :                         zval_ptr_dtor(&data); /* will free also zval structure */
    2678              15 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only flip STRING and INTEGER values!");
    2679                 :                 }
    2680                 : 
    2681             149 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
    2682                 :         }
    2683                 : }
    2684                 : /* }}} */
    2685                 : 
    2686                 : /* {{{ proto array array_change_key_case(array input [, int case=CASE_LOWER])
    2687                 :    Retuns an array with all string keys lowercased [or uppercased] */
    2688                 : PHP_FUNCTION(array_change_key_case)
    2689             201 : {
    2690                 :         zval *array, **entry;
    2691                 :         char *string_key;
    2692                 :         char *new_key;
    2693                 :         uint str_key_len;
    2694                 :         ulong num_key;
    2695             201 :         long change_to_upper=0;
    2696                 :         HashPosition pos;
    2697                 : 
    2698             201 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &change_to_upper) == FAILURE) {
    2699              36 :                 return;
    2700                 :         }
    2701                 : 
    2702             165 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
    2703                 : 
    2704             165 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
    2705             736 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
    2706             406 :                 zval_add_ref(entry);
    2707                 : 
    2708             406 :                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {
    2709                 :                         case HASH_KEY_IS_LONG:
    2710              64 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(entry), NULL);
    2711              64 :                                 break;
    2712                 :                         case HASH_KEY_IS_STRING:
    2713             342 :                                 new_key = estrndup(string_key, str_key_len - 1);
    2714             342 :                                 if (change_to_upper) {
    2715             169 :                                         php_strtoupper(new_key, str_key_len - 1);
    2716                 :                                 } else {
    2717             173 :                                         php_strtolower(new_key, str_key_len - 1);
    2718                 :                                 }
    2719             342 :                                 zend_hash_update(Z_ARRVAL_P(return_value), new_key, str_key_len, entry, sizeof(entry), NULL);
    2720             342 :                                 efree(new_key);
    2721                 :                                 break;
    2722                 :                 }
    2723                 : 
    2724             406 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
    2725                 :         }
    2726                 : }
    2727                 : /* }}} */
    2728                 : 
    2729                 : /* {{{ proto array array_unique(array input [, int sort_flags])
    2730                 :    Removes duplicate values from array */
    2731                 : PHP_FUNCTION(array_unique)
    2732              71 : {
    2733                 :         zval *array, *tmp;
    2734                 :         Bucket *p;
    2735                 :         struct bucketindex {
    2736                 :                 Bucket *b;
    2737                 :                 unsigned int i;
    2738                 :         };
    2739                 :         struct bucketindex *arTmp, *cmpdata, *lastkept;
    2740                 :         unsigned int i;
    2741              71 :         long sort_type = PHP_SORT_STRING;
    2742                 : 
    2743              71 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
    2744              27 :                 return;
    2745                 :         }
    2746                 : 
    2747              44 :         php_set_compare_func(sort_type TSRMLS_CC);
    2748                 : 
    2749              44 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
    2750              44 :         zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*));
    2751                 : 
    2752              44 :         if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {     /* nothing to do */
    2753               2 :                 return;
    2754                 :         }
    2755                 : 
    2756                 :         /* create and sort array with pointers to the target_hash buckets */
    2757              42 :         arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->persistent);
    2758              42 :         if (!arTmp) {
    2759               0 :                 zval_dtor(return_value);
    2760               0 :                 RETURN_FALSE;
    2761                 :         }
    2762           11076 :         for (i = 0, p = Z_ARRVAL_P(array)->pListHead; p; i++, p = p->pListNext) {
    2763           11034 :                 arTmp[i].b = p;
    2764           11034 :                 arTmp[i].i = i;
    2765                 :         }
    2766              42 :         arTmp[i].b = NULL;
    2767              42 :         zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC);
    2768                 : 
    2769                 :         /* go through the sorted array and delete duplicates from the copy */
    2770              42 :         lastkept = arTmp;
    2771           11034 :         for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) {
    2772           10992 :                 if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
    2773           10928 :                         lastkept = cmpdata;
    2774                 :                 } else {
    2775              64 :                         if (lastkept->i > cmpdata->i) {
    2776              42 :                                 p = lastkept->b;
    2777              42 :                                 lastkept = cmpdata;
    2778                 :                         } else {
    2779              22 :                                 p = cmpdata->b;
    2780                 :                         }
    2781              64 :                         if (p->nKeyLength == 0) {
    2782              40 :                                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    2783                 :                         } else {
    2784              24 :                                 if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
    2785               0 :                                         zend_delete_global_variable(p->arKey, p->nKeyLength - 1 TSRMLS_CC);
    2786                 :                                 } else {
    2787              24 :                                         zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
    2788                 :                                 }
    2789                 :                         }
    2790                 :                 }
    2791                 :         }
    2792              42 :         pefree(arTmp, Z_ARRVAL_P(array)->persistent);
    2793                 : }
    2794                 : /* }}} */
    2795                 : 
    2796                 : static int zval_compare(zval **a, zval **b TSRMLS_DC) /* {{{ */
    2797            1109 : {
    2798                 :         zval result;
    2799                 :         zval *first;
    2800                 :         zval *second;
    2801                 : 
    2802            1109 :         first = *((zval **) a);
    2803            1109 :         second = *((zval **) b);
    2804                 : 
    2805            1109 :         if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) {
    2806               0 :                 return 0;
    2807                 :         }
    2808                 : 
    2809            1109 :         if (Z_TYPE(result) == IS_DOUBLE) {
    2810               0 :                 if (Z_DVAL(result) < 0) {
    2811               0 :                         return -1;
    2812               0 :                 } else if (Z_DVAL(result) > 0) {
    2813               0 :                         return 1;
    2814                 :                 } else {
    2815               0 :                         return 0;
    2816                 :                 }
    2817                 :         }
    2818                 : 
    2819            1109 :         convert_to_long(&result);
    2820                 : 
    2821            1109 :         if (Z_LVAL(result) < 0) {
    2822             362 :                 return -1;
    2823             747 :         } else if (Z_LVAL(result) > 0) {
    2824             369 :                 return 1;
    2825                 :         }
    2826                 : 
    2827             378 :         return 0;
    2828                 : }
    2829                 : /* }}} */
    2830                 : 
    2831                 : static int zval_user_compare(zval **a, zval **b TSRMLS_DC) /* {{{ */
    2832              44 : {
    2833                 :         zval **args[2];
    2834                 :         zval *retval_ptr;
    2835                 : 
    2836              44 :         args[0] = (zval **) a;
    2837              44 :         args[1] = (zval **) b;
    2838                 : 
    2839              44 :         BG(user_compare_fci).param_count = 2;
    2840              44 :         BG(user_compare_fci).params = args;
    2841              44 :         BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
    2842              44 :         BG(user_compare_fci).no_separation = 0;
    2843                 : 
    2844              44 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
    2845                 :                 long retval;
    2846                 : 
    2847              44 :                 convert_to_long_ex(&retval_ptr);
    2848              44 :                 retval = Z_LVAL_P(retval_ptr);
    2849              44 :                 zval_ptr_dtor(&retval_ptr);
    2850              44 :                 return retval < 0 ? -1 : retval > 0 ? 1 : 0;;
    2851                 :         } else {
    2852               0 :                 return 0;
    2853                 :         }
    2854                 : }
    2855                 : /* }}} */
    2856                 : 
    2857                 : static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
    2858             552 : {
    2859                 :         Bucket *p;
    2860                 :         int argc, i;
    2861                 :         zval ***args;
    2862             552 :         int (*intersect_data_compare_func)(zval **, zval ** TSRMLS_DC) = NULL;
    2863                 :         zend_bool ok;
    2864                 :         zval **data;
    2865                 :         int req_args;
    2866                 :         char *param_spec;
    2867                 : 
    2868                 :         /* Get the argument count */
    2869             552 :         argc = ZEND_NUM_ARGS();
    2870             552 :         if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    2871                 :                 /* INTERSECT_COMP_DATA_USER - array_uintersect_assoc() */
    2872             112 :                 req_args = 3;
    2873             112 :                 param_spec = "+f";
    2874             112 :                 intersect_data_compare_func = zval_user_compare;
    2875                 :         } else {
    2876                 :                 /*      INTERSECT_COMP_DATA_NONE - array_intersect_key()
    2877                 :                         INTERSECT_COMP_DATA_INTERNAL - array_intersect_assoc() */
    2878             440 :                 req_args = 2;
    2879             440 :                 param_spec = "+";
    2880                 :                                 
    2881             440 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
    2882             279 :                         intersect_data_compare_func = zval_compare;
    2883                 :                 }
    2884                 :         }
    2885                 :         
    2886             552 :         if (argc < req_args) {
    2887               5 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, argc);
    2888               5 :                 return;
    2889                 :         }
    2890                 : 
    2891             547 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
    2892              30 :                 return;
    2893                 :         }
    2894                 : 
    2895            1272 :         for (i = 0; i < argc; i++) {
    2896            1056 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
    2897             301 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
    2898             301 :                         RETVAL_NULL();
    2899             301 :                         goto out;
    2900                 :                 }
    2901                 :         }
    2902                 : 
    2903             216 :         array_init(return_value);
    2904                 : 
    2905            1929 :         for (p = Z_ARRVAL_PP(args[0])->pListHead; p != NULL; p = p->pListNext) {
    2906            1713 :                 if (p->nKeyLength == 0) {
    2907            1141 :                         ok = 1;
    2908            1345 :                         for (i = 1; i < argc; i++) {
    2909            1208 :                                 if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == FAILURE ||
    2910                 :                                         (intersect_data_compare_func &&
    2911                 :                                         intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)
    2912                 :                                 ) {
    2913            1004 :                                         ok = 0;
    2914            1004 :                                         break;
    2915                 :                                 }
    2916                 :                         }
    2917            1141 :                         if (ok) {
    2918             137 :                                 Z_ADDREF_PP((zval**)p->pData);
    2919             137 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, p->pData, sizeof(zval*), NULL);
    2920                 :                         }
    2921                 :                 } else {
    2922             572 :                         ok = 1;
    2923             699 :                         for (i = 1; i < argc; i++) {
    2924             612 :                                 if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == FAILURE ||
    2925                 :                                         (intersect_data_compare_func &&
    2926                 :                                         intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)
    2927                 :                                 ) {
    2928             485 :                                         ok = 0;
    2929             485 :                                         break;
    2930                 :                                 }
    2931                 :                         }
    2932             572 :                         if (ok) {
    2933              87 :                                 Z_ADDREF_PP((zval**)p->pData);
    2934              87 :                                 zend_hash_quick_update(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval*), NULL);
    2935                 :                         }
    2936                 :                 }
    2937                 :         }
    2938             517 : out:
    2939             517 :         efree(args);
    2940                 : }
    2941                 : /* }}} */
    2942                 : 
    2943                 : static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type) /* {{{ */
    2944             965 : {
    2945             965 :         zval ***args = NULL;
    2946                 :         HashTable *hash;
    2947             965 :         int arr_argc, i, c = 0;
    2948                 :         Bucket ***lists, **list, ***ptrs, *p;
    2949                 :         int req_args;
    2950                 :         char *param_spec;
    2951                 :         zend_fcall_info fci1, fci2;
    2952             965 :         zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
    2953                 :         zend_fcall_info *fci_key, *fci_data;
    2954                 :         zend_fcall_info_cache *fci_key_cache, *fci_data_cache;
    2955                 :         PHP_ARRAY_CMP_FUNC_VARS;
    2956                 : 
    2957                 :         int (*intersect_key_compare_func)(const void *, const void * TSRMLS_DC);
    2958                 :         int (*intersect_data_compare_func)(const void *, const void * TSRMLS_DC);
    2959                 : 
    2960             965 :         if (behavior == INTERSECT_NORMAL) {
    2961             397 :                 intersect_key_compare_func = php_array_key_compare;
    2962                 : 
    2963             397 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
    2964                 :                         /* array_intersect() */
    2965             283 :                         req_args = 2;
    2966             283 :                         param_spec = "+";
    2967             283 :                         intersect_data_compare_func = php_array_data_compare;
    2968             114 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    2969                 :                         /* array_uintersect() */
    2970             114 :                         req_args = 3;
    2971             114 :                         param_spec = "+f";
    2972             114 :                         intersect_data_compare_func = php_array_user_compare;
    2973                 :                 } else {
    2974               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
    2975               0 :                         return;
    2976                 :                 }
    2977                 : 
    2978             397 :                 if (ZEND_NUM_ARGS() < req_args) {
    2979               3 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    2980               3 :                         return;
    2981                 :                 }
    2982                 : 
    2983             394 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
    2984              30 :                         return;
    2985                 :                 }
    2986             364 :                 fci_data = &fci1;
    2987             364 :                 fci_data_cache = &fci1_cache;
    2988                 : 
    2989             568 :         } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    2990                 :                 /* INTERSECT_KEY is subset of INTERSECT_ASSOC. When having the former
    2991                 :                  * no comparison of the data is done (part of INTERSECT_ASSOC) */
    2992             568 :                 intersect_key_compare_func = php_array_key_compare;
    2993                 : 
    2994             568 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
    2995                 :                         /* array_intersect_assoc() or array_intersect_key() */
    2996               0 :                         req_args = 2;
    2997               0 :                         param_spec = "+";
    2998               0 :                         intersect_key_compare_func = php_array_key_compare;
    2999               0 :                         intersect_data_compare_func = php_array_data_compare;
    3000             568 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
    3001                 :                         /* array_uintersect_assoc() */
    3002               0 :                         req_args = 3;
    3003               0 :                         param_spec = "+f";
    3004               0 :                         intersect_key_compare_func = php_array_key_compare;
    3005               0 :                         intersect_data_compare_func = php_array_user_compare;
    3006               0 :                         fci_data = &fci1;
    3007               0 :                         fci_data_cache = &fci1_cache;
    3008             995 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3009                 :                         /* array_intersect_uassoc() or array_intersect_ukey() */
    3010             427 :                         req_args = 3;
    3011             427 :                         param_spec = "+f";
    3012             427 :                         intersect_key_compare_func = php_array_user_key_compare;
    3013             427 :                         intersect_data_compare_func = php_array_data_compare;
    3014             427 :                         fci_key = &fci1;
    3015             427 :                         fci_key_cache = &fci1_cache;
    3016             282 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3017                 :                         /* array_uintersect_uassoc() */
    3018             141 :                         req_args = 4;
    3019             141 :                         param_spec = "+ff";
    3020             141 :                         intersect_key_compare_func = php_array_user_key_compare;
    3021             141 :                         intersect_data_compare_func = php_array_user_compare;
    3022             141 :                         fci_data = &fci1;
    3023             141 :                         fci_data_cache = &fci1_cache;
    3024             141 :                         fci_key = &fci2;
    3025             141 :                         fci_key_cache = &fci2_cache;
    3026                 :                 } else {
    3027               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
    3028               0 :                         return;
    3029                 :                 }
    3030                 : 
    3031             568 :                 if (ZEND_NUM_ARGS() < req_args) {
    3032               5 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3033               5 :                         return;
    3034                 :                 }
    3035                 : 
    3036             563 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
    3037             160 :                         return;
    3038                 :                 }
    3039                 : 
    3040                 :         } else {
    3041               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
    3042               0 :                 return;
    3043                 :         }
    3044                 : 
    3045             767 :         PHP_ARRAY_CMP_FUNC_BACKUP();
    3046                 : 
    3047                 :         /* for each argument, create and sort list with pointers to the hash buckets */
    3048             767 :         lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
    3049             767 :         ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
    3050             767 :         php_set_compare_func(PHP_SORT_STRING TSRMLS_CC);
    3051                 : 
    3052             850 :         if (behavior == INTERSECT_NORMAL && data_compare_type == INTERSECT_COMP_DATA_USER) {
    3053              83 :                 BG(user_compare_fci) = *fci_data;
    3054              83 :                 BG(user_compare_fci_cache) = *fci_data_cache;
    3055             684 :         } else if (behavior & INTERSECT_ASSOC && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3056             403 :                 BG(user_compare_fci) = *fci_key;
    3057             403 :                 BG(user_compare_fci_cache) = *fci_key_cache;
    3058                 :         }
    3059                 : 
    3060            1795 :         for (i = 0; i < arr_argc; i++) {
    3061            1560 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
    3062             532 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
    3063             532 :                         arr_argc = i; /* only free up to i - 1 */
    3064             532 :                         goto out;
    3065                 :                 }
    3066            1028 :                 hash = Z_ARRVAL_PP(args[i]);
    3067            1028 :                 list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent);
    3068            1028 :                 if (!list) {
    3069               0 :                         PHP_ARRAY_CMP_FUNC_RESTORE();
    3070                 : 
    3071               0 :                         efree(ptrs);
    3072               0 :                         efree(lists);
    3073               0 :                         efree(args);
    3074               0 :                         RETURN_FALSE;
    3075                 :                 }
    3076            1028 :                 lists[i] = list;
    3077            1028 :                 ptrs[i] = list;
    3078            6558 :                 for (p = hash->pListHead; p; p = p->pListNext) {
    3079            5530 :                         *list++ = p;
    3080                 :                 }
    3081            1028 :                 *list = NULL;
    3082            1028 :                 if (behavior == INTERSECT_NORMAL) {
    3083             604 :                         zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_data_compare_func TSRMLS_CC);
    3084             424 :                 } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3085             424 :                         zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_key_compare_func TSRMLS_CC);
    3086                 :                 }
    3087                 :         }
    3088                 : 
    3089                 :         /* copy the argument array */
    3090             235 :         RETVAL_ZVAL(*args[0], 1, 0);
    3091             235 :         if (return_value->value.ht == &EG(symbol_table)) {
    3092                 :                 HashTable *ht;
    3093                 :                 zval *tmp;
    3094                 : 
    3095               0 :                 ALLOC_HASHTABLE(ht);
    3096               0 :                 zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0);
    3097               0 :                 zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
    3098               0 :                 return_value->value.ht = ht;
    3099                 :         }
    3100                 : 
    3101                 :         /* go through the lists and look for common values */
    3102             988 :         while (*ptrs[0]) {
    3103             747 :                 if ((behavior & INTERSECT_ASSOC) /* triggered also when INTERSECT_KEY */
    3104                 :                         &&
    3105                 :                         key_compare_type == INTERSECT_COMP_KEY_USER) {
    3106                 : 
    3107             148 :                         BG(user_compare_fci) = *fci_key;
    3108             148 :                         BG(user_compare_fci_cache) = *fci_key_cache;
    3109                 :                 }
    3110                 : 
    3111            1250 :                 for (i = 1; i < arr_argc; i++) {
    3112             906 :                         if (behavior & INTERSECT_NORMAL) {
    3113            2358 :                                 while (*ptrs[i] && (0 < (c = intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
    3114             874 :                                         ptrs[i]++;
    3115                 :                                 }
    3116             164 :                         } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3117             402 :                                 while (*ptrs[i] && (0 < (c = intersect_key_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
    3118              74 :                                         ptrs[i]++;
    3119                 :                                 }
    3120             164 :                                 if ((!c && *ptrs[i]) && (behavior == INTERSECT_ASSOC)) { /* only when INTERSECT_ASSOC */
    3121                 :                                         /* this means that ptrs[i] is not NULL so we can compare
    3122                 :                                          * and "c==0" is from last operation
    3123                 :                                          * in this branch of code we enter only when INTERSECT_ASSOC
    3124                 :                                          * since when we have INTERSECT_KEY compare of data is not wanted. */
    3125              40 :                                         if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    3126              12 :                                                 BG(user_compare_fci) = *fci_data;
    3127              12 :                                                 BG(user_compare_fci_cache) = *fci_data_cache;
    3128                 :                                         }
    3129              40 :                                         if (intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
    3130              19 :                                                 c = 1;
    3131              19 :                                                 if (key_compare_type == INTERSECT_COMP_KEY_USER) {
    3132              19 :                                                         BG(user_compare_fci) = *fci_key;
    3133              19 :                                                         BG(user_compare_fci_cache) = *fci_key_cache;
    3134                 :                                                         /* When KEY_USER, the last parameter is always the callback */
    3135                 :                                                 }
    3136                 :                                                 /* we are going to the break */
    3137                 :                                         } else {
    3138                 :                                                 /* continue looping */
    3139                 :                                         }
    3140                 :                                 }
    3141                 :                         }
    3142             906 :                         if (!*ptrs[i]) {
    3143                 :                                 /* delete any values corresponding to remains of ptrs[0] */
    3144                 :                                 /* and exit because they do not present in at least one of */
    3145                 :                                 /* the other arguments */
    3146                 :                                 for (;;) {
    3147             698 :                                         p = *ptrs[0]++;
    3148             698 :                                         if (!p) {
    3149             109 :                                                 goto out;
    3150                 :                                         }
    3151             589 :                                         if (p->nKeyLength == 0) {
    3152             522 :                                                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3153                 :                                         } else {
    3154              67 :                                                 zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
    3155                 :                                         }
    3156             589 :                                 }
    3157                 :                         }
    3158             797 :                         if (c) /* here we get if not all are equal */
    3159             294 :                                 break;
    3160             503 :                         ptrs[i]++;
    3161                 :                 }
    3162             638 :                 if (c) {
    3163                 :                         /* Value of ptrs[0] not in all arguments, delete all entries */
    3164                 :                         /* with value < value of ptrs[i] */
    3165                 :                         for (;;) {
    3166             678 :                                 p = *ptrs[0];
    3167             678 :                                 if (p->nKeyLength == 0) {
    3168             564 :                                         zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3169                 :                                 } else {
    3170             114 :                                         zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
    3171                 :                                 }
    3172             678 :                                 if (!*++ptrs[0]) {
    3173              54 :                                         goto out;
    3174                 :                                 }
    3175             624 :                                 if (behavior == INTERSECT_NORMAL) {
    3176             567 :                                         if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)) {
    3177             183 :                                                 break;
    3178                 :                                         }
    3179              57 :                                 } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3180                 :                                         /* no need of looping because indexes are unique */
    3181              57 :                                         break;
    3182                 :                                 }
    3183             384 :                         }
    3184                 :                 } else {
    3185                 :                         /* ptrs[0] is present in all the arguments */
    3186                 :                         /* Skip all entries with same value as ptrs[0] */
    3187                 :                         for (;;) {
    3188             402 :                                 if (!*++ptrs[0]) {
    3189              66 :                                         goto out;
    3190                 :                                 }
    3191             336 :                                 if (behavior == INTERSECT_NORMAL) {
    3192             287 :                                         if (intersect_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
    3193             229 :                                                 break;
    3194                 :                                         }
    3195              49 :                                 } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3196                 :                                         /* no need of looping because indexes are unique */
    3197              49 :                                         break;
    3198                 :                                 }
    3199              58 :                         }
    3200                 :                 }
    3201                 :         }
    3202             767 : out:
    3203            1795 :         for (i = 0; i < arr_argc; i++) {
    3204            1028 :                 hash = Z_ARRVAL_PP(args[i]);
    3205            1028 :                 pefree(lists[i], hash->persistent);
    3206                 :         }
    3207                 : 
    3208             767 :         PHP_ARRAY_CMP_FUNC_RESTORE();
    3209                 : 
    3210             767 :         efree(ptrs);
    3211             767 :         efree(lists);
    3212             767 :         efree(args);
    3213                 : }
    3214                 : /* }}} */
    3215                 : 
    3216                 : /* {{{ proto array array_intersect_key(array arr1, array arr2 [, array ...])
    3217                 :    Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). Equivalent of array_intersect_assoc() but does not do compare of the data. */
    3218                 : PHP_FUNCTION(array_intersect_key)
    3219             161 : {
    3220             161 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_NONE);
    3221             161 : }
    3222                 : /* }}} */
    3223                 : 
    3224                 : /* {{{ proto array array_intersect_ukey(array arr1, array arr2 [, array ...], callback key_compare_func)
    3225                 :    Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). The comparison of the keys is performed by a user supplied function. Equivalent of array_intersect_uassoc() but does not do compare of the data. */
    3226                 : PHP_FUNCTION(array_intersect_ukey)
    3227             233 : {
    3228             233 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
    3229             233 : }
    3230                 : /* }}} */
    3231                 : 
    3232                 : /* {{{ proto array array_intersect(array arr1, array arr2 [, array ...])
    3233                 :    Returns the entries of arr1 that have values which are present in all the other arguments */
    3234                 : PHP_FUNCTION(array_intersect)
    3235             283 : {
    3236             283 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
    3237             283 : }
    3238                 : /* }}} */
    3239                 : 
    3240                 : /* {{{ proto array array_uintersect(array arr1, array arr2 [, array ...], callback data_compare_func)
    3241                 :    Returns the entries of arr1 that have values which are present in all the other arguments. Data is compared by using an user-supplied callback. */
    3242                 : PHP_FUNCTION(array_uintersect)
    3243             114 : {
    3244             114 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_INTERNAL);
    3245             114 : }
    3246                 : /* }}} */
    3247                 : 
    3248                 : /* {{{ proto array array_intersect_assoc(array arr1, array arr2 [, array ...])
    3249                 :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check */
    3250                 : PHP_FUNCTION(array_intersect_assoc)
    3251             279 : {
    3252             279 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_INTERNAL);
    3253             279 : }
    3254                 : /* }}} */
    3255                 : 
    3256                 : /* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array ...], callback key_compare_func) U
    3257                 :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check and they are compared by using an user-supplied callback. */
    3258                 : PHP_FUNCTION(array_intersect_uassoc)
    3259             194 : {
    3260             194 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
    3261             194 : }
    3262                 : /* }}} */
    3263                 : 
    3264                 : /* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array ...], callback data_compare_func) U
    3265                 :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Data is compared by using an user-supplied callback. */
    3266                 : PHP_FUNCTION(array_uintersect_assoc)
    3267             112 : {
    3268             112 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_USER);
    3269             112 : }
    3270                 : /* }}} */
    3271                 : 
    3272                 : /* {{{ proto array array_uintersect_uassoc(array arr1, array arr2 [, array ...], callback data_compare_func, callback key_compare_func)
    3273                 :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Both data and keys are compared by using user-supplied callbacks. */
    3274                 : PHP_FUNCTION(array_uintersect_uassoc)
    3275             141 : {
    3276             141 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_USER);
    3277             141 : }
    3278                 : /* }}} */
    3279                 : 
    3280                 : static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
    3281             416 : {
    3282                 :         Bucket *p;
    3283                 :         int argc, i;
    3284                 :         zval ***args;
    3285             416 :         int (*diff_data_compare_func)(zval **, zval ** TSRMLS_DC) = NULL;
    3286                 :         zend_bool ok;
    3287                 :         zval **data;
    3288                 : 
    3289                 :         /* Get the argument count */
    3290             416 :         argc = ZEND_NUM_ARGS();
    3291             416 :         if (data_compare_type == DIFF_COMP_DATA_USER) {
    3292             114 :                 if (argc < 3) {
    3293               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
    3294               1 :                         return;
    3295                 :                 }
    3296             113 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
    3297              30 :                         return;
    3298                 :                 }
    3299              83 :                 diff_data_compare_func = zval_user_compare;
    3300                 :         } else {
    3301             302 :                 if (argc < 2) {
    3302               4 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
    3303               4 :                         return;
    3304                 :                 }
    3305             298 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
    3306               0 :                         return;
    3307                 :                 }
    3308             298 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
    3309             136 :                         diff_data_compare_func = zval_compare;
    3310                 :                 }
    3311                 :         }
    3312                 : 
    3313             847 :         for (i = 0; i < argc; i++) {
    3314             723 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
    3315             257 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
    3316             257 :                         RETVAL_NULL();
    3317             257 :                         goto out;
    3318                 :                 }
    3319                 :         }
    3320                 : 
    3321             124 :         array_init(return_value);
    3322                 : 
    3323             990 :         for (p = Z_ARRVAL_PP(args[0])->pListHead; p != NULL; p = p->pListNext) {
    3324             866 :                 if (p->nKeyLength == 0) {
    3325             740 :                         ok = 1;
    3326            1363 :                         for (i = 1; i < argc; i++) {
    3327             774 :                                 if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == SUCCESS &&
    3328                 :                                         (!diff_data_compare_func ||
    3329                 :                                         diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)
    3330                 :                                 ) {
    3331             151 :                                         ok = 0;
    3332             151 :                                         break;
    3333                 :                                 }
    3334                 :                         }
    3335             740 :                         if (ok) {
    3336             589 :                                 Z_ADDREF_PP((zval**)p->pData);
    3337             589 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, p->pData, sizeof(zval*), NULL);
    3338                 :                         }
    3339                 :                 } else {
    3340             126 :                         ok = 1;
    3341             215 :                         for (i = 1; i < argc; i++) {
    3342             140 :                                 if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == SUCCESS &&
    3343                 :                                         (!diff_data_compare_func ||
    3344                 :                                         diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)
    3345                 :                                 ) {
    3346              51 :                                         ok = 0;
    3347              51 :                                         break;
    3348                 :                                 }
    3349                 :                         }
    3350             126 :                         if (ok) {
    3351              75 :                                 Z_ADDREF_PP((zval**)p->pData);
    3352              75 :                                 zend_hash_quick_update(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval*), NULL);
    3353                 :                         }
    3354                 :                 }
    3355                 :         }
    3356             381 : out:
    3357             381 :         efree(args);
    3358                 : }
    3359                 : /* }}} */
    3360                 : 
    3361                 : static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type) /* {{{ */
    3362             746 : {
    3363             746 :         zval ***args = NULL;
    3364                 :         HashTable *hash;
    3365                 :         int arr_argc, i, c;
    3366                 :         Bucket ***lists, **list, ***ptrs, *p;
    3367                 :         int req_args;
    3368                 :         char *param_spec;
    3369                 :         zend_fcall_info fci1, fci2;
    3370             746 :         zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
    3371                 :         zend_fcall_info *fci_key, *fci_data;
    3372                 :         zend_fcall_info_cache *fci_key_cache, *fci_data_cache;
    3373                 :         PHP_ARRAY_CMP_FUNC_VARS;
    3374                 : 
    3375                 :         int (*diff_key_compare_func)(const void *, const void * TSRMLS_DC);
    3376                 :         int (*diff_data_compare_func)(const void *, const void * TSRMLS_DC);
    3377                 : 
    3378             746 :         if (behavior == DIFF_NORMAL) {
    3379             250 :                 diff_key_compare_func = php_array_key_compare;
    3380                 : 
    3381             250 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
    3382                 :                         /* array_diff */
    3383             138 :                         req_args = 2;
    3384             138 :                         param_spec = "+";
    3385             138 :                         diff_data_compare_func = php_array_data_compare;
    3386             112 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER) {
    3387                 :                         /* array_udiff */
    3388             112 :                         req_args = 3;
    3389             112 :                         param_spec = "+f";
    3390             112 :                         diff_data_compare_func = php_array_user_compare;
    3391                 :                 } else {
    3392               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
    3393               0 :                         return;
    3394                 :                 }
    3395                 : 
    3396             250 :                 if (ZEND_NUM_ARGS() < req_args) {
    3397               3 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3398               3 :                         return;
    3399                 :                 }
    3400                 : 
    3401             247 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
    3402              30 :                         return;
    3403                 :                 }
    3404             217 :                 fci_data = &fci1;
    3405             217 :                 fci_data_cache = &fci1_cache;
    3406                 : 
    3407             496 :         } else if (behavior & DIFF_ASSOC) { /* triggered also if DIFF_KEY */
    3408                 :                 /* DIFF_KEY is subset of DIFF_ASSOC. When having the former
    3409                 :                  * no comparison of the data is done (part of DIFF_ASSOC) */
    3410                 : 
    3411             496 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
    3412                 :                         /* array_diff_assoc() or array_diff_key() */
    3413               0 :                         req_args = 2;
    3414               0 :                         param_spec = "+";
    3415               0 :                         diff_key_compare_func = php_array_key_compare;
    3416               0 :                         diff_data_compare_func = php_array_data_compare;
    3417             496 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
    3418                 :                         /* array_udiff_assoc() */
    3419               0 :                         req_args = 3;
    3420               0 :                         param_spec = "+f";
    3421               0 :                         diff_key_compare_func = php_array_key_compare;
    3422               0 :                         diff_data_compare_func = php_array_user_compare;
    3423               0 :                         fci_data = &fci1;
    3424               0 :                         fci_data_cache = &fci1_cache;
    3425             851 :                 } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) {
    3426                 :                         /* array_diff_uassoc() or array_diff_ukey() */
    3427             355 :                         req_args = 3;
    3428             355 :                         param_spec = "+f";
    3429             355 :                         diff_key_compare_func = php_array_user_key_compare;
    3430             355 :                         diff_data_compare_func = php_array_data_compare;
    3431             355 :                         fci_key = &fci1;
    3432             355 :                         fci_key_cache = &fci1_cache;
    3433             282 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) {
    3434                 :                         /* array_udiff_uassoc() */
    3435             141 :                         req_args = 4;
    3436             141 :                         param_spec = "+ff";
    3437             141 :                         diff_key_compare_func = php_array_user_key_compare;
    3438             141 :                         diff_data_compare_func = php_array_user_compare;
    3439             141 :                         fci_data = &fci1;
    3440             141 :                         fci_data_cache = &fci1_cache;
    3441             141 :                         fci_key = &fci2;
    3442             141 :                         fci_key_cache = &fci2_cache;
    3443                 :                 } else {
    3444               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
    3445               0 :                         return;
    3446                 :                 }
    3447                 : 
    3448             496 :                 if (ZEND_NUM_ARGS() < req_args) {
    3449               5 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3450               5 :                         return;
    3451                 :                 }
    3452                 : 
    3453             491 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
    3454             138 :                         return;
    3455                 :                 }
    3456                 : 
    3457                 :         } else {
    3458               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
    3459               0 :                 return;
    3460                 :         }
    3461                 : 
    3462             570 :         PHP_ARRAY_CMP_FUNC_BACKUP();
    3463                 : 
    3464                 :         /* for each argument, create and sort list with pointers to the hash buckets */
    3465             570 :         lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
    3466             570 :         ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
    3467             570 :         php_set_compare_func(PHP_SORT_STRING TSRMLS_CC);
    3468                 : 
    3469             651 :         if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) {
    3470              81 :                 BG(user_compare_fci) = *fci_data;
    3471              81 :                 BG(user_compare_fci_cache) = *fci_data_cache;
    3472             489 :         } else if (behavior & DIFF_ASSOC && key_compare_type == DIFF_COMP_KEY_USER) {
    3473             353 :                 BG(user_compare_fci) = *fci_key;
    3474             353 :                 BG(user_compare_fci_cache) = *fci_key_cache;
    3475                 :         }
    3476                 : 
    3477            1256 :         for (i = 0; i < arr_argc; i++) {
    3478            1097 :                 if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
    3479             411 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
    3480             411 :                         arr_argc = i; /* only free up to i - 1 */
    3481             411 :                         goto out;
    3482                 :                 }
    3483             686 :                 hash = Z_ARRVAL_PP(args[i]);
    3484             686 :                 list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent);
    3485             686 :                 if (!list) {
    3486               0 :                         PHP_ARRAY_CMP_FUNC_RESTORE();
    3487                 : 
    3488               0 :                         efree(ptrs);
    3489               0 :                         efree(lists);
    3490               0 :                         efree(args);
    3491               0 :                         RETURN_FALSE;
    3492                 :                 }
    3493             686 :                 lists[i] = list;
    3494             686 :                 ptrs[i] = list;
    3495            7060 :                 for (p = hash->pListHead; p; p = p->pListNext) {
    3496            6374 :                         *list++ = p;
    3497                 :                 }
    3498             686 :                 *list = NULL;
    3499             686 :                 if (behavior == DIFF_NORMAL) {
    3500             284 :                         zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_data_compare_func TSRMLS_CC);
    3501             402 :                 } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    3502             402 :                         zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_key_compare_func TSRMLS_CC);
    3503                 :                 }
    3504                 :         }
    3505                 : 
    3506                 :         /* copy the argument array */
    3507             159 :         RETVAL_ZVAL(*args[0], 1, 0);
    3508             159 :         if (return_value->value.ht == &EG(symbol_table)) {
    3509                 :                 HashTable *ht;
    3510                 :                 zval *tmp;
    3511                 : 
    3512               0 :                 ALLOC_HASHTABLE(ht);
    3513               0 :                 zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0);
    3514               0 :                 zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
    3515               0 :                 return_value->value.ht = ht;
    3516                 :         }
    3517                 : 
    3518                 :         /* go through the lists and look for values of ptr[0] that are not in the others */
    3519            1286 :         while (*ptrs[0]) {
    3520            1126 :                 if ((behavior & DIFF_ASSOC) /* triggered also when DIFF_KEY */
    3521                 :                         &&
    3522                 :                         key_compare_type == DIFF_COMP_KEY_USER
    3523                 :                 ) {
    3524             212 :                         BG(user_compare_fci) = *fci_key;
    3525             212 :                         BG(user_compare_fci_cache) = *fci_key_cache;
    3526                 :                 }
    3527            1126 :                 c = 1;
    3528            1419 :                 for (i = 1; i < arr_argc; i++) {
    3529            1156 :                         Bucket **ptr = ptrs[i];
    3530            1156 :                         if (behavior == DIFF_NORMAL) {
    3531          557062 :                                 while (*ptr && (0 < (c = diff_data_compare_func(ptrs[0], ptr TSRMLS_CC)))) {
    3532          555210 :                                         ptr++;
    3533                 :                                 }
    3534             230 :                         } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    3535            1084 :                                 while (*ptr && (0 != (c = diff_key_compare_func(ptrs[0], ptr TSRMLS_CC)))) {
    3536             624 :                                         ptr++;
    3537                 :                                 }
    3538                 :                         }
    3539            1156 :                         if (!c) {
    3540             888 :                                 if (behavior == DIFF_NORMAL) {
    3541             764 :                                         if (*ptrs[i]) {
    3542             764 :                                                 ptrs[i]++;
    3543                 :                                         }
    3544             764 :                                         break;
    3545             124 :                                 } else if (behavior == DIFF_ASSOC) {  /* only when DIFF_ASSOC */
    3546                 :                                         /* In this branch is execute only when DIFF_ASSOC. If behavior == DIFF_KEY
    3547                 :                                          * data comparison is not needed - skipped. */
    3548              70 :                                         if (*ptr) {
    3549              70 :                                                 if (data_compare_type == DIFF_COMP_DATA_USER) {
    3550              12 :                                                         BG(user_compare_fci) = *fci_data;
    3551              12 :                                                         BG(user_compare_fci_cache) = *fci_data_cache;
    3552                 :                                                 }
    3553              70 :                                                 if (diff_data_compare_func(ptrs[0], ptr TSRMLS_CC) != 0) {
    3554                 :                                                         /* the data is not the same */
    3555              25 :                                                         c = -1;
    3556              25 :                                                         if (key_compare_type == DIFF_COMP_KEY_USER) {
    3557              25 :                                                                 BG(user_compare_fci) = *fci_key;
    3558              25 :                                                                 BG(user_compare_fci_cache) = *fci_key_cache;
    3559                 :                                                         }
    3560                 :                                                 } else {
    3561              45 :                                                         break;
    3562                 :                                                         /* we have found the element in other arrays thus we don't want it
    3563                 :                                                          * in the return_value -> delete from there */
    3564                 :                                                 }
    3565                 :                                         }
    3566              54 :                                 } else if (behavior == DIFF_KEY) { /* only when DIFF_KEY */
    3567                 :                                         /* the behavior here differs from INTERSECT_KEY in php_intersect
    3568                 :                                          * since in the "diff" case we have to remove the entry from
    3569                 :                                          * return_value while when doing intersection the entry must not
    3570                 :                                          * be deleted. */
    3571              54 :                                         break; /* remove the key */
    3572                 :                                 }
    3573                 :                         }
    3574                 :                 }
    3575            1126 :                 if (!c) {
    3576                 :                         /* ptrs[0] in one of the other arguments */
    3577                 :                         /* delete all entries with value as ptrs[0] */
    3578                 :                         for (;;) {
    3579            2350 :                                 p = *ptrs[0];
    3580            2350 :                                 if (p->nKeyLength == 0) {
    3581             197 :                                         zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3582                 :                                 } else {
    3583            2153 :                                         zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
    3584                 :                                 }
    3585            2350 :                                 if (!*++ptrs[0]) {
    3586              57 :                                         goto out;
    3587                 :                                 }
    3588            2293 :                                 if (behavior == DIFF_NORMAL) {
    3589            2221 :                                         if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
    3590             734 :                                                 break;
    3591                 :                                         }
    3592              72 :                                 } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    3593                 :                                         /* in this case no array_key_compare is needed */
    3594              72 :                                         break;
    3595                 :                                 }
    3596            1487 :                         }
    3597                 :                 } else {
    3598                 :                         /* ptrs[0] in none of the other arguments */
    3599                 :                         /* skip all entries with value as ptrs[0] */
    3600                 :                         for (;;) {
    3601             277 :                                 if (!*++ptrs[0]) {
    3602             101 :                                         goto out;
    3603                 :                                 }
    3604             176 :                                 if (behavior == DIFF_NORMAL) {
    3605             106 :                                         if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
    3606              92 :                                                 break;
    3607                 :                                         }
    3608              70 :                                 } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    3609                 :                                         /* in this case no array_key_compare is needed */
    3610              70 :                                         break;
    3611                 :                                 }
    3612              14 :                         }
    3613                 :                 }
    3614                 :         }
    3615             570 : out:
    3616            1256 :         for (i = 0; i < arr_argc; i++) {
    3617             686 :                 hash = Z_ARRVAL_PP(args[i]);
    3618             686 :                 pefree(lists[i], hash->persistent);
    3619                 :         }
    3620                 : 
    3621             570 :         PHP_ARRAY_CMP_FUNC_RESTORE();
    3622                 : 
    3623             570 :         efree(ptrs);
    3624             570 :         efree(lists);
    3625             570 :         efree(args);
    3626                 : }
    3627                 : /* }}} */
    3628                 : 
    3629                 : /* {{{ proto array array_diff_key(array arr1, array arr2 [, array ...])
    3630                 :    Returns the entries of arr1 that have keys which are not present in any of the others arguments. This function is like array_diff() but works on the keys instead of the values. The associativity is preserved. */
    3631                 : PHP_FUNCTION(array_diff_key)
    3632             164 : {
    3633             164 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_NONE);
    3634             164 : }
    3635                 : /* }}} */
    3636                 : 
    3637                 : /* {{{ proto array array_diff_ukey(array arr1, array arr2 [, array ...], callback key_comp_func)
    3638                 :    Returns the entries of arr1 that have keys which are not present in any of the others arguments. User supplied function is used for comparing the keys. This function is like array_udiff() but works on the keys instead of the values. The associativity is preserved. */
    3639                 : PHP_FUNCTION(array_diff_ukey)
    3640             206 : {
    3641             206 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
    3642             206 : }
    3643                 : /* }}} */
    3644                 : 
    3645                 : /* {{{ proto array array_diff(array arr1, array arr2 [, array ...])
    3646                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments. */
    3647                 : PHP_FUNCTION(array_diff)
    3648             138 : {
    3649             138 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL);
    3650             138 : }
    3651                 : /* }}} */
    3652                 : 
    3653                 : /* {{{ proto array array_udiff(array arr1, array arr2 [, array ...], callback data_comp_func)
    3654                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments. Elements are compared by user supplied function. */
    3655                 : PHP_FUNCTION(array_udiff)
    3656             112 : {
    3657             112 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_INTERNAL);
    3658             112 : }
    3659                 : /* }}} */
    3660                 : 
    3661                 : /* {{{ proto array array_diff_assoc(array arr1, array arr2 [, array ...])
    3662                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal */
    3663                 : PHP_FUNCTION(array_diff_assoc)
    3664             138 : {
    3665             138 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_INTERNAL);
    3666             138 : }
    3667                 : /* }}} */
    3668                 : 
    3669                 : /* {{{ proto array array_diff_uassoc(array arr1, array arr2 [, array ...], callback data_comp_func)
    3670                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Elements are compared by user supplied function. */
    3671                 : PHP_FUNCTION(array_diff_uassoc)
    3672             149 : {
    3673             149 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
    3674             149 : }
    3675                 : /* }}} */
    3676                 : 
    3677                 : /* {{{ proto array array_udiff_assoc(array arr1, array arr2 [, array ...], callback key_comp_func)
    3678                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys are compared by user supplied function. */
    3679                 : PHP_FUNCTION(array_udiff_assoc)
    3680             114 : {
    3681             114 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_USER);
    3682             114 : }
    3683                 : /* }}} */
    3684                 : 
    3685                 : /* {{{ proto array array_udiff_uassoc(array arr1, array arr2 [, array ...], callback data_comp_func, callback key_comp_func)
    3686                 :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys and elements are compared by user supplied functions. */
    3687                 : PHP_FUNCTION(array_udiff_uassoc)
    3688             141 : {
    3689             141 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_USER);
    3690             141 : }
    3691                 : /* }}} */
    3692                 : 
    3693                 : #define MULTISORT_ORDER 0
    3694                 : #define MULTISORT_TYPE  1
    3695                 : #define MULTISORT_LAST  2
    3696                 : 
    3697                 : PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
    3698             114 : {
    3699             114 :         Bucket **ab = *(Bucket ***)a;
    3700             114 :         Bucket **bb = *(Bucket ***)b;
    3701                 :         int r;
    3702             114 :         int result = 0;
    3703                 :         zval temp;
    3704                 : 
    3705             114 :         r = 0;
    3706                 :         do {
    3707             120 :                 php_set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC);
    3708                 : 
    3709             120 :                 ARRAYG(compare_func)(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData) TSRMLS_CC);
    3710             120 :                 result = ARRAYG(multisort_flags)[MULTISORT_ORDER][r] * Z_LVAL(temp);
    3711             120 :                 if (result != 0) {
    3712              90 :                         return result;
    3713                 :                 }
    3714              30 :                 r++;
    3715              30 :         } while (ab[r] != NULL);
    3716                 : 
    3717              24 :         return result;
    3718                 : }
    3719                 : /* }}} */
    3720                 : 
    3721                 : #define MULTISORT_ABORT                                         \
    3722                 :         for (k = 0; k < MULTISORT_LAST; k++) \
    3723                 :                 efree(ARRAYG(multisort_flags)[k]);      \
    3724                 :         efree(arrays);                                                  \
    3725                 :         efree(args);                                                    \
    3726                 :         RETURN_FALSE;
    3727                 : 
    3728                 : /* {{{ proto bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
    3729                 :    Sort multiple arrays at once similar to how ORDER BY clause works in SQL */
    3730                 : PHP_FUNCTION(array_multisort)
    3731              99 : {
    3732                 :         zval***                 args;
    3733                 :         zval***                 arrays;
    3734                 :         Bucket***               indirect;
    3735                 :         Bucket*                 p;
    3736                 :         HashTable*              hash;
    3737                 :         int                             argc;
    3738                 :         int                             array_size;
    3739              99 :         int                             num_arrays = 0;
    3740                 :         int                             parse_state[MULTISORT_LAST];   /* 0 - flag not allowed 1 - flag allowed */
    3741              99 :         int                             sort_order = PHP_SORT_ASC;
    3742              99 :         int                             sort_type  = PHP_SORT_REGULAR;
    3743                 :         int                             i, k;
    3744                 : 
    3745              99 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
    3746               1 :                 return;
    3747                 :         }
    3748                 : 
    3749                 :         /* Allocate space for storing pointers to input arrays and sort flags. */
    3750              98 :         arrays = (zval ***)ecalloc(argc, sizeof(zval **));
    3751             294 :         for (i = 0; i < MULTISORT_LAST; i++) {
    3752             196 :                 parse_state[i] = 0;
    3753             196 :                 ARRAYG(multisort_flags)[i] = (int *)ecalloc(argc, sizeof(int));
    3754                 :         }
    3755                 : 
    3756                 :         /* Here we go through the input arguments and parse them. Each one can
    3757                 :          * be either an array or a sort flag which follows an array. If not
    3758                 :          * specified, the sort flags defaults to PHP_SORT_ASC and PHP_SORT_REGULAR
    3759                 :          * accordingly. There can't be two sort flags of the same type after an
    3760                 :          * array, and the very first argument has to be an array. */
    3761             231 :         for (i = 0; i < argc; i++) {
    3762             208 :                 if (Z_TYPE_PP(args[i]) == IS_ARRAY) {
    3763                 :                         /* We see the next array, so we update the sort flags of
    3764                 :                          * the previous array and reset the sort flags. */
    3765              82 :                         if (i > 0) {
    3766               9 :                                 ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
    3767               9 :                                 ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
    3768               9 :                                 sort_order = PHP_SORT_ASC;
    3769               9 :                                 sort_type = PHP_SORT_REGULAR;
    3770                 :                         }
    3771              82 :                         arrays[num_arrays++] = args[i];
    3772                 : 
    3773                 :                         /* Next one may be an array or a list of sort flags. */
    3774             246 :                         for (k = 0; k < MULTISORT_LAST; k++) {
    3775             164 :                                 parse_state[k] = 1;
    3776                 :                         }
    3777             126 :                 } else if (Z_TYPE_PP(args[i]) == IS_LONG) {
    3778              63 :                         switch (Z_LVAL_PP(args[i])) {
    3779                 :                                 case PHP_SORT_ASC:
    3780                 :                                 case PHP_SORT_DESC:
    3781                 :                                         /* flag allowed here */
    3782              12 :                                         if (parse_state[MULTISORT_ORDER] == 1) {
    3783                 :                                                 /* Save the flag and make sure then next arg is not the current flag. */
    3784              11 :                                                 sort_order = Z_LVAL_PP(args[i]) == PHP_SORT_DESC ? -1 : 1;
    3785              11 :                                                 parse_state[MULTISORT_ORDER] = 0;
    3786                 :                                         } else {
    3787               1 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
    3788               1 :                                                 MULTISORT_ABORT;
    3789                 :                                         }
    3790              11 :                                         break;
    3791                 : 
    3792                 :                                 case PHP_SORT_REGULAR:
    3793                 :                                 case PHP_SORT_NUMERIC:
    3794                 :                                 case PHP_SORT_STRING:
    3795                 : #if HAVE_STRCOLL
    3796                 :                                 case PHP_SORT_LOCALE_STRING:
    3797                 : #endif
    3798                 :                                         /* flag allowed here */
    3799              45 :                                         if (parse_state[MULTISORT_TYPE] == 1) {
    3800                 :                                                 /* Save the flag and make sure then next arg is not the current flag. */
    3801              40 :                                                 sort_type = Z_LVAL_PP(args[i]);
    3802              40 :                                                 parse_state[MULTISORT_TYPE] = 0;
    3803                 :                                         } else {
    3804               5 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
    3805               5 :                                                 MULTISORT_ABORT;
    3806                 :                                         }
    3807              40 :                                         break;
    3808                 : 
    3809                 :                                 default:
    3810               6 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is an unknown sort flag", i + 1);
    3811               6 :                                         MULTISORT_ABORT;
    3812                 :                                         break;
    3813                 : 
    3814                 :                         }
    3815                 :                 } else {
    3816              63 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or a sort flag", i + 1);
    3817              63 :                         MULTISORT_ABORT;
    3818                 :                 }
    3819                 :         }
    3820                 :         /* Take care of the last array sort flags. */
    3821              23 :         ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
    3822              23 :         ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
    3823                 : 
    3824                 :         /* Make sure the arrays are of the same size. */
    3825              23 :         array_size = zend_hash_num_elements(Z_ARRVAL_PP(arrays[0]));
    3826              52 :         for (i = 0; i < num_arrays; i++) {
    3827              32 :                 if (zend_hash_num_elements(Z_ARRVAL_PP(arrays[i])) != array_size) {
    3828               3 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array sizes are inconsistent");
    3829               3 :                         MULTISORT_ABORT;
    3830                 :                 }
    3831                 :         }
    3832                 : 
    3833                 :         /* If all arrays are empty we don't need to do anything. */
    3834              20 :         if (array_size < 1) {
    3835               3 :                 for (k = 0; k < MULTISORT_LAST; k++) {
    3836               2 :                         efree(ARRAYG(multisort_flags)[k]);
    3837                 :                 }
    3838               1 :                 efree(arrays);
    3839               1 :                 efree(args);
    3840               1 :                 RETURN_TRUE;
    3841                 :         }
    3842                 : 
    3843                 :         /* Create the indirection array. This array is of size MxN, where
    3844                 :          * M is the number of entries in each input array and N is the number
    3845                 :          * of the input arrays + 1. The last column is NULL to indicate the end
    3846                 :          * of the row. */
    3847              19 :         indirect = (Bucket ***)safe_emalloc(array_size, sizeof(Bucket **), 0);
    3848              96 :         for (i = 0; i < array_size; i++) {
    3849              77 :                 indirect[i] = (Bucket **)safe_emalloc((num_arrays + 1), sizeof(Bucket *), 0);
    3850                 :         }
    3851              44 :         for (i = 0; i < num_arrays; i++) {
    3852              25 :                 k = 0;
    3853             123 :                 for (p = Z_ARRVAL_PP(arrays[i])->pListHead; p; p = p->pListNext, k++) {
    3854              98 :                         indirect[k][i] = p;
    3855                 :                 }
    3856                 :         }
    3857              96 :         for (k = 0; k < array_size; k++) {
    3858              77 :                 indirect[k][num_arrays] = NULL;
    3859                 :         }
    3860                 : 
    3861                 :         /* Do the actual sort magic - bada-bim, bada-boom. */
    3862              19 :         zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC);
    3863                 : 
    3864                 :         /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */
    3865              19 :         HANDLE_BLOCK_INTERRUPTIONS();
    3866              44 :         for (i = 0; i < num_arrays; i++) {
    3867              25 :                 hash = Z_ARRVAL_PP(arrays[i]);
    3868              25 :                 hash->pListHead = indirect[0][i];;
    3869              25 :                 hash->pListTail = NULL;
    3870              25 :                 hash->pInternalPointer = hash->pListHead;
    3871                 : 
    3872             123 :                 for (k = 0; k < array_size; k++) {
    3873              98 :                         if (hash->pListTail) {
    3874              73 :                                 hash->pListTail->pListNext = indirect[k][i];
    3875                 :                         }
    3876              98 :                         indirect[k][i]->pListLast = hash->pListTail;
    3877              98 :                         indirect[k][i]->pListNext = NULL;
    3878              98 :                         hash->pListTail = indirect[k][i];
    3879                 :                 }
    3880                 : 
    3881              25 :                 p = hash->pListHead;
    3882              25 :                 k = 0;
    3883             148 :                 while (p != NULL) {
    3884              98 :                         if (p->nKeyLength == 0)
    3885              59 :                                 p->h = k++;
    3886              98 :                         p = p->pListNext;
    3887                 :                 }
    3888              25 :                 hash->nNextFreeElement = array_size;
    3889              25 :                 zend_hash_rehash(hash);
    3890                 :         }
    3891              19 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    3892                 : 
    3893                 :         /* Clean up. */
    3894              96 :         for (i = 0; i < array_size; i++) {
    3895              77 :                 efree(indirect[i]);
    3896                 :         }
    3897              19 :         efree(indirect);
    3898              57 :         for (k = 0; k < MULTISORT_LAST; k++) {
    3899              38 :                 efree(ARRAYG(multisort_flags)[k]);
    3900                 :         }
    3901              19 :         efree(arrays);
    3902              19 :         efree(args);
    3903              19 :         RETURN_TRUE;
    3904                 : }
    3905                 : /* }}} */
    3906                 : 
    3907                 : /* {{{ proto mixed array_rand(array input [, int num_req])
    3908                 :    Return key/keys for random entry/entries in the array */
    3909                 : PHP_FUNCTION(array_rand)
    3910             363 : {
    3911                 :         zval *input;
    3912             363 :         long randval, num_req = 1;
    3913                 :         int num_avail, key_type;
    3914                 :         char *string_key;
    3915                 :         uint string_key_len;
    3916                 :         ulong num_key;
    3917                 :         HashPosition pos;
    3918                 : 
    3919             363 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &input, &num_req) == FAILURE) {
    3920              32 :                 return;
    3921                 :         }
    3922                 : 
    3923             331 :         num_avail = zend_hash_num_elements(Z_ARRVAL_P(input));
    3924                 : 
    3925             331 :         if (ZEND_NUM_ARGS() > 1) {
    3926             313 :                 if (num_req <= 0 || num_req > num_avail) {
    3927              21 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument has to be between 1 and the number of elements in the array");
    3928              21 :                         return;
    3929                 :                 }
    3930                 :         }
    3931                 : 
    3932                 :         /* Make the return value an array only if we need to pass back more than one result. */
    3933             310 :         if (num_req > 1) {
    3934              25 :                 array_init_size(return_value, num_req);
    3935                 :         }
    3936                 : 
    3937                 :         /* We can't use zend_hash_index_find() because the array may have string keys or gaps. */
    3938             310 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    3939            1455 :         while (num_req && (key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
    3940                 : 
    3941            1119 :                 randval = php_rand(TSRMLS_C);
    3942                 : 
    3943            1119 :                 if ((double) (randval / (PHP_RAND_MAX + 1.0)) < (double) num_req / (double) num_avail) {
    3944                 :                         /* If we are returning a single result, just do it. */
    3945             760 :                         if (Z_TYPE_P(return_value) != IS_ARRAY) {
    3946             284 :                                 if (key_type == HASH_KEY_IS_STRING) {
    3947               7 :                                         RETURN_STRINGL(string_key, string_key_len - 1, 1);
    3948                 :                                 } else {
    3949             277 :                                         RETURN_LONG(num_key);
    3950                 :                                 }
    3951                 :                         } else {
    3952                 :                                 /* Append the result to the return value. */
    3953             476 :                                 if (key_type == HASH_KEY_IS_STRING) {
    3954              19 :                                         add_next_index_stringl(return_value, string_key, string_key_len - 1, 1);
    3955                 :                                 } else {
    3956             457 :                                         add_next_index_long(return_value, num_key);
    3957                 :                                 }
    3958                 :                         }
    3959             476 :                         num_req--;
    3960                 :                 }
    3961             835 :                 num_avail--;
    3962             835 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
    3963                 :         }
    3964                 : }
    3965                 : /* }}} */
    3966                 : 
    3967                 : /* {{{ proto mixed array_sum(array input)
    3968                 :    Returns the sum of the array entries */
    3969                 : PHP_FUNCTION(array_sum)
    3970              58 : {
    3971                 :         zval *input,
    3972                 :                  **entry,
    3973                 :                  entry_n;
    3974                 :         HashPosition pos;
    3975                 :         double dval;
    3976                 : 
    3977              58 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
    3978              25 :                 return;
    3979                 :         }
    3980                 : 
    3981              33 :         ZVAL_LONG(return_value, 0);
    3982                 : 
    3983              33 :         for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    3984          202212 :                 zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS;
    3985                 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos)
    3986          202146 :         ) {
    3987          202146 :                 if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) {
    3988                 :                         continue;
    3989                 :                 }
    3990          202138 :                 entry_n = **entry;
    3991          202138 :                 zval_copy_ctor(&entry_n);
    3992          202138 :                 convert_scalar_to_number(&entry_n TSRMLS_CC);
    3993                 : 
    3994          202138 :                 if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
    3995          133157 :                         dval = (double)Z_LVAL_P(return_value) + (double)Z_LVAL(entry_n);
    3996          133157 :                         if ( (double)LONG_MIN <= dval && dval <= (double)LONG_MAX ) {
    3997          133155 :                                 Z_LVAL_P(return_value) += Z_LVAL(entry_n);
    3998          133155 :                                 continue;
    3999                 :                         }
    4000                 :                 }
    4001           68983 :                 convert_to_double(return_value);
    4002           68983 :                 convert_to_double(&entry_n);
    4003           68983 :                 Z_DVAL_P(return_value) += Z_DVAL(entry_n);
    4004                 :         }
    4005                 : }
    4006                 : /* }}} */
    4007                 : 
    4008                 : /* {{{ proto mixed array_product(array input)
    4009                 :    Returns the product of the array entries */
    4010                 : PHP_FUNCTION(array_product)
    4011              52 : {
    4012                 :         zval *input,
    4013                 :                  **entry,
    4014                 :                  entry_n;
    4015                 :         HashPosition pos;
    4016                 :         double dval;
    4017                 : 
    4018              52 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
    4019              29 :                 return;
    4020                 :         }
    4021                 : 
    4022              23 :         if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
    4023               1 :                 RETURN_LONG(0);
    4024                 :         }
    4025              22 :         ZVAL_LONG(return_value, 1);
    4026                 : 
    4027              22 :         for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    4028            1076 :                 zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS;
    4029                 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos)
    4030            1032 :         ) {
    4031            1032 :                 if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) {
    4032                 :                         continue;
    4033                 :                 }
    4034            1030 :                 entry_n = **entry;
    4035            1030 :                 zval_copy_ctor(&entry_n);
    4036            1030 :                 convert_scalar_to_number(&entry_n TSRMLS_CC);
    4037                 : 
    4038            1030 :                 if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
    4039              25 :                         dval = (double)Z_LVAL_P(return_value) * (double)Z_LVAL(entry_n);
    4040              25 :                         if ( (double)LONG_MIN <= dval && dval <= (double)LONG_MAX ) {
    4041              23 :                                 Z_LVAL_P(return_value) *= Z_LVAL(entry_n);
    4042              23 :                                 continue;
    4043                 :                         }
    4044                 :                 }
    4045            1007 :                 convert_to_double(return_value);
    4046            1007 :                 convert_to_double(&entry_n);
    4047            1007 :                 Z_DVAL_P(return_value) *= Z_DVAL(entry_n);
    4048                 :         }
    4049                 : }
    4050                 : /* }}} */
    4051                 : 
    4052                 : /* {{{ proto mixed array_reduce(array input, mixed callback [, mixed initial])
    4053                 :    Iteratively reduce the array to a single value via the callback. */
    4054                 : PHP_FUNCTION(array_reduce)
    4055              72 : {
    4056                 :         zval *input;
    4057                 :         zval **args[2];
    4058                 :         zval **operand;
    4059              72 :         zval *result = NULL;
    4060                 :         zval *retval;
    4061                 :         zend_fcall_info fci;
    4062              72 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4063              72 :         zval *initial = NULL;
    4064                 :         HashPosition pos;
    4065                 :         HashTable *htbl;
    4066                 : 
    4067              72 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af|z", &input, &fci, &fci_cache, &initial) == FAILURE) {
    4068               5 :                 return;
    4069                 :         }
    4070                 : 
    4071              67 :         if (ZEND_NUM_ARGS() > 2) {
    4072              15 :                 ALLOC_ZVAL(result);
    4073              15 :                 *result = *initial;
    4074              15 :                 zval_copy_ctor(result);
    4075              15 :                 INIT_PZVAL(result);
    4076                 :         } else {
    4077              52 :                 MAKE_STD_ZVAL(result);
    4078              52 :                 ZVAL_NULL(result);
    4079                 :         }
    4080                 : 
    4081                 :         /* (zval **)input points to an element of argument stack
    4082                 :          * the base pointer of which is subject to change.
    4083                 :          * thus we need to keep the pointer to the hashtable for safety */
    4084              67 :         htbl = Z_ARRVAL_P(input);
    4085                 : 
    4086              67 :         if (zend_hash_num_elements(htbl) == 0) {
    4087               1 :                 if (result) {
    4088               1 :                         RETVAL_ZVAL(result, 1, 1);
    4089                 :                 }
    4090               1 :                 return;
    4091                 :         }
    4092                 : 
    4093              66 :         fci.retval_ptr_ptr = &retval;
    4094              66 :         fci.param_count = 2;
    4095              66 :         fci.no_separation = 0;
    4096                 : 
    4097              66 :         zend_hash_internal_pointer_reset_ex(htbl, &pos);
    4098           21873 :         while (zend_hash_get_current_data_ex(htbl, (void **)&operand, &pos) == SUCCESS) {
    4099                 : 
    4100           21741 :                 if (result) {
    4101           21741 :                         args[0] = &result;
    4102           21741 :                         args[1] = operand;
    4103           21741 :                         fci.params = args;
    4104                 : 
    4105           21741 :                         if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) {
    4106           21741 :                                 zval_ptr_dtor(&result);
    4107           21741 :                                 result = retval;
    4108                 :                         } else {
    4109               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the reduction callback");
    4110               0 :                                 return;
    4111                 :                         }
    4112                 :                 } else {
    4113               0 :                         result = *operand;
    4114               0 :                         zval_add_ref(&result);
    4115                 :                 }
    4116           21741 :                 zend_hash_move_forward_ex(htbl, &pos);
    4117                 :         }
    4118              66 :         RETVAL_ZVAL(result, 1, 1);
    4119                 : }
    4120                 : /* }}} */
    4121                 : 
    4122                 : /* {{{ proto array array_filter(array input [, mixed callback])
    4123                 :    Filters elements from the array via the callback. */
    4124                 : PHP_FUNCTION(array_filter)
    4125             117 : {
    4126                 :         zval *array;
    4127                 :         zval **operand;
    4128                 :         zval **args[1];
    4129             117 :         zval *retval = NULL;
    4130             117 :         zend_bool have_callback = 0;
    4131                 :         char *string_key;
    4132             117 :         zend_fcall_info fci = empty_fcall_info;
    4133             117 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4134                 :         uint string_key_len;
    4135                 :         ulong num_key;
    4136                 :         HashPosition pos;
    4137                 : 
    4138             117 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|f", &array, &fci, &fci_cache) == FAILURE) {
    4139              59 :                 return;
    4140                 :         }
    4141                 : 
    4142              58 :         array_init(return_value);
    4143              58 :         if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
    4144               1 :                 return;
    4145                 :         }
    4146                 : 
    4147              57 :         if (ZEND_NUM_ARGS() > 1) {
    4148              45 :                 have_callback = 1;
    4149              45 :                 fci.no_separation = 0;
    4150              45 :                 fci.retval_ptr_ptr = &retval;
    4151              45 :                 fci.param_count = 1;
    4152                 :         }
    4153                 : 
    4154              57 :         for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
    4155            1097 :                 zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS;
    4156                 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
    4157             983 :         ) {
    4158             983 :                 if (have_callback) {
    4159             922 :                         args[0] = operand;
    4160             922 :                         fci.params = args;
    4161                 : 
    4162             922 :                         if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) {
    4163             922 :                                 if (!zend_is_true(retval)) {
    4164             121 :                                         zval_ptr_dtor(&retval);
    4165             121 :                                         continue;
    4166                 :                                 } else {
    4167             801 :                                         zval_ptr_dtor(&retval);
    4168                 :                                 }
    4169                 :                         } else {
    4170               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback");
    4171               0 :                                 return;
    4172                 :                         }
    4173              61 :                 } else if (!zend_is_true(*operand)) {
    4174              26 :                         continue;
    4175                 :                 }
    4176                 : 
    4177             836 :                 zval_add_ref(operand);
    4178             836 :                 switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos)) {
    4179                 :                         case HASH_KEY_IS_STRING:
    4180              15 :                                 zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, operand, sizeof(zval *), NULL);
    4181              15 :                                 break;
    4182                 : 
    4183                 :                         case HASH_KEY_IS_LONG:
    4184             821 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, operand, sizeof(zval *), NULL);
    4185                 :                                 break;
    4186                 :                 }
    4187                 :         }
    4188                 : }
    4189                 : /* }}} */
    4190                 : 
    4191                 : /* {{{ proto array array_map(mixed callback, array input1 [, array input2 ,...])
    4192                 :    Applies the callback to the elements in given arrays. */
    4193                 : PHP_FUNCTION(array_map)
    4194             297 : {
    4195             297 :         zval ***arrays = NULL;
    4196             297 :         int n_arrays = 0;
    4197                 :         zval ***params;
    4198                 :         zval *result, *null;
    4199                 :         HashPosition *array_pos;
    4200                 :         zval **args;
    4201             297 :         zend_fcall_info fci = empty_fcall_info;
    4202             297 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4203             297 :         int i, k, maxlen = 0;
    4204                 :         int *array_len;
    4205                 : 
    4206             297 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f!+", &fci, &fci_cache, &arrays, &n_arrays) == FAILURE) {
    4207              43 :                 return;
    4208                 :         }
    4209                 : 
    4210             254 :         RETVAL_NULL();
    4211                 : 
    4212             254 :         args = (zval **)safe_emalloc(n_arrays, sizeof(zval *), 0);
    4213             254 :         array_len = (int *)safe_emalloc(n_arrays, sizeof(int), 0);
    4214             254 :         array_pos = (HashPosition *)safe_emalloc(n_arrays, sizeof(HashPosition), 0);
    4215                 : 
    4216             511 :         for (i = 0; i < n_arrays; i++) {
    4217             283 :                 if (Z_TYPE_PP(arrays[i]) != IS_ARRAY) {
    4218              26 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 2);
    4219              26 :                         efree(arrays);
    4220              26 :                         efree(args);
    4221              26 :                         efree(array_len);
    4222              26 :                         efree(array_pos);
    4223              26 :                         return;
    4224                 :                 }
    4225             257 :                 SEPARATE_ZVAL_IF_NOT_REF(arrays[i]);
    4226             257 :                 args[i] = *arrays[i];
    4227             257 :                 array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(arrays[i]));
    4228             257 :                 if (array_len[i] > maxlen) {
    4229             202 :                         maxlen = array_len[i];
    4230                 :                 }
    4231             257 :                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arrays[i]), &array_pos[i]);
    4232                 :         }
    4233                 : 
    4234             228 :         efree(arrays);
    4235                 : 
    4236                 :         /* Short-circuit: if no callback and only one array, just return it. */
    4237             228 :         if (!ZEND_FCI_INITIALIZED(fci) && n_arrays == 1) {
    4238               3 :                 RETVAL_ZVAL(args[0], 1, 0);
    4239               3 :                 efree(array_len);
    4240               3 :                 efree(array_pos);
    4241               3 :                 efree(args);
    4242               3 :                 return;
    4243                 :         }
    4244                 : 
    4245             225 :         array_init_size(return_value, maxlen);
    4246             225 :         params = (zval ***)safe_emalloc(n_arrays, sizeof(zval **), 0);
    4247             225 :         MAKE_STD_ZVAL(null);
    4248             225 :         ZVAL_NULL(null);
    4249                 : 
    4250                 :         /* We iterate through all the arrays at once. */
    4251            1113 :         for (k = 0; k < maxlen; k++) {
    4252                 :                 uint str_key_len;
    4253                 :                 ulong num_key;
    4254                 :                 char *str_key;
    4255             890 :                 int key_type = 0;
    4256                 : 
    4257                 :                 /* If no callback, the result will be an array, consisting of current
    4258                 :                  * entries from all arrays. */
    4259             890 :                 if (!ZEND_FCI_INITIALIZED(fci)) {
    4260              14 :                         MAKE_STD_ZVAL(result);
    4261              14 :                         array_init_size(result, n_arrays);
    4262                 :                 }
    4263                 : 
    4264            1857 :                 for (i = 0; i < n_arrays; i++) {
    4265                 :                         /* If this array still has elements, add the current one to the
    4266                 :                          * parameter list, otherwise use null value. */
    4267             967 :                         if (k < array_len[i]) {
    4268             955 :                                 zend_hash_get_current_data_ex(Z_ARRVAL_P(args[i]), (void **)&params[i], &array_pos[i]);
    4269                 : 
    4270                 :                                 /* It is safe to store only last value of key type, because
    4271                 :                                  * this loop will run just once if there is only 1 array. */
    4272             955 :                                 if (n_arrays == 1) {
    4273             827 :                                         key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(args[0]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]);
    4274                 :                                 }
    4275             955 :                                 zend_hash_move_forward_ex(Z_ARRVAL_P(args[i]), &array_pos[i]);
    4276                 :                         } else {
    4277              12 :                                 params[i] = &null;
    4278                 :                         }
    4279                 : 
    4280             967 :                         if (!ZEND_FCI_INITIALIZED(fci)) {
    4281              37 :                                 zval_add_ref(params[i]);
    4282              37 :                                 add_next_index_zval(result, *params[i]);
    4283                 :                         }
    4284                 :                 }
    4285                 : 
    4286             890 :                 if (ZEND_FCI_INITIALIZED(fci)) {
    4287             876 :                         fci.retval_ptr_ptr = &result;
    4288             876 :                         fci.param_count = n_arrays;
    4289             876 :                         fci.params = params;
    4290             876 :                         fci.no_separation = 0;
    4291                 : 
    4292             876 :                         if (zend_call_function(&fci, &fci_cache TSRMLS_CC) != SUCCESS || !result) {
    4293               2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the map callback");
    4294               2 :                                 efree(array_len);
    4295               2 :                                 efree(args);
    4296               2 :                                 efree(array_pos);
    4297               2 :                                 zval_dtor(return_value);
    4298               2 :                                 zval_ptr_dtor(&null);
    4299               2 :                                 efree(params);
    4300               2 :                                 RETURN_NULL();
    4301                 :                         }
    4302                 :                 }
    4303                 : 
    4304             888 :                 if (n_arrays > 1) {
    4305              62 :                         add_next_index_zval(return_value, result);
    4306                 :                 } else {
    4307             826 :                         if (key_type == HASH_KEY_IS_STRING) {
    4308             114 :                                 add_assoc_zval_ex(return_value, str_key, str_key_len, result);
    4309                 :                         } else {
    4310             712 :                                 add_index_zval(return_value, num_key, result);
    4311                 :                         }
    4312                 :                 }
    4313                 :         }
    4314                 : 
    4315             223 :         zval_ptr_dtor(&null);
    4316             223 :         efree(params);
    4317             223 :         efree(array_len);
    4318             223 :         efree(array_pos);
    4319             223 :         efree(args);
    4320                 : }
    4321                 : /* }}} */
    4322                 : 
    4323                 : /* {{{ proto bool array_key_exists(mixed key, array search)
    4324                 :    Checks if the given key or index exists in the array */
    4325                 : PHP_FUNCTION(array_key_exists)
    4326           76157 : {
    4327                 :         zval *key;                                      /* key to check for */
    4328                 :         HashTable *array;                       /* array to check in */
    4329                 : 
    4330           76157 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zH", &key, &array) == FAILURE) {
    4331              35 :                 return;
    4332                 :         }
    4333                 : 
    4334           76122 :         switch (Z_TYPE_P(key)) {
    4335                 :                 case IS_STRING:
    4336           75826 :                         if (zend_symtable_exists(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1)) {
    4337            8796 :                                 RETURN_TRUE;
    4338                 :                         }
    4339           67030 :                         RETURN_FALSE;
    4340                 :                 case IS_LONG:
    4341             223 :                         if (zend_hash_index_exists(array, Z_LVAL_P(key))) {
    4342              93 :                                 RETURN_TRUE;
    4343                 :                         }
    4344             130 :                         RETURN_FALSE;
    4345                 :                 case IS_NULL:
    4346              55 :                         if (zend_hash_exists(array, "", 1)) {
    4347              27 :                                 RETURN_TRUE;
    4348                 :                         }
    4349              28 :                         RETURN_FALSE;
    4350                 : 
    4351                 :                 default:
    4352              18 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be either a string or an integer");
    4353              18 :                         RETURN_FALSE;
    4354                 :         }
    4355                 : }
    4356                 : /* }}} */
    4357                 : 
    4358                 : /* {{{ proto array array_chunk(array input, int size [, bool preserve_keys])
    4359                 :    Split array into chunks */
    4360                 : PHP_FUNCTION(array_chunk)
    4361             521 : {
    4362             521 :         int argc = ZEND_NUM_ARGS(), key_type, num_in;
    4363             521 :         long size, current = 0;
    4364                 :         char *str_key;
    4365                 :         uint str_key_len;
    4366                 :         ulong num_key;
    4367             521 :         zend_bool preserve_keys = 0;
    4368             521 :         zval *input = NULL;
    4369             521 :         zval *chunk = NULL;
    4370                 :         zval **entry;
    4371                 :         HashPosition pos;
    4372                 : 
    4373             521 :         if (zend_parse_parameters(argc TSRMLS_CC, "al|b", &input, &size, &preserve_keys) == FAILURE) {
    4374             106 :                 return;
    4375                 :         }
    4376                 :         /* Do bounds checking for size parameter. */
    4377             415 :         if (size < 1) {
    4378             107 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size parameter expected to be greater than 0");
    4379             107 :                 return;
    4380                 :         }
    4381                 : 
    4382             308 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
    4383                 : 
    4384             308 :         if (size > num_in) {
    4385              34 :                 size = num_in > 0 ? num_in : 1;
    4386                 :         }
    4387                 : 
    4388             308 :         array_init_size(return_value, ((num_in - 1) / size) + 1);
    4389                 : 
    4390             308 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
    4391            2084 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void**)&entry, &pos) == SUCCESS) {
    4392                 :                 /* If new chunk, create and initialize it. */
    4393            1468 :                 if (!chunk) {
    4394             683 :                         MAKE_STD_ZVAL(chunk);
    4395             683 :                         array_init_size(chunk, size);
    4396                 :                 }
    4397                 : 
    4398                 :                 /* Add entry to the chunk, preserving keys if necessary. */
    4399            1468 :                 zval_add_ref(entry);
    4400                 : 
    4401            1468 :                 if (preserve_keys) {
    4402             507 :                         key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key, &str_key_len, &num_key, 0, &pos);
    4403             507 :                         switch (key_type) {
    4404                 :                                 case HASH_KEY_IS_STRING:
    4405              93 :                                         add_assoc_zval_ex(chunk, str_key, str_key_len, *entry);
    4406              93 :                                         break;
    4407                 :                                 default:
    4408             414 :                                         add_index_zval(chunk, num_key, *entry);
    4409                 :                                         break;
    4410                 :                         }
    4411                 :                 } else {
    4412             961 :                         add_next_index_zval(chunk, *entry);
    4413                 :                 }
    4414                 : 
    4415                 :                 /* If reached the chunk size, add it to the result array, and reset the
    4416                 :                  * pointer. */
    4417            1468 :                 if (!(++current % size)) {
    4418             576 :                         add_next_index_zval(return_value, chunk);
    4419             576 :                         chunk = NULL;
    4420                 :                 }
    4421                 : 
    4422            1468 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
    4423                 :         }
    4424                 : 
    4425                 :         /* Add the final chunk if there is one. */
    4426             308 :         if (chunk) {
    4427             107 :                 add_next_index_zval(return_value, chunk);
    4428                 :         }
    4429                 : }
    4430                 : /* }}} */
    4431                 : 
    4432                 : /* {{{ proto array array_combine(array keys, array values)
    4433                 :    Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values */
    4434                 : PHP_FUNCTION(array_combine)
    4435             118 : {
    4436                 :         zval *values, *keys;
    4437                 :         HashPosition pos_values, pos_keys;
    4438                 :         zval **entry_keys, **entry_values;
    4439                 :         int num_keys, num_values;
    4440                 : 
    4441             118 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &keys, &values) == FAILURE) {
    4442              51 :                 return;
    4443                 :         }
    4444                 : 
    4445              67 :         num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
    4446              67 :         num_values = zend_hash_num_elements(Z_ARRVAL_P(values));
    4447                 : 
    4448              67 :         if (num_keys != num_values) {
    4449               3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have an equal number of elements");
    4450               3 :                 RETURN_FALSE;
    4451                 :         }
    4452                 : 
    4453              64 :         if (!num_keys) {
    4454               4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have at least 1 element");
    4455               4 :                 RETURN_FALSE;
    4456                 :         }
    4457                 : 
    4458              60 :         array_init_size(return_value, num_keys);
    4459                 : 
    4460              60 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos_keys);
    4461              60 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);
    4462             301 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry_keys, &pos_keys) == SUCCESS &&
    4463                 :                 zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&entry_values, &pos_values) == SUCCESS
    4464                 :         ) {
    4465             181 :                 if (Z_TYPE_PP(entry_keys) == IS_LONG) {
    4466              43 :                         zval_add_ref(entry_values);
    4467              43 :                         add_index_zval(return_value, Z_LVAL_PP(entry_keys), *entry_values);
    4468                 :                 } else {
    4469             138 :                         zval key, *key_ptr = *entry_keys;
    4470                 : 
    4471             138 :                         if (Z_TYPE_PP(entry_keys) != IS_STRING) {
    4472              40 :                                 key = **entry_keys;
    4473              40 :                                 zval_copy_ctor(&key);
    4474              40 :                                 convert_to_string(&key);
    4475              40 :                                 key_ptr = &key;
    4476                 :                         }
    4477                 : 
    4478             138 :                         zval_add_ref(entry_values);
    4479             138 :                         add_assoc_zval_ex(return_value, Z_STRVAL_P(key_ptr), Z_STRLEN_P(key_ptr) + 1, *entry_values);
    4480                 : 
    4481             138 :                         if (key_ptr != *entry_keys) {
    4482              40 :                                 zval_dtor(&key);
    4483                 :                         }
    4484                 :                 }
    4485                 : 
    4486             181 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos_keys);
    4487             181 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values);
    4488                 :         }
    4489                 : }
    4490                 : /* }}} */
    4491                 : 
    4492                 : /*
    4493                 :  * Local variables:
    4494                 :  * tab-width: 4
    4495                 :  * c-basic-offset: 4
    4496                 :  * End:
    4497                 :  * vim600: noet sw=4 ts=4 fdm=marker
    4498                 :  * vim<600: noet sw=4 ts=4
    4499                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:13 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.