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

LCOV - code coverage report
Current view: top level - ext/standard - string.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 2472 2584 95.7 %
Date: 2016-07-19 Functions: 111 114 97.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2016 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: Rasmus Lerdorf <rasmus@php.net>                             |
      16             :    |          Stig S�ther Bakken <ssb@php.net>                          |
      17             :    |          Zeev Suraski <zeev@zend.com>                                |
      18             :    +----------------------------------------------------------------------+
      19             :  */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : /* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */
      24             : 
      25             : #include <stdio.h>
      26             : #include "php.h"
      27             : #include "php_rand.h"
      28             : #include "php_string.h"
      29             : #include "php_variables.h"
      30             : #ifdef HAVE_LOCALE_H
      31             : # include <locale.h>
      32             : #endif
      33             : #ifdef HAVE_LANGINFO_H
      34             : # include <langinfo.h>
      35             : #endif
      36             : #ifdef HAVE_MONETARY_H
      37             : # include <monetary.h>
      38             : #endif
      39             : /*
      40             :  * This define is here because some versions of libintl redefine setlocale
      41             :  * to point to libintl_setlocale.  That's a ridiculous thing to do as far
      42             :  * as I am concerned, but with this define and the subsequent undef we
      43             :  * limit the damage to just the actual setlocale() call in this file
      44             :  * without turning zif_setlocale into zif_libintl_setlocale.  -Rasmus
      45             :  */
      46             : #define php_my_setlocale setlocale
      47             : #ifdef HAVE_LIBINTL
      48             : # include <libintl.h> /* For LC_MESSAGES */
      49             :  #ifdef setlocale
      50             :  # undef setlocale
      51             :  #endif
      52             : #endif
      53             : 
      54             : #include "scanf.h"
      55             : #include "zend_API.h"
      56             : #include "zend_execute.h"
      57             : #include "php_globals.h"
      58             : #include "basic_functions.h"
      59             : #include "zend_smart_str.h"
      60             : #include <Zend/zend_exceptions.h>
      61             : #ifdef ZTS
      62             : #include "TSRM.h"
      63             : #endif
      64             : 
      65             : /* For str_getcsv() support */
      66             : #include "ext/standard/file.h"
      67             : 
      68             : #define STR_PAD_LEFT                    0
      69             : #define STR_PAD_RIGHT                   1
      70             : #define STR_PAD_BOTH                    2
      71             : #define PHP_PATHINFO_DIRNAME    1
      72             : #define PHP_PATHINFO_BASENAME   2
      73             : #define PHP_PATHINFO_EXTENSION  4
      74             : #define PHP_PATHINFO_FILENAME   8
      75             : #define PHP_PATHINFO_ALL        (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION | PHP_PATHINFO_FILENAME)
      76             : 
      77             : #define STR_STRSPN                              0
      78             : #define STR_STRCSPN                             1
      79             : 
      80             : /* {{{ register_string_constants
      81             :  */
      82       23409 : void register_string_constants(INIT_FUNC_ARGS)
      83             : {
      84       23409 :         REGISTER_LONG_CONSTANT("STR_PAD_LEFT", STR_PAD_LEFT, CONST_CS | CONST_PERSISTENT);
      85       23409 :         REGISTER_LONG_CONSTANT("STR_PAD_RIGHT", STR_PAD_RIGHT, CONST_CS | CONST_PERSISTENT);
      86       23409 :         REGISTER_LONG_CONSTANT("STR_PAD_BOTH", STR_PAD_BOTH, CONST_CS | CONST_PERSISTENT);
      87       23409 :         REGISTER_LONG_CONSTANT("PATHINFO_DIRNAME", PHP_PATHINFO_DIRNAME, CONST_CS | CONST_PERSISTENT);
      88       23409 :         REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT);
      89       23409 :         REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);
      90       23409 :         REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
      91             : 
      92             : #ifdef HAVE_LOCALECONV
      93             :         /* If last members of struct lconv equal CHAR_MAX, no grouping is done */
      94             : 
      95             : /* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */
      96             : # ifndef HAVE_LIMITS_H
      97             : # define CHAR_MAX 127
      98             : # endif
      99             : 
     100       23409 :         REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT);
     101             : #endif
     102             : 
     103             : #ifdef HAVE_LOCALE_H
     104       23409 :         REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT);
     105       23409 :         REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT);
     106       23409 :         REGISTER_LONG_CONSTANT("LC_TIME", LC_TIME, CONST_CS | CONST_PERSISTENT);
     107       23409 :         REGISTER_LONG_CONSTANT("LC_COLLATE", LC_COLLATE, CONST_CS | CONST_PERSISTENT);
     108       23409 :         REGISTER_LONG_CONSTANT("LC_MONETARY", LC_MONETARY, CONST_CS | CONST_PERSISTENT);
     109       23409 :         REGISTER_LONG_CONSTANT("LC_ALL", LC_ALL, CONST_CS | CONST_PERSISTENT);
     110             : # ifdef LC_MESSAGES
     111       23409 :         REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
     112             : # endif
     113             : #endif
     114             : 
     115       23409 : }
     116             : /* }}} */
     117             : 
     118             : int php_tag_find(char *tag, size_t len, const char *set);
     119             : 
     120             : #ifdef PHP_WIN32
     121             : # define SET_ALIGNED(alignment, decl) __declspec(align(alignment)) decl
     122             : #elif HAVE_ATTRIBUTE_ALIGNED
     123             : # define SET_ALIGNED(alignment, decl) decl __attribute__ ((__aligned__ (alignment)))
     124             : #else
     125             : # define SET_ALIGNED(alignment, decl) decl
     126             : #endif
     127             : 
     128             : /* this is read-only, so it's ok */
     129             : SET_ALIGNED(16, static char hexconvtab[]) = "0123456789abcdef";
     130             : 
     131             : /* localeconv mutex */
     132             : #ifdef ZTS
     133             : static MUTEX_T locale_mutex = NULL;
     134             : #endif
     135             : 
     136             : /* {{{ php_bin2hex
     137             :  */
     138       22545 : static zend_string *php_bin2hex(const unsigned char *old, const size_t oldlen)
     139             : {
     140             :         zend_string *result;
     141             :         size_t i, j;
     142             : 
     143       22545 :         result = zend_string_safe_alloc(oldlen, 2 * sizeof(char), 0, 0);
     144             : 
     145      141312 :         for (i = j = 0; i < oldlen; i++) {
     146      118767 :                 ZSTR_VAL(result)[j++] = hexconvtab[old[i] >> 4];
     147      118767 :                 ZSTR_VAL(result)[j++] = hexconvtab[old[i] & 15];
     148             :         }
     149       22545 :         ZSTR_VAL(result)[j] = '\0';
     150             : 
     151       22545 :         return result;
     152             : }
     153             : /* }}} */
     154             : 
     155             : /* {{{ php_hex2bin
     156             :  */
     157         104 : static zend_string *php_hex2bin(const unsigned char *old, const size_t oldlen)
     158             : {
     159         104 :         size_t target_length = oldlen >> 1;
     160         104 :         zend_string *str = zend_string_alloc(target_length, 0);
     161         104 :         unsigned char *ret = (unsigned char *)ZSTR_VAL(str);
     162             :         size_t i, j;
     163             : 
     164        3618 :         for (i = j = 0; i < target_length; i++) {
     165        1707 :                 unsigned char c = old[j++];
     166        1707 :                 unsigned char l = c & ~0x20;
     167        1707 :                 int is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
     168             :                 unsigned char d;
     169             : 
     170             :                 /* basically (c >= '0' && c <= '9') || (l >= 'A' && l <= 'F') */ 
     171        1707 :                 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
     172        1706 :                         d = (l - 0x10 - 0x27 * is_letter) << 4;
     173             :                 } else {
     174             :                         zend_string_free(str);
     175           1 :                         return NULL;
     176             :                 }
     177        1706 :                 c = old[j++];
     178        1706 :                 l = c & ~0x20;
     179        1706 :                 is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
     180        1706 :                 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
     181        1705 :                         d |= l - 0x10 - 0x27 * is_letter;
     182             :                 } else {
     183             :                         zend_string_free(str);
     184           1 :                         return NULL;
     185             :                 }
     186        1705 :                 ret[i] = d;
     187             :         }
     188         102 :         ret[i] = '\0';
     189             : 
     190         102 :         return str;
     191             : }
     192             : /* }}} */
     193             : 
     194             : #ifdef HAVE_LOCALECONV
     195             : /* {{{ localeconv_r
     196             :  * glibc's localeconv is not reentrant, so lets make it so ... sorta */
     197          11 : PHPAPI struct lconv *localeconv_r(struct lconv *out)
     198             : {
     199             : 
     200             : # ifdef ZTS
     201             :         tsrm_mutex_lock( locale_mutex );
     202             : # endif
     203             : 
     204             : /*  cur->locinfo is struct __crt_locale_info which implementation is
     205             :         hidden in vc14. TODO revisit this and check if a workaround available
     206             :         and needed. */
     207             : #if defined(PHP_WIN32) && _MSC_VER < 1900 && defined(ZTS)
     208             :         {
     209             :                 /* Even with the enabled per thread locale, localeconv
     210             :                         won't check any locale change in the master thread. */
     211             :                 _locale_t cur = _get_current_locale();
     212             :                 *out = *cur->locinfo->lconv;
     213             :                 _free_locale(cur);
     214             :         }
     215             : #else
     216             :         /* localeconv doesn't return an error condition */
     217          11 :         *out = *localeconv();
     218             : #endif
     219             : 
     220             : # ifdef ZTS
     221             :         tsrm_mutex_unlock( locale_mutex );
     222             : # endif
     223             : 
     224          11 :         return out;
     225             : }
     226             : /* }}} */
     227             : 
     228             : # ifdef ZTS
     229             : /* {{{ PHP_MINIT_FUNCTION
     230             :  */
     231             : PHP_MINIT_FUNCTION(localeconv)
     232             : {
     233             :         locale_mutex = tsrm_mutex_alloc();
     234             :         return SUCCESS;
     235             : }
     236             : /* }}} */
     237             : 
     238             : /* {{{ PHP_MSHUTDOWN_FUNCTION
     239             :  */
     240             : PHP_MSHUTDOWN_FUNCTION(localeconv)
     241             : {
     242             :         tsrm_mutex_free( locale_mutex );
     243             :         locale_mutex = NULL;
     244             :         return SUCCESS;
     245             : }
     246             : /* }}} */
     247             : # endif
     248             : #endif
     249             : 
     250             : /* {{{ proto string bin2hex(string data)
     251             :    Converts the binary representation of data to hex */
     252       22551 : PHP_FUNCTION(bin2hex)
     253             : {
     254             :         zend_string *result;
     255             :         zend_string *data;
     256             : 
     257       22551 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &data) == FAILURE) {
     258           6 :                 return;
     259             :         }
     260             : 
     261       22545 :         result = php_bin2hex((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
     262             : 
     263       22545 :         if (!result) {
     264           0 :                 RETURN_FALSE;
     265             :         }
     266             : 
     267       22545 :         RETURN_STR(result);
     268             : }
     269             : /* }}} */
     270             : 
     271             : /* {{{ proto string hex2bin(string data)
     272             :    Converts the hex representation of data to binary */
     273         105 : PHP_FUNCTION(hex2bin)
     274             : {
     275             :         zend_string *result, *data;
     276             : 
     277         105 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &data) == FAILURE) {
     278           0 :                 return;
     279             :         }
     280             : 
     281         105 :         if (ZSTR_LEN(data) % 2 != 0) {
     282           1 :                 php_error_docref(NULL, E_WARNING, "Hexadecimal input string must have an even length");
     283           1 :                 RETURN_FALSE;
     284             :         }
     285             : 
     286         104 :         result = php_hex2bin((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
     287             : 
     288         104 :         if (!result) {
     289           2 :                 php_error_docref(NULL, E_WARNING, "Input string must be hexadecimal string");
     290           2 :                 RETURN_FALSE;
     291             :         }
     292             : 
     293         102 :         RETVAL_STR(result);
     294             : }
     295             : /* }}} */
     296             : 
     297       13045 : static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
     298             : {
     299             :         zend_string *s11, *s22;
     300       13045 :         zend_long start = 0, len = 0;
     301             : 
     302       13045 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &s11,
     303             :                                 &s22, &start, &len) == FAILURE) {
     304         144 :                 return;
     305             :         }
     306             : 
     307       12901 :         if (ZEND_NUM_ARGS() < 4) {
     308        4086 :                 len = ZSTR_LEN(s11);
     309             :         }
     310             : 
     311             :         /* look at substr() function for more information */
     312             : 
     313       12901 :         if (start < 0) {
     314        4336 :                 start += (zend_long)ZSTR_LEN(s11);
     315        4336 :                 if (start < 0) {
     316        2306 :                         start = 0;
     317             :                 }
     318        8565 :         } else if ((size_t)start > ZSTR_LEN(s11)) {
     319        2662 :                 RETURN_FALSE;
     320             :         }
     321             : 
     322       10239 :         if (len < 0) {
     323        2226 :                 len += (ZSTR_LEN(s11) - start);
     324        2226 :                 if (len < 0) {
     325        1285 :                         len = 0;
     326             :                 }
     327             :         }
     328             : 
     329       10239 :         if (len > (zend_long)ZSTR_LEN(s11) - start) {
     330        3430 :                 len = ZSTR_LEN(s11) - start;
     331             :         }
     332             : 
     333       10239 :         if(len == 0) {
     334        3624 :                 RETURN_LONG(0);
     335             :         }
     336             : 
     337        6615 :         if (behavior == STR_STRSPN) {
     338        3381 :                 RETURN_LONG(php_strspn(ZSTR_VAL(s11) + start /*str1_start*/,
     339             :                                                 ZSTR_VAL(s22) /*str2_start*/,
     340             :                                                 ZSTR_VAL(s11) + start + len /*str1_end*/,
     341             :                                                 ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
     342        3234 :         } else if (behavior == STR_STRCSPN) {
     343        3234 :                 RETURN_LONG(php_strcspn(ZSTR_VAL(s11) + start /*str1_start*/,
     344             :                                                 ZSTR_VAL(s22) /*str2_start*/,
     345             :                                                 ZSTR_VAL(s11) + start + len /*str1_end*/,
     346             :                                                 ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
     347             :         }
     348             : 
     349             : }
     350             : /* }}} */
     351             : 
     352             : /* {{{ proto int strspn(string str, string mask [, int start [, int len]])
     353             :    Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars) */
     354        6718 : PHP_FUNCTION(strspn)
     355             : {
     356        6718 :         php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
     357        6718 : }
     358             : /* }}} */
     359             : 
     360             : /* {{{ proto int strcspn(string str, string mask [, int start [, int len]])
     361             :    Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars) */
     362        6327 : PHP_FUNCTION(strcspn)
     363             : {
     364        6327 :         php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRCSPN);
     365        6327 : }
     366             : /* }}} */
     367             : 
     368             : /* {{{ PHP_MINIT_FUNCTION(nl_langinfo) */
     369             : #if HAVE_NL_LANGINFO
     370       23409 : PHP_MINIT_FUNCTION(nl_langinfo)
     371             : {
     372             : #define REGISTER_NL_LANGINFO_CONSTANT(x)        REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
     373             : #ifdef ABDAY_1
     374       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_1);
     375       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_2);
     376       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_3);
     377       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_4);
     378       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_5);
     379       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_6);
     380       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_7);
     381             : #endif
     382             : #ifdef DAY_1
     383       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_1);
     384       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_2);
     385       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_3);
     386       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_4);
     387       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_5);
     388       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_6);
     389       23409 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_7);
     390             : #endif
     391             : #ifdef ABMON_1
     392       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_1);
     393       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_2);
     394       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_3);
     395       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_4);
     396       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_5);
     397       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_6);
     398       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_7);
     399       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_8);
     400       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_9);
     401       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_10);
     402       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_11);
     403       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_12);
     404             : #endif
     405             : #ifdef MON_1
     406       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_1);
     407       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_2);
     408       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_3);
     409       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_4);
     410       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_5);
     411       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_6);
     412       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_7);
     413       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_8);
     414       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_9);
     415       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_10);
     416       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_11);
     417       23409 :         REGISTER_NL_LANGINFO_CONSTANT(MON_12);
     418             : #endif
     419             : #ifdef AM_STR
     420       23409 :         REGISTER_NL_LANGINFO_CONSTANT(AM_STR);
     421             : #endif
     422             : #ifdef PM_STR
     423       23409 :         REGISTER_NL_LANGINFO_CONSTANT(PM_STR);
     424             : #endif
     425             : #ifdef D_T_FMT
     426       23409 :         REGISTER_NL_LANGINFO_CONSTANT(D_T_FMT);
     427             : #endif
     428             : #ifdef D_FMT
     429       23409 :         REGISTER_NL_LANGINFO_CONSTANT(D_FMT);
     430             : #endif
     431             : #ifdef T_FMT
     432       23409 :         REGISTER_NL_LANGINFO_CONSTANT(T_FMT);
     433             : #endif
     434             : #ifdef T_FMT_AMPM
     435       23409 :         REGISTER_NL_LANGINFO_CONSTANT(T_FMT_AMPM);
     436             : #endif
     437             : #ifdef ERA
     438       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ERA);
     439             : #endif
     440             : #ifdef ERA_YEAR
     441             :         REGISTER_NL_LANGINFO_CONSTANT(ERA_YEAR);
     442             : #endif
     443             : #ifdef ERA_D_T_FMT
     444       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_D_T_FMT);
     445             : #endif
     446             : #ifdef ERA_D_FMT
     447       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_D_FMT);
     448             : #endif
     449             : #ifdef ERA_T_FMT
     450       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_T_FMT);
     451             : #endif
     452             : #ifdef ALT_DIGITS
     453       23409 :         REGISTER_NL_LANGINFO_CONSTANT(ALT_DIGITS);
     454             : #endif
     455             : #ifdef INT_CURR_SYMBOL
     456             :         REGISTER_NL_LANGINFO_CONSTANT(INT_CURR_SYMBOL);
     457             : #endif
     458             : #ifdef CURRENCY_SYMBOL
     459             :         REGISTER_NL_LANGINFO_CONSTANT(CURRENCY_SYMBOL);
     460             : #endif
     461             : #ifdef CRNCYSTR
     462       23409 :         REGISTER_NL_LANGINFO_CONSTANT(CRNCYSTR);
     463             : #endif
     464             : #ifdef MON_DECIMAL_POINT
     465             :         REGISTER_NL_LANGINFO_CONSTANT(MON_DECIMAL_POINT);
     466             : #endif
     467             : #ifdef MON_THOUSANDS_SEP
     468             :         REGISTER_NL_LANGINFO_CONSTANT(MON_THOUSANDS_SEP);
     469             : #endif
     470             : #ifdef MON_GROUPING
     471             :         REGISTER_NL_LANGINFO_CONSTANT(MON_GROUPING);
     472             : #endif
     473             : #ifdef POSITIVE_SIGN
     474             :         REGISTER_NL_LANGINFO_CONSTANT(POSITIVE_SIGN);
     475             : #endif
     476             : #ifdef NEGATIVE_SIGN
     477             :         REGISTER_NL_LANGINFO_CONSTANT(NEGATIVE_SIGN);
     478             : #endif
     479             : #ifdef INT_FRAC_DIGITS
     480             :         REGISTER_NL_LANGINFO_CONSTANT(INT_FRAC_DIGITS);
     481             : #endif
     482             : #ifdef FRAC_DIGITS
     483             :         REGISTER_NL_LANGINFO_CONSTANT(FRAC_DIGITS);
     484             : #endif
     485             : #ifdef P_CS_PRECEDES
     486             :         REGISTER_NL_LANGINFO_CONSTANT(P_CS_PRECEDES);
     487             : #endif
     488             : #ifdef P_SEP_BY_SPACE
     489             :         REGISTER_NL_LANGINFO_CONSTANT(P_SEP_BY_SPACE);
     490             : #endif
     491             : #ifdef N_CS_PRECEDES
     492             :         REGISTER_NL_LANGINFO_CONSTANT(N_CS_PRECEDES);
     493             : #endif
     494             : #ifdef N_SEP_BY_SPACE
     495             :         REGISTER_NL_LANGINFO_CONSTANT(N_SEP_BY_SPACE);
     496             : #endif
     497             : #ifdef P_SIGN_POSN
     498             :         REGISTER_NL_LANGINFO_CONSTANT(P_SIGN_POSN);
     499             : #endif
     500             : #ifdef N_SIGN_POSN
     501             :         REGISTER_NL_LANGINFO_CONSTANT(N_SIGN_POSN);
     502             : #endif
     503             : #ifdef DECIMAL_POINT
     504             :         REGISTER_NL_LANGINFO_CONSTANT(DECIMAL_POINT);
     505             : #endif
     506             : #ifdef RADIXCHAR
     507       23409 :         REGISTER_NL_LANGINFO_CONSTANT(RADIXCHAR);
     508             : #endif
     509             : #ifdef THOUSANDS_SEP
     510             :         REGISTER_NL_LANGINFO_CONSTANT(THOUSANDS_SEP);
     511             : #endif
     512             : #ifdef THOUSEP
     513       23409 :         REGISTER_NL_LANGINFO_CONSTANT(THOUSEP);
     514             : #endif
     515             : #ifdef GROUPING
     516             :         REGISTER_NL_LANGINFO_CONSTANT(GROUPING);
     517             : #endif
     518             : #ifdef YESEXPR
     519       23409 :         REGISTER_NL_LANGINFO_CONSTANT(YESEXPR);
     520             : #endif
     521             : #ifdef NOEXPR
     522       23409 :         REGISTER_NL_LANGINFO_CONSTANT(NOEXPR);
     523             : #endif
     524             : #ifdef YESSTR
     525             :         REGISTER_NL_LANGINFO_CONSTANT(YESSTR);
     526             : #endif
     527             : #ifdef NOSTR
     528             :         REGISTER_NL_LANGINFO_CONSTANT(NOSTR);
     529             : #endif
     530             : #ifdef CODESET
     531       23409 :         REGISTER_NL_LANGINFO_CONSTANT(CODESET);
     532             : #endif
     533             : #undef REGISTER_NL_LANGINFO_CONSTANT
     534       23409 :         return SUCCESS;
     535             : }
     536             : /* }}} */
     537             : 
     538             : /* {{{ proto string nl_langinfo(int item)
     539             :    Query language and locale information */
     540          15 : PHP_FUNCTION(nl_langinfo)
     541             : {
     542             :         zend_long item;
     543             :         char *value;
     544             : 
     545          15 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &item) == FAILURE) {
     546           7 :                 return;
     547             :         }
     548             : 
     549           8 :         switch(item) { /* {{{ */
     550             : #ifdef ABDAY_1
     551             :                 case ABDAY_1:
     552             :                 case ABDAY_2:
     553             :                 case ABDAY_3:
     554             :                 case ABDAY_4:
     555             :                 case ABDAY_5:
     556             :                 case ABDAY_6:
     557             :                 case ABDAY_7:
     558             : #endif
     559             : #ifdef DAY_1
     560             :                 case DAY_1:
     561             :                 case DAY_2:
     562             :                 case DAY_3:
     563             :                 case DAY_4:
     564             :                 case DAY_5:
     565             :                 case DAY_6:
     566             :                 case DAY_7:
     567             : #endif
     568             : #ifdef ABMON_1
     569             :                 case ABMON_1:
     570             :                 case ABMON_2:
     571             :                 case ABMON_3:
     572             :                 case ABMON_4:
     573             :                 case ABMON_5:
     574             :                 case ABMON_6:
     575             :                 case ABMON_7:
     576             :                 case ABMON_8:
     577             :                 case ABMON_9:
     578             :                 case ABMON_10:
     579             :                 case ABMON_11:
     580             :                 case ABMON_12:
     581             : #endif
     582             : #ifdef MON_1
     583             :                 case MON_1:
     584             :                 case MON_2:
     585             :                 case MON_3:
     586             :                 case MON_4:
     587             :                 case MON_5:
     588             :                 case MON_6:
     589             :                 case MON_7:
     590             :                 case MON_8:
     591             :                 case MON_9:
     592             :                 case MON_10:
     593             :                 case MON_11:
     594             :                 case MON_12:
     595             : #endif
     596             : #ifdef AM_STR
     597             :                 case AM_STR:
     598             : #endif
     599             : #ifdef PM_STR
     600             :                 case PM_STR:
     601             : #endif
     602             : #ifdef D_T_FMT
     603             :                 case D_T_FMT:
     604             : #endif
     605             : #ifdef D_FMT
     606             :                 case D_FMT:
     607             : #endif
     608             : #ifdef T_FMT
     609             :                 case T_FMT:
     610             : #endif
     611             : #ifdef T_FMT_AMPM
     612             :                 case T_FMT_AMPM:
     613             : #endif
     614             : #ifdef ERA
     615             :                 case ERA:
     616             : #endif
     617             : #ifdef ERA_YEAR
     618             :                 case ERA_YEAR:
     619             : #endif
     620             : #ifdef ERA_D_T_FMT
     621             :                 case ERA_D_T_FMT:
     622             : #endif
     623             : #ifdef ERA_D_FMT
     624             :                 case ERA_D_FMT:
     625             : #endif
     626             : #ifdef ERA_T_FMT
     627             :                 case ERA_T_FMT:
     628             : #endif
     629             : #ifdef ALT_DIGITS
     630             :                 case ALT_DIGITS:
     631             : #endif
     632             : #ifdef INT_CURR_SYMBOL
     633             :                 case INT_CURR_SYMBOL:
     634             : #endif
     635             : #ifdef CURRENCY_SYMBOL
     636             :                 case CURRENCY_SYMBOL:
     637             : #endif
     638             : #ifdef CRNCYSTR
     639             :                 case CRNCYSTR:
     640             : #endif
     641             : #ifdef MON_DECIMAL_POINT
     642             :                 case MON_DECIMAL_POINT:
     643             : #endif
     644             : #ifdef MON_THOUSANDS_SEP
     645             :                 case MON_THOUSANDS_SEP:
     646             : #endif
     647             : #ifdef MON_GROUPING
     648             :                 case MON_GROUPING:
     649             : #endif
     650             : #ifdef POSITIVE_SIGN
     651             :                 case POSITIVE_SIGN:
     652             : #endif
     653             : #ifdef NEGATIVE_SIGN
     654             :                 case NEGATIVE_SIGN:
     655             : #endif
     656             : #ifdef INT_FRAC_DIGITS
     657             :                 case INT_FRAC_DIGITS:
     658             : #endif
     659             : #ifdef FRAC_DIGITS
     660             :                 case FRAC_DIGITS:
     661             : #endif
     662             : #ifdef P_CS_PRECEDES
     663             :                 case P_CS_PRECEDES:
     664             : #endif
     665             : #ifdef P_SEP_BY_SPACE
     666             :                 case P_SEP_BY_SPACE:
     667             : #endif
     668             : #ifdef N_CS_PRECEDES
     669             :                 case N_CS_PRECEDES:
     670             : #endif
     671             : #ifdef N_SEP_BY_SPACE
     672             :                 case N_SEP_BY_SPACE:
     673             : #endif
     674             : #ifdef P_SIGN_POSN
     675             :                 case P_SIGN_POSN:
     676             : #endif
     677             : #ifdef N_SIGN_POSN
     678             :                 case N_SIGN_POSN:
     679             : #endif
     680             : #ifdef DECIMAL_POINT
     681             :                 case DECIMAL_POINT:
     682             : #elif defined(RADIXCHAR)
     683             :                 case RADIXCHAR:
     684             : #endif
     685             : #ifdef THOUSANDS_SEP
     686             :                 case THOUSANDS_SEP:
     687             : #elif defined(THOUSEP)
     688             :                 case THOUSEP:
     689             : #endif
     690             : #ifdef GROUPING
     691             :                 case GROUPING:
     692             : #endif
     693             : #ifdef YESEXPR
     694             :                 case YESEXPR:
     695             : #endif
     696             : #ifdef NOEXPR
     697             :                 case NOEXPR:
     698             : #endif
     699             : #ifdef YESSTR
     700             :                 case YESSTR:
     701             : #endif
     702             : #ifdef NOSTR
     703             :                 case NOSTR:
     704             : #endif
     705             : #ifdef CODESET
     706             :                 case CODESET:
     707             : #endif
     708           5 :                         break;
     709             :                 default:
     710           3 :                         php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
     711           3 :                         RETURN_FALSE;
     712             :         }
     713             :         /* }}} */
     714             : 
     715           5 :         value = nl_langinfo(item);
     716           5 :         if (value == NULL) {
     717           0 :                 RETURN_FALSE;
     718             :         } else {
     719          10 :                 RETURN_STRING(value);
     720             :         }
     721             : }
     722             : #endif
     723             : /* }}} */
     724             : 
     725             : #ifdef HAVE_STRCOLL
     726             : /* {{{ proto int strcoll(string str1, string str2)
     727             :    Compares two strings using the current locale */
     728           5 : PHP_FUNCTION(strcoll)
     729             : {
     730             :         zend_string *s1, *s2;
     731             : 
     732           5 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
     733           4 :                 return;
     734             :         }
     735             : 
     736           1 :         RETURN_LONG(strcoll((const char *) ZSTR_VAL(s1),
     737             :                             (const char *) ZSTR_VAL(s2)));
     738             : }
     739             : /* }}} */
     740             : #endif
     741             : 
     742             : /* {{{ php_charmask
     743             :  * Fills a 256-byte bytemask with input. You can specify a range like 'a..z',
     744             :  * it needs to be incrementing.
     745             :  * Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
     746             :  */
     747        2199 : static inline int php_charmask(unsigned char *input, size_t len, char *mask)
     748             : {
     749             :         unsigned char *end;
     750             :         unsigned char c;
     751        2199 :         int result = SUCCESS;
     752             : 
     753        2199 :         memset(mask, 0, 256);
     754        7455 :         for (end = input+len; input < end; input++) {
     755        5256 :                 c=*input;
     756        5314 :                 if ((input+3 < end) && input[1] == '.' && input[2] == '.'
     757          32 :                                 && input[3] >= c) {
     758          26 :                         memset(mask+c, 1, input[3] - c + 1);
     759          26 :                         input+=3;
     760        5230 :                 } else if ((input+1 < end) && input[0] == '.' && input[1] == '.') {
     761             :                         /* Error, try to be as helpful as possible:
     762             :                            (a range ending/starting with '.' won't be captured here) */
     763          15 :                         if (end-len >= input) { /* there was no 'left' char */
     764           3 :                                 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'");
     765           3 :                                 result = FAILURE;
     766           3 :                                 continue;
     767             :                         }
     768          12 :                         if (input+2 >= end) { /* there is no 'right' char */
     769           3 :                                 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'");
     770           3 :                                 result = FAILURE;
     771           3 :                                 continue;
     772             :                         }
     773           9 :                         if (input[-1] > input[2]) { /* wrong order */
     774           6 :                                 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing");
     775           6 :                                 result = FAILURE;
     776           6 :                                 continue;
     777             :                         }
     778             :                         /* FIXME: better error (a..b..c is the only left possibility?) */
     779           3 :                         php_error_docref(NULL, E_WARNING, "Invalid '..'-range");
     780           3 :                         result = FAILURE;
     781           3 :                         continue;
     782             :                 } else {
     783        5215 :                         mask[c]=1;
     784             :                 }
     785             :         }
     786        2199 :         return result;
     787             : }
     788             : /* }}} */
     789             : 
     790             : /* {{{ php_trim()
     791             :  * mode 1 : trim left
     792             :  * mode 2 : trim right
     793             :  * mode 3 : trim left and right
     794             :  * what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0')
     795             :  */
     796     1095258 : PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)
     797             : {
     798     1095258 :         const char *c = ZSTR_VAL(str);
     799     1095258 :         size_t len = ZSTR_LEN(str);
     800             :         register size_t i;
     801     1095258 :         size_t trimmed = 0;
     802             :         char mask[256];
     803             : 
     804     1095258 :         if (what) {
     805         251 :                 if (what_len == 1) {
     806          43 :                         char p = *what;
     807          43 :                         if (mode & 1) {
     808          68 :                                 for (i = 0; i < len; i++) {
     809          34 :                                         if (c[i] == p) {
     810          14 :                                                 trimmed++;
     811             :                                         } else {
     812          20 :                                                 break;
     813             :                                         }
     814             :                                 }
     815          20 :                                 len -= trimmed;
     816          20 :                                 c += trimmed;
     817             :                         }
     818          43 :                         if (mode & 2) {
     819          28 :                                 if (len > 0) {
     820          28 :                                         i = len - 1;
     821             :                                         do {
     822          49 :                                                 if (c[i] == p) {
     823          23 :                                                         len--;
     824             :                                                 } else {
     825          26 :                                                         break;
     826             :                                                 }
     827          23 :                                         } while (i-- != 0);
     828             :                                 }
     829             :                         }
     830             :                 } else {
     831         208 :                         php_charmask((unsigned char*)what, what_len, mask);
     832             : 
     833         208 :                         if (mode & 1) {
     834         392 :                                 for (i = 0; i < len; i++) {
     835         184 :                                         if (mask[(unsigned char)c[i]]) {
     836          97 :                                                 trimmed++;
     837             :                                         } else {
     838          87 :                                                 break;
     839             :                                         }
     840             :                                 }
     841          99 :                                 len -= trimmed;
     842          99 :                                 c += trimmed;
     843             :                         }
     844         208 :                         if (mode & 2) {
     845         160 :                                 if (len > 0) {
     846         139 :                                         i = len - 1;
     847             :                                         do {
     848         331 :                                                 if (mask[(unsigned char)c[i]]) {
     849         199 :                                                         len--;
     850             :                                                 } else {
     851         132 :                                                         break;
     852             :                                                 }
     853         199 :                                         } while (i-- != 0);
     854             :                                 }
     855             :                         }
     856             :                 }
     857             :         } else {
     858     1095007 :                 if (mode & 1) {
     859     1102943 :                         for (i = 0; i < len; i++) {
     860      963569 :                                 if ((unsigned char)c[i] <= ' ' &&
     861       12500 :                                     (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
     862        8133 :                                         trimmed++;
     863             :                                 } else {
     864             :                                         break;
     865             :                                 }
     866             :                         }
     867     1094810 :                         len -= trimmed;
     868     1094810 :                         c += trimmed;
     869             :                 }
     870     1095007 :                 if (mode & 2) {
     871     1073465 :                         if (len > 0) {
     872      941839 :                                 i = len - 1;
     873             :                                 do {
     874     1110410 :                                         if ((unsigned char)c[i] <= ' ' &&
     875      111990 :                                             (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
     876       56584 :                                                 len--;
     877             :                                         } else {
     878             :                                                 break;
     879             :                                         }
     880       56584 :                                 } while (i-- != 0);
     881             :                         }
     882             :                 }
     883             :         }
     884             : 
     885     1095258 :         if (ZSTR_LEN(str) == len) {
     886     1040407 :                 return zend_string_copy(str);
     887             :         } else {
     888       54851 :                 return zend_string_init(c, len, 0);
     889             :         }
     890             : }
     891             : /* }}} */
     892             : 
     893             : /* {{{ php_do_trim
     894             :  * Base for trim(), rtrim() and ltrim() functions.
     895             :  */
     896     1071855 : static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
     897             : {
     898             :         zend_string *str;
     899     1071855 :         zend_string *what = NULL;
     900             : 
     901             : #ifndef FAST_ZPP
     902             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &str, &what) == FAILURE) {
     903             :                 return;
     904             :         }
     905             : #else
     906     1071855 :         ZEND_PARSE_PARAMETERS_START(1, 2)
     907     3215520 :                 Z_PARAM_STR(str)
     908     1071816 :                 Z_PARAM_OPTIONAL
     909     1072354 :                 Z_PARAM_STR(what)
     910     1071855 :         ZEND_PARSE_PARAMETERS_END();
     911             : #endif
     912             : 
     913     1071798 :         ZVAL_STR(return_value, php_trim(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : 0), mode));
     914             : }
     915             : /* }}} */
     916             : 
     917             : /* {{{ proto string trim(string str [, string character_mask])
     918             :    Strips whitespace from the beginning and end of a string */
     919     1049903 : PHP_FUNCTION(trim)
     920             : {
     921     1049903 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
     922     1049903 : }
     923             : /* }}} */
     924             : 
     925             : /* {{{ proto string rtrim(string str [, string character_mask])
     926             :    Removes trailing whitespace */
     927         335 : PHP_FUNCTION(rtrim)
     928             : {
     929         335 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
     930         335 : }
     931             : /* }}} */
     932             : 
     933             : /* {{{ proto string ltrim(string str [, string character_mask])
     934             :    Strips whitespace from the beginning of a string */
     935       21617 : PHP_FUNCTION(ltrim)
     936             : {
     937       21617 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     938       21617 : }
     939             : /* }}} */
     940             : 
     941             : /* {{{ proto string wordwrap(string str [, int width [, string break [, boolean cut]]])
     942             :    Wraps buffer to selected number of characters using string break char */
     943         357 : PHP_FUNCTION(wordwrap)
     944             : {
     945             :         zend_string *text;
     946         357 :         char *breakchar = "\n";
     947         357 :         size_t newtextlen, chk, breakchar_len = 1;
     948             :         size_t alloced;
     949         357 :         zend_long current = 0, laststart = 0, lastspace = 0;
     950         357 :         zend_long linelength = 75;
     951         357 :         zend_bool docut = 0;
     952             :         zend_string *newtext;
     953             : 
     954         357 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|lsb", &text, &linelength, &breakchar, &breakchar_len, &docut) == FAILURE) {
     955         108 :                 return;
     956             :         }
     957             : 
     958         249 :         if (ZSTR_LEN(text) == 0) {
     959          40 :                 RETURN_EMPTY_STRING();
     960             :         }
     961             : 
     962         209 :         if (breakchar_len == 0) {
     963          25 :                 php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
     964          25 :                 RETURN_FALSE;
     965             :         }
     966             : 
     967         184 :         if (linelength == 0 && docut) {
     968           8 :                 php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
     969           8 :                 RETURN_FALSE;
     970             :         }
     971             : 
     972             :         /* Special case for a single-character break as it needs no
     973             :            additional storage space */
     974         176 :         if (breakchar_len == 1 && !docut) {
     975         100 :                 newtext = zend_string_init(ZSTR_VAL(text), ZSTR_LEN(text), 0);
     976             : 
     977          50 :                 laststart = lastspace = 0;
     978        1009 :                 for (current = 0; current < (zend_long)ZSTR_LEN(text); current++) {
     979         959 :                         if (ZSTR_VAL(text)[current] == breakchar[0]) {
     980           4 :                                 laststart = lastspace = current + 1;
     981         955 :                         } else if (ZSTR_VAL(text)[current] == ' ') {
     982          72 :                                 if (current - laststart >= linelength) {
     983          30 :                                         ZSTR_VAL(newtext)[current] = breakchar[0];
     984          30 :                                         laststart = current + 1;
     985             :                                 }
     986          72 :                                 lastspace = current;
     987         883 :                         } else if (current - laststart >= linelength && laststart != lastspace) {
     988         220 :                                 ZSTR_VAL(newtext)[lastspace] = breakchar[0];
     989         220 :                                 laststart = lastspace + 1;
     990             :                         }
     991             :                 }
     992             : 
     993          50 :                 RETURN_NEW_STR(newtext);
     994             :         } else {
     995             :                 /* Multiple character line break or forced cut */
     996         126 :                 if (linelength > 0) {
     997         102 :                         chk = (size_t)(ZSTR_LEN(text)/linelength + 1);
     998         204 :                         newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0);
     999         102 :                         alloced = ZSTR_LEN(text) + chk * breakchar_len + 1;
    1000             :                 } else {
    1001          24 :                         chk = ZSTR_LEN(text);
    1002          24 :                         alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1;
    1003          48 :                         newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0);
    1004             :                 }
    1005             : 
    1006             :                 /* now keep track of the actual new text length */
    1007         126 :                 newtextlen = 0;
    1008             : 
    1009         126 :                 laststart = lastspace = 0;
    1010        2742 :                 for (current = 0; current < (zend_long)ZSTR_LEN(text); current++) {
    1011        2616 :                         if (chk <= 0) {
    1012           6 :                                 alloced += (size_t) (((ZSTR_LEN(text) - current + 1)/linelength + 1) * breakchar_len) + 1;
    1013           6 :                                 newtext = zend_string_extend(newtext, alloced, 0);
    1014           6 :                                 chk = (size_t) ((ZSTR_LEN(text) - current)/linelength) + 1;
    1015             :                         }
    1016             :                         /* when we hit an existing break, copy to new buffer, and
    1017             :                          * fix up laststart and lastspace */
    1018        7902 :                         if (ZSTR_VAL(text)[current] == breakchar[0]
    1019        5252 :                                 && current + breakchar_len < ZSTR_LEN(text)
    1020          40 :                                 && !strncmp(ZSTR_VAL(text) + current, breakchar, breakchar_len)) {
    1021          14 :                                 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart + breakchar_len);
    1022          14 :                                 newtextlen += current - laststart + breakchar_len;
    1023          14 :                                 current += breakchar_len - 1;
    1024          14 :                                 laststart = lastspace = current + 1;
    1025          14 :                                 chk--;
    1026             :                         }
    1027             :                         /* if it is a space, check if it is at the line boundary,
    1028             :                          * copy and insert a break, or just keep track of it */
    1029        2602 :                         else if (ZSTR_VAL(text)[current] == ' ') {
    1030         214 :                                 if (current - laststart >= linelength) {
    1031          85 :                                         memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
    1032          85 :                                         newtextlen += current - laststart;
    1033          85 :                                         memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
    1034          85 :                                         newtextlen += breakchar_len;
    1035          85 :                                         laststart = current + 1;
    1036          85 :                                         chk--;
    1037             :                                 }
    1038         214 :                                 lastspace = current;
    1039             :                         }
    1040             :                         /* if we are cutting, and we've accumulated enough
    1041             :                          * characters, and we haven't see a space for this line,
    1042             :                          * copy and insert a break. */
    1043        5898 :                         else if (current - laststart >= linelength
    1044        3342 :                                         && docut && laststart >= lastspace) {
    1045         168 :                                 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
    1046         168 :                                 newtextlen += current - laststart;
    1047         168 :                                 memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
    1048         168 :                                 newtextlen += breakchar_len;
    1049         168 :                                 laststart = lastspace = current;
    1050         168 :                                 chk--;
    1051             :                         }
    1052             :                         /* if the current word puts us over the linelength, copy
    1053             :                          * back up until the last space, insert a break, and move
    1054             :                          * up the laststart */
    1055        4440 :                         else if (current - laststart >= linelength
    1056        2220 :                                         && laststart < lastspace) {
    1057         107 :                                 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, lastspace - laststart);
    1058         107 :                                 newtextlen += lastspace - laststart;
    1059         107 :                                 memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
    1060         107 :                                 newtextlen += breakchar_len;
    1061         107 :                                 laststart = lastspace = lastspace + 1;
    1062         107 :                                 chk--;
    1063             :                         }
    1064             :                 }
    1065             : 
    1066             :                 /* copy over any stragglers */
    1067         126 :                 if (laststart != current) {
    1068         126 :                         memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
    1069         126 :                         newtextlen += current - laststart;
    1070             :                 }
    1071             : 
    1072         126 :                 ZSTR_VAL(newtext)[newtextlen] = '\0';
    1073             :                 /* free unused memory */
    1074         126 :                 newtext = zend_string_truncate(newtext, newtextlen, 0);
    1075             : 
    1076         126 :                 RETURN_NEW_STR(newtext);
    1077             :         }
    1078             : }
    1079             : /* }}} */
    1080             : 
    1081             : /* {{{ php_explode
    1082             :  */
    1083      597931 : PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
    1084             : {
    1085      597931 :         char *p1 = ZSTR_VAL(str);
    1086      597931 :         char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
    1087     1195862 :         char *p2 = (char *) php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
    1088             :         zval  tmp;
    1089             : 
    1090      597931 :         if (p2 == NULL) {
    1091         155 :                 ZVAL_STR_COPY(&tmp, str);
    1092         155 :                 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1093             :         } else {
    1094             :                 do {
    1095     1215228 :                         ZVAL_STRINGL(&tmp, p1, p2 - p1);
    1096      607614 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1097      607614 :                         p1 = p2 + ZSTR_LEN(delim);
    1098     1215228 :                         p2 = (char *) php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
    1099      607614 :                 } while (p2 != NULL && --limit > 1);
    1100             : 
    1101      597776 :                 if (p1 <= endp) {
    1102     1195552 :                         ZVAL_STRINGL(&tmp, p1, endp - p1);
    1103      597776 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1104             :                 }
    1105             :         }
    1106      597931 : }
    1107             : /* }}} */
    1108             : 
    1109             : /* {{{ php_explode_negative_limit
    1110             :  */
    1111          23 : PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
    1112             : {
    1113             : #define EXPLODE_ALLOC_STEP 64
    1114          23 :         char *p1 = ZSTR_VAL(str);
    1115          23 :         char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
    1116          46 :         char *p2 = (char *) php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
    1117             :         zval  tmp;
    1118             : 
    1119          23 :         if (p2 == NULL) {
    1120             :                 /*
    1121             :                 do nothing since limit <= -1, thus if only one chunk - 1 + (limit) <= 0
    1122             :                 by doing nothing we return empty array
    1123             :                 */
    1124             :         } else {
    1125          22 :                 size_t allocated = EXPLODE_ALLOC_STEP, found = 0;
    1126             :                 zend_long i, to_return;
    1127          22 :                 char **positions = emalloc(allocated * sizeof(char *));
    1128             : 
    1129          22 :                 positions[found++] = p1;
    1130             :                 do {
    1131         178 :                         if (found >= allocated) {
    1132           1 :                                 allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */
    1133           1 :                                 positions = erealloc(positions, allocated*sizeof(char *));
    1134             :                         }
    1135         178 :                         positions[found++] = p1 = p2 + ZSTR_LEN(delim);
    1136         356 :                         p2 = (char *) php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
    1137         178 :                 } while (p2 != NULL);
    1138             : 
    1139          22 :                 to_return = limit + found;
    1140             :                 /* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
    1141         181 :                 for (i = 0; i < to_return; i++) { /* this checks also for to_return > 0 */
    1142         318 :                         ZVAL_STRINGL(&tmp, positions[i], (positions[i+1] - ZSTR_LEN(delim)) - positions[i]);
    1143         159 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1144             :                 }
    1145          22 :                 efree(positions);
    1146             :         }
    1147             : #undef EXPLODE_ALLOC_STEP
    1148          23 : }
    1149             : /* }}} */
    1150             : 
    1151             : /* {{{ proto array explode(string separator, string str [, int limit])
    1152             :    Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */
    1153      598047 : PHP_FUNCTION(explode)
    1154             : {
    1155             :         zend_string *str, *delim;
    1156      598047 :         zend_long limit = ZEND_LONG_MAX; /* No limit */
    1157             :         zval tmp;
    1158             : 
    1159             : #ifndef FAST_ZPP
    1160             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &delim, &str, &limit) == FAILURE) {
    1161             :                 return;
    1162             :         }
    1163             : #else
    1164      598047 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    1165     1794126 :                 Z_PARAM_STR(delim)
    1166     1794099 :                 Z_PARAM_STR(str)
    1167      598029 :                 Z_PARAM_OPTIONAL
    1168     1591899 :                 Z_PARAM_LONG(limit)
    1169      598047 :         ZEND_PARSE_PARAMETERS_END();
    1170             : #endif
    1171             : 
    1172      598024 :         if (ZSTR_LEN(delim) == 0) {
    1173          28 :                 php_error_docref(NULL, E_WARNING, "Empty delimiter");
    1174          28 :                 RETURN_FALSE;
    1175             :         }
    1176             : 
    1177      597996 :         array_init(return_value);
    1178             : 
    1179      597996 :         if (ZSTR_LEN(str) == 0) {
    1180          12 :                 if (limit >= 0) {
    1181          11 :                         ZVAL_EMPTY_STRING(&tmp);
    1182          11 :                         zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
    1183             :                 }
    1184          12 :                 return;
    1185             :         }
    1186             : 
    1187      597984 :         if (limit > 1) {
    1188      597931 :                 php_explode(delim, str, return_value, limit);
    1189          53 :         } else if (limit < 0) {
    1190          23 :                 php_explode_negative_limit(delim, str, return_value, limit);
    1191             :         } else {
    1192          30 :                 ZVAL_STR_COPY(&tmp, str);
    1193          30 :                 zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
    1194             :         }
    1195             : }
    1196             : /* }}} */
    1197             : 
    1198             : /* {{{ proto string join(array src, string glue)
    1199             :    An alias for implode */
    1200             : /* }}} */
    1201             : 
    1202             : /* {{{ php_implode
    1203             :  */
    1204       91103 : PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value)
    1205             : {
    1206             :         zval         *tmp;
    1207             :         int           numelems;
    1208             :         zend_string  *str;
    1209             :         char         *cptr;
    1210       91103 :         size_t        len = 0;
    1211             :         zend_string **strings, **strptr;
    1212             : 
    1213       91103 :         numelems = zend_hash_num_elements(Z_ARRVAL_P(arr));
    1214             : 
    1215       91103 :         if (numelems == 0) {
    1216          53 :                 RETURN_EMPTY_STRING();
    1217       91050 :         } else if (numelems == 1) {
    1218             :                 /* loop to search the first not undefined element... */
    1219        1389 :                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
    1220         926 :                         RETURN_STR(zval_get_string(tmp));
    1221             :                 } ZEND_HASH_FOREACH_END();
    1222             :         }
    1223             : 
    1224       90587 :         strings = emalloc((sizeof(zend_long) + sizeof(zend_string *)) * numelems);
    1225       90587 :         strptr = strings - 1;
    1226             : 
    1227      820391 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
    1228      364880 :                 if (Z_TYPE_P(tmp) == IS_LONG) {
    1229      360750 :                         zend_long val = Z_LVAL_P(tmp);
    1230             : 
    1231      360750 :                         *++strptr = NULL;
    1232      360750 :                         ((zend_long *) (strings + numelems))[strptr - strings] = Z_LVAL_P(tmp);
    1233      360750 :                         if (val <= 0) {
    1234         534 :                                 len++;
    1235             :                         }
    1236     1081978 :                         while (val) {
    1237      360478 :                                 val /= 10;
    1238      360478 :                                 len++;
    1239             :                         }
    1240             :                 } else {
    1241        8260 :                         *++strptr = zval_get_string(tmp);
    1242        4130 :                         len += ZSTR_LEN(*strptr);
    1243             :                 }
    1244             :         } ZEND_HASH_FOREACH_END();
    1245             :         /* numelems can not be 0, we checked above */
    1246      181174 :         str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(delim), len, 0);
    1247       90587 :         cptr = ZSTR_VAL(str) + ZSTR_LEN(str);
    1248       90587 :         *cptr = 0;
    1249             : 
    1250             :         do {
    1251      274293 :                 if (*strptr) {
    1252        3597 :                         cptr -= ZSTR_LEN(*strptr);
    1253        3597 :                         memcpy(cptr, ZSTR_VAL(*strptr), ZSTR_LEN(*strptr));
    1254        3597 :                         zend_string_release(*strptr);
    1255             :                 } else {
    1256      270696 :                         char *oldPtr = cptr;
    1257      270696 :                         char oldVal = *cptr;
    1258      270696 :                         zend_long val = ((zend_long *) (strings + numelems))[strptr - strings];
    1259      270696 :                         cptr = zend_print_long_to_buf(cptr, val);
    1260      270696 :                         *oldPtr = oldVal;
    1261             :                 }
    1262             : 
    1263      274293 :                 cptr -= ZSTR_LEN(delim);
    1264      274293 :                 memcpy(cptr, ZSTR_VAL(delim), ZSTR_LEN(delim));
    1265      274293 :         } while (--strptr > strings);
    1266             : 
    1267       90587 :         if (*strptr) {
    1268         533 :                 memcpy(ZSTR_VAL(str), ZSTR_VAL(*strptr), ZSTR_LEN(*strptr));
    1269         533 :                 zend_string_release(*strptr);
    1270             :         } else {
    1271       90054 :                 char *oldPtr = cptr;
    1272       90054 :                 char oldVal = *cptr;
    1273       90054 :                 zend_print_long_to_buf(cptr, ((zend_long *) (strings + numelems))[strptr - strings]);
    1274       90054 :                 *oldPtr = oldVal;
    1275             :         }
    1276             : 
    1277       90587 :         efree(strings);
    1278       90587 :         RETURN_NEW_STR(str);
    1279             : }
    1280             : /* }}} */
    1281             : 
    1282             : /* {{{ proto string implode([string glue,] array pieces)
    1283             :    Joins array elements placing glue string between items and return one string */
    1284       91138 : PHP_FUNCTION(implode)
    1285             : {
    1286       91138 :         zval *arg1, *arg2 = NULL, *arr;
    1287             :         zend_string *delim;
    1288             : 
    1289             : #ifndef FAST_ZPP
    1290             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|z", &arg1, &arg2) == FAILURE) {
    1291             :                 return;
    1292             :         }
    1293             : #else
    1294       91138 :         ZEND_PARSE_PARAMETERS_START(1, 2)
    1295       91134 :                 Z_PARAM_ZVAL(arg1)
    1296       91134 :                 Z_PARAM_OPTIONAL
    1297       91134 :                 Z_PARAM_ZVAL(arg2)
    1298       91138 :         ZEND_PARSE_PARAMETERS_END();
    1299             : #endif
    1300             : 
    1301       91134 :         if (arg2 == NULL) {
    1302          20 :                 if (Z_TYPE_P(arg1) != IS_ARRAY) {
    1303           4 :                         php_error_docref(NULL, E_WARNING, "Argument must be an array");
    1304           4 :                         return;
    1305             :                 }
    1306             : 
    1307           6 :                 delim = ZSTR_EMPTY_ALLOC();
    1308           6 :                 arr = arg1;
    1309             :         } else {
    1310      182248 :                 if (Z_TYPE_P(arg1) == IS_ARRAY) {
    1311          88 :                         delim = zval_get_string(arg2);
    1312          44 :                         arr = arg1;
    1313      182160 :                 } else if (Z_TYPE_P(arg2) == IS_ARRAY) {
    1314      182106 :                         delim = zval_get_string(arg1);
    1315       91053 :                         arr = arg2;
    1316             :                 } else {
    1317          27 :                         php_error_docref(NULL, E_WARNING, "Invalid arguments passed");
    1318          27 :                         return;
    1319             :                 }
    1320             :         }
    1321             : 
    1322       91103 :         php_implode(delim, arr, return_value);
    1323             :         zend_string_release(delim);
    1324             : }
    1325             : /* }}} */
    1326             : 
    1327             : #define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
    1328             : 
    1329             : /* {{{ proto string strtok([string str,] string token)
    1330             :    Tokenize a string */
    1331         344 : PHP_FUNCTION(strtok)
    1332             : {
    1333         344 :         zend_string *str, *tok = NULL;
    1334             :         char *token;
    1335             :         char *token_end;
    1336             :         char *p;
    1337             :         char *pe;
    1338         344 :         size_t skipped = 0;
    1339             : 
    1340             : #ifndef FAST_ZPP
    1341             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &str, &tok) == FAILURE) {
    1342             :                 return;
    1343             :         }
    1344             : #else
    1345         344 :         ZEND_PARSE_PARAMETERS_START(1, 2)
    1346        1026 :                 Z_PARAM_STR(str)
    1347         336 :                 Z_PARAM_OPTIONAL
    1348         526 :                 Z_PARAM_STR(tok)
    1349         344 :         ZEND_PARSE_PARAMETERS_END();
    1350             : #endif
    1351             : 
    1352         330 :         if (ZEND_NUM_ARGS() == 1) {
    1353         241 :                 tok = str;
    1354             :         } else {
    1355          89 :                 zval_ptr_dtor(&BG(strtok_zval));
    1356         178 :                 ZVAL_STRINGL(&BG(strtok_zval), ZSTR_VAL(str), ZSTR_LEN(str));
    1357          89 :                 BG(strtok_last) = BG(strtok_string) = Z_STRVAL(BG(strtok_zval));
    1358          89 :                 BG(strtok_len) = ZSTR_LEN(str);
    1359             :         }
    1360             : 
    1361         330 :         p = BG(strtok_last); /* Where we start to search */
    1362         330 :         pe = BG(strtok_string) + BG(strtok_len);
    1363             : 
    1364         330 :         if (!p || p >= pe) {
    1365         160 :                 RETURN_FALSE;
    1366             :         }
    1367             : 
    1368         170 :         token = ZSTR_VAL(tok);
    1369         170 :         token_end = token + ZSTR_LEN(tok);
    1370             : 
    1371         987 :         while (token < token_end) {
    1372         647 :                 STRTOK_TABLE(token++) = 1;
    1373             :         }
    1374             : 
    1375             :         /* Skip leading delimiters */
    1376         427 :         while (STRTOK_TABLE(p)) {
    1377          99 :                 if (++p >= pe) {
    1378             :                         /* no other chars left */
    1379          12 :                         BG(strtok_last) = NULL;
    1380          12 :                         RETVAL_FALSE;
    1381          12 :                         goto restore;
    1382             :                 }
    1383          87 :                 skipped++;
    1384             :         }
    1385             : 
    1386             :         /* We know at this place that *p is no delimiter, so skip it */
    1387        1487 :         while (++p < pe) {
    1388        1278 :                 if (STRTOK_TABLE(p)) {
    1389         107 :                         goto return_token;
    1390             :                 }
    1391             :         }
    1392             : 
    1393          51 :         if (p - BG(strtok_last)) {
    1394             : return_token:
    1395         316 :                 RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped);
    1396         158 :                 BG(strtok_last) = p + 1;
    1397             :         } else {
    1398           0 :                 RETVAL_FALSE;
    1399           0 :                 BG(strtok_last) = NULL;
    1400             :         }
    1401             : 
    1402             :         /* Restore table -- usually faster then memset'ing the table on every invocation */
    1403             : restore:
    1404         170 :         token = ZSTR_VAL(tok);
    1405             : 
    1406         987 :         while (token < token_end) {
    1407         647 :                 STRTOK_TABLE(token++) = 0;
    1408             :         }
    1409             : }
    1410             : /* }}} */
    1411             : 
    1412             : /* {{{ php_strtoupper
    1413             :  */
    1414        1053 : PHPAPI char *php_strtoupper(char *s, size_t len)
    1415             : {
    1416             :         unsigned char *c, *e;
    1417             : 
    1418        1053 :         c = (unsigned char *)s;
    1419        1053 :         e = (unsigned char *)c+len;
    1420             : 
    1421        6424 :         while (c < e) {
    1422        4318 :                 *c = toupper(*c);
    1423        4318 :                 c++;
    1424             :         }
    1425        1053 :         return s;
    1426             : }
    1427             : /* }}} */
    1428             : 
    1429             : /* {{{ php_string_toupper
    1430             :  */
    1431        1145 : PHPAPI zend_string *php_string_toupper(zend_string *s)
    1432             : {
    1433             :         unsigned char *c, *e;
    1434             : 
    1435        1145 :         c = (unsigned char *)ZSTR_VAL(s);
    1436        1145 :         e = c + ZSTR_LEN(s);
    1437             : 
    1438        5245 :         while (c < e) {
    1439        3811 :                 if (islower(*c)) {
    1440             :                         register unsigned char *r;
    1441        1712 :                         zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
    1442             : 
    1443         856 :                         if (c != (unsigned char*)ZSTR_VAL(s)) {
    1444          87 :                                 memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
    1445             :                         }
    1446         856 :                         r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
    1447        7766 :                         while (c < e) {
    1448        6054 :                                 *r = toupper(*c);
    1449        6054 :                                 r++;
    1450        6054 :                                 c++;
    1451             :                         }
    1452         856 :                         *r = '\0';
    1453         856 :                         return res;
    1454             :                 }
    1455        2955 :                 c++;
    1456             :         }
    1457         289 :         return zend_string_copy(s);
    1458             : }
    1459             : /* }}} */
    1460             : 
    1461             : /* {{{ proto string strtoupper(string str)
    1462             :    Makes a string uppercase */
    1463         982 : PHP_FUNCTION(strtoupper)
    1464             : {
    1465             :         zend_string *arg;
    1466             : 
    1467             : #ifndef FAST_ZPP
    1468             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
    1469             :                 return;
    1470             :         }
    1471             : #else
    1472         982 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    1473        2940 :                 Z_PARAM_STR(arg)
    1474         982 :         ZEND_PARSE_PARAMETERS_END();
    1475             : #endif
    1476             : 
    1477         979 :         RETURN_STR(php_string_toupper(arg));
    1478             : }
    1479             : /* }}} */
    1480             : 
    1481             : /* {{{ php_strtolower
    1482             :  */
    1483      249124 : PHPAPI char *php_strtolower(char *s, size_t len)
    1484             : {
    1485             :         unsigned char *c, *e;
    1486             : 
    1487      249124 :         c = (unsigned char *)s;
    1488      249124 :         e = c+len;
    1489             : 
    1490     6342971 :         while (c < e) {
    1491     5844723 :                 *c = tolower(*c);
    1492     5844723 :                 c++;
    1493             :         }
    1494      249124 :         return s;
    1495             : }
    1496             : /* }}} */
    1497             : 
    1498             : /* {{{ php_string_tolower
    1499             :  */
    1500        2060 : PHPAPI zend_string *php_string_tolower(zend_string *s)
    1501             : {
    1502             :         unsigned char *c, *e;
    1503             : 
    1504        2060 :         c = (unsigned char *)ZSTR_VAL(s);
    1505        2060 :         e = c + ZSTR_LEN(s);
    1506             : 
    1507        8706 :         while (c < e) {
    1508        5882 :                 if (isupper(*c)) {
    1509             :                         register unsigned char *r;
    1510        2592 :                         zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
    1511             : 
    1512        1296 :                         if (c != (unsigned char*)ZSTR_VAL(s)) {
    1513         404 :                                 memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
    1514             :                         }
    1515        1296 :                         r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
    1516      105880 :                         while (c < e) {
    1517      103288 :                                 *r = tolower(*c);
    1518      103288 :                                 r++;
    1519      103288 :                                 c++;
    1520             :                         }
    1521        1296 :                         *r = '\0';
    1522        1296 :                         return res;
    1523             :                 }
    1524        4586 :                 c++;
    1525             :         }
    1526         764 :         return zend_string_copy(s);
    1527             : }
    1528             : /* }}} */
    1529             : 
    1530             : /* {{{ proto string strtolower(string str)
    1531             :    Makes a string lowercase */
    1532         365 : PHP_FUNCTION(strtolower)
    1533             : {
    1534             :         zend_string *str;
    1535             : 
    1536             : #ifndef FAST_ZPP
    1537             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    1538             :                 return;
    1539             :         }
    1540             : #else
    1541         365 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    1542        1089 :                 Z_PARAM_STR(str)
    1543         365 :         ZEND_PARSE_PARAMETERS_END();
    1544             : #endif
    1545             : 
    1546         362 :         RETURN_STR(php_string_tolower(str));
    1547             : }
    1548             : /* }}} */
    1549             : 
    1550             : /* {{{ php_basename
    1551             :  */
    1552       17608 : PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen)
    1553             : {
    1554             :         char *c, *comp, *cend;
    1555             :         size_t inc_len, cnt;
    1556             :         int state;
    1557             :         zend_string *ret;
    1558             : 
    1559       17608 :         c = comp = cend = (char*)s;
    1560       17608 :         cnt = len;
    1561       17608 :         state = 0;
    1562     1062829 :         while (cnt > 0) {
    1563     1027613 :                 inc_len = (*c == '\0' ? 1 : php_mblen(c, cnt));
    1564             : 
    1565     1027613 :                 switch (inc_len) {
    1566             :                         case -2:
    1567             :                         case -1:
    1568         109 :                                 inc_len = 1;
    1569         109 :                                 php_mb_reset();
    1570         109 :                                 break;
    1571             :                         case 0:
    1572           0 :                                 goto quit_loop;
    1573             :                         case 1:
    1574             : #if defined(PHP_WIN32) || defined(NETWARE)
    1575             :                                 if (*c == '/' || *c == '\\') {
    1576             : #else
    1577     1027504 :                                 if (*c == '/') {
    1578             : #endif
    1579      116717 :                                         if (state == 1) {
    1580      100381 :                                                 state = 0;
    1581      100381 :                                                 cend = c;
    1582             :                                         }
    1583             : #if defined(PHP_WIN32) || defined(NETWARE)
    1584             :                                 /* Catch relative paths in c:file.txt style. They're not to confuse
    1585             :                                    with the NTFS streams. This part ensures also, that no drive
    1586             :                                    letter traversing happens. */
    1587             :                                 } else if ((*c == ':' && (c - comp == 1))) {
    1588             :                                         if (state == 0) {
    1589             :                                                 comp = c;
    1590             :                                                 state = 1;
    1591             :                                         } else {
    1592             :                                                 cend = c;
    1593             :                                                 state = 0;
    1594             :                                         }
    1595             : #endif
    1596             :                                 } else {
    1597      910787 :                                         if (state == 0) {
    1598      117750 :                                                 comp = c;
    1599      117750 :                                                 state = 1;
    1600             :                                         }
    1601             :                                 }
    1602     1027504 :                                 break;
    1603             :                         default:
    1604           0 :                                 if (state == 0) {
    1605           0 :                                         comp = c;
    1606           0 :                                         state = 1;
    1607             :                                 }
    1608             :                                 break;
    1609             :                 }
    1610     1027613 :                 c += inc_len;
    1611     1027613 :                 cnt -= inc_len;
    1612             :         }
    1613             : 
    1614             : quit_loop:
    1615       17608 :         if (state == 1) {
    1616       17369 :                 cend = c;
    1617             :         }
    1618       33662 :         if (suffix != NULL && sufflen < (size_t)(cend - comp) &&
    1619       16054 :                         memcmp(cend - sufflen, suffix, sufflen) == 0) {
    1620       15969 :                 cend -= sufflen;
    1621             :         }
    1622             : 
    1623       17608 :         len = cend - comp;
    1624             : 
    1625       17608 :         ret = zend_string_init(comp, len, 0);
    1626       17608 :         return ret;
    1627             : }
    1628             : /* }}} */
    1629             : 
    1630             : /* {{{ proto string basename(string path [, string suffix])
    1631             :    Returns the filename component of the path */
    1632       16408 : PHP_FUNCTION(basename)
    1633             : {
    1634       16408 :         char *string, *suffix = NULL;
    1635       16408 :         size_t   string_len, suffix_len = 0;
    1636             : 
    1637       16408 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &string, &string_len, &suffix, &suffix_len) == FAILURE) {
    1638          30 :                 return;
    1639             :         }
    1640             : 
    1641       16378 :         RETURN_STR(php_basename(string, string_len, suffix, suffix_len));
    1642             : }
    1643             : /* }}} */
    1644             : 
    1645             : /* {{{ php_dirname
    1646             :    Returns directory name component of path */
    1647         463 : PHPAPI size_t php_dirname(char *path, size_t len)
    1648             : {
    1649         463 :         return zend_dirname(path, len);
    1650             : }
    1651             : /* }}} */
    1652             : 
    1653             : /* {{{ proto string dirname(string path[, int levels])
    1654             :    Returns the directory name component of the path */
    1655       27954 : PHP_FUNCTION(dirname)
    1656             : {
    1657             :         char *str;
    1658             :         size_t str_len;
    1659             :         zend_string *ret;
    1660       27954 :         zend_long levels = 1;
    1661             : 
    1662       27954 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &levels) == FAILURE) {
    1663           9 :                 return;
    1664             :         }
    1665             : 
    1666       55890 :         ret = zend_string_init(str, str_len, 0);
    1667             : 
    1668       27945 :         if (levels == 1) {
    1669             :                 /* Defaut case */
    1670             : #ifdef PHP_WIN32
    1671             :                 ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len);
    1672             : #else
    1673       27939 :                 ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
    1674             : #endif
    1675           6 :         } else if (levels < 1) {
    1676           2 :                 php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
    1677             :                 zend_string_free(ret);
    1678           2 :                 return;
    1679             :         } else {
    1680             :                 /* Some levels up */
    1681             :                 do {
    1682             : #ifdef PHP_WIN32
    1683             :                         ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret));
    1684             : #else
    1685          13 :                         ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret));
    1686             : #endif
    1687          13 :                 } while (ZSTR_LEN(ret) < str_len && --levels);
    1688             :         }
    1689             : 
    1690       27943 :         RETURN_NEW_STR(ret);
    1691             : }
    1692             : /* }}} */
    1693             : 
    1694             : /* {{{ proto array pathinfo(string path[, int options])
    1695             :    Returns information about a certain string */
    1696         615 : PHP_FUNCTION(pathinfo)
    1697             : {
    1698             :         zval tmp;
    1699             :         char *path, *dirname;
    1700             :         size_t path_len;
    1701             :         int have_basename;
    1702         615 :         zend_long opt = PHP_PATHINFO_ALL;
    1703         615 :         zend_string *ret = NULL;
    1704             : 
    1705         615 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &path_len, &opt) == FAILURE) {
    1706          25 :                 return;
    1707             :         }
    1708             : 
    1709         590 :         have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
    1710             : 
    1711         590 :         array_init(&tmp);
    1712             : 
    1713         590 :         if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
    1714         247 :                 dirname = estrndup(path, path_len);
    1715         247 :                 php_dirname(dirname, path_len);
    1716         247 :                 if (*dirname) {
    1717         224 :                         add_assoc_string(&tmp, "dirname", dirname);
    1718             :                 }
    1719         247 :                 efree(dirname);
    1720             :         }
    1721             : 
    1722         590 :         if (have_basename) {
    1723         227 :                 ret = php_basename(path, path_len, NULL, 0);
    1724         227 :                 add_assoc_str(&tmp, "basename", zend_string_copy(ret));
    1725             :         }
    1726             : 
    1727         590 :         if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
    1728             :                 const char *p;
    1729             :                 ptrdiff_t idx;
    1730             : 
    1731         238 :                 if (!have_basename) {
    1732         120 :                         ret = php_basename(path, path_len, NULL, 0);
    1733             :                 }
    1734             : 
    1735         476 :                 p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
    1736             : 
    1737         238 :                 if (p) {
    1738         130 :                         idx = p - ZSTR_VAL(ret);
    1739         130 :                         add_assoc_stringl(&tmp, "extension", ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
    1740             :                 }
    1741             :         }
    1742             : 
    1743         590 :         if ((opt & PHP_PATHINFO_FILENAME) == PHP_PATHINFO_FILENAME) {
    1744             :                 const char *p;
    1745             :                 ptrdiff_t idx;
    1746             : 
    1747             :                 /* Have we already looked up the basename? */
    1748         232 :                 if (!have_basename && !ret) {
    1749         110 :                         ret = php_basename(path, path_len, NULL, 0);
    1750             :                 }
    1751             : 
    1752         464 :                 p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
    1753             : 
    1754         232 :                 idx = p ? (p - ZSTR_VAL(ret)) : (ptrdiff_t)ZSTR_LEN(ret);
    1755         232 :                 add_assoc_stringl(&tmp, "filename", ZSTR_VAL(ret), idx);
    1756             :         }
    1757             : 
    1758         590 :         if (ret) {
    1759             :                 zend_string_release(ret);
    1760             :         }
    1761             : 
    1762         590 :         if (opt == PHP_PATHINFO_ALL) {
    1763         113 :                 ZVAL_COPY_VALUE(return_value, &tmp);
    1764             :         } else {
    1765             :                 zval *element;
    1766         477 :                 if ((element = zend_hash_get_current_data(Z_ARRVAL(tmp))) != NULL) {
    1767         401 :                         ZVAL_DEREF(element);
    1768         401 :                         ZVAL_COPY(return_value, element);
    1769             :                 } else {
    1770          76 :                         ZVAL_EMPTY_STRING(return_value);
    1771             :                 }
    1772         477 :                 zval_ptr_dtor(&tmp);
    1773             :         }
    1774             : }
    1775             : /* }}} */
    1776             : 
    1777             : /* {{{ php_stristr
    1778             :    case insensitve strstr */
    1779        6481 : PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
    1780             : {
    1781        6481 :         php_strtolower(s, s_len);
    1782        6481 :         php_strtolower(t, t_len);
    1783       12962 :         return (char*)php_memnstr(s, t, t_len, s + s_len);
    1784             : }
    1785             : /* }}} */
    1786             : 
    1787             : /* {{{ php_strspn
    1788             :  */
    1789        3381 : PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end)
    1790             : {
    1791        3381 :         register const char *p = s1, *spanp;
    1792        3381 :         register char c = *p;
    1793             : 
    1794             : cont:
    1795       44022 :         for (spanp = s2; p != s1_end && spanp != s2_end;) {
    1796       34080 :                 if (*spanp++ == c) {
    1797        3180 :                         c = *(++p);
    1798        3180 :                         goto cont;
    1799             :                 }
    1800             :         }
    1801        3381 :         return (p - s1);
    1802             : }
    1803             : /* }}} */
    1804             : 
    1805             : /* {{{ php_strcspn
    1806             :  */
    1807        3234 : PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end)
    1808             : {
    1809             :         register const char *p, *spanp;
    1810        3234 :         register char c = *s1;
    1811             : 
    1812        3234 :         for (p = s1;;) {
    1813       24666 :                 spanp = s2;
    1814             :                 do {
    1815       55604 :                         if (*spanp == c || p == s1_end) {
    1816        3234 :                                 return p - s1;
    1817             :                         }
    1818       52370 :                 } while (spanp++ < (s2_end - 1));
    1819       21432 :                 c = *++p;
    1820       21432 :         }
    1821             :         /* NOTREACHED */
    1822             : }
    1823             : /* }}} */
    1824             : 
    1825             : /* {{{ php_needle_char
    1826             :  */
    1827         305 : static int php_needle_char(zval *needle, char *target)
    1828             : {
    1829         305 :         switch (Z_TYPE_P(needle)) {
    1830             :                 case IS_LONG:
    1831          62 :                         *target = (char)Z_LVAL_P(needle);
    1832          62 :                         return SUCCESS;
    1833             :                 case IS_NULL:
    1834             :                 case IS_FALSE:
    1835         139 :                         *target = '\0';
    1836         139 :                         return SUCCESS;
    1837             :                 case IS_TRUE:
    1838          24 :                         *target = '\1';
    1839          24 :                         return SUCCESS;
    1840             :                 case IS_DOUBLE:
    1841          47 :                         *target = (char)(int)Z_DVAL_P(needle);
    1842          47 :                         return SUCCESS;
    1843             :                 case IS_OBJECT:
    1844           9 :                         *target = (char) zval_get_long(needle);
    1845           9 :                         return SUCCESS;
    1846             :                 default:
    1847          24 :                         php_error_docref(NULL, E_WARNING, "needle is not a string or an integer");
    1848          24 :                         return FAILURE;
    1849             :         }
    1850             : }
    1851             : /* }}} */
    1852             : 
    1853             : /* {{{ proto string stristr(string haystack, string needle[, bool part])
    1854             :    Finds first occurrence of a string within another, case insensitive */
    1855        6415 : PHP_FUNCTION(stristr)
    1856             : {
    1857             :         zval *needle;
    1858             :         zend_string *haystack;
    1859        6415 :         char *found = NULL;
    1860             :         size_t  found_offset;
    1861             :         char *haystack_dup;
    1862             :         char needle_char[2];
    1863        6415 :         zend_bool part = 0;
    1864             : 
    1865        6415 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|b", &haystack, &needle, &part) == FAILURE) {
    1866          11 :                 return;
    1867             :         }
    1868             : 
    1869        6404 :         haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
    1870             : 
    1871       12808 :         if (Z_TYPE_P(needle) == IS_STRING) {
    1872             :                 char *orig_needle;
    1873        6381 :                 if (!Z_STRLEN_P(needle)) {
    1874           4 :                         php_error_docref(NULL, E_WARNING, "Empty needle");
    1875           4 :                         efree(haystack_dup);
    1876           4 :                         RETURN_FALSE;
    1877             :                 }
    1878        6377 :                 orig_needle = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle));
    1879        6377 :                 found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), Z_STRLEN_P(needle));
    1880        6377 :                 efree(orig_needle);
    1881             :         } else {
    1882          23 :                 if (php_needle_char(needle, needle_char) != SUCCESS) {
    1883           5 :                         efree(haystack_dup);
    1884           5 :                         RETURN_FALSE;
    1885             :                 }
    1886          18 :                 needle_char[1] = 0;
    1887             : 
    1888          18 :                 found = php_stristr(haystack_dup, needle_char, ZSTR_LEN(haystack), 1);
    1889             :         }
    1890             : 
    1891        6395 :         if (found) {
    1892        1317 :                 found_offset = found - haystack_dup;
    1893        1317 :                 if (part) {
    1894           8 :                         RETVAL_STRINGL(ZSTR_VAL(haystack), found_offset);
    1895             :                 } else {
    1896        2626 :                         RETVAL_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset);
    1897             :                 }
    1898             :         } else {
    1899        5078 :                 RETVAL_FALSE;
    1900             :         }
    1901             : 
    1902        6395 :         efree(haystack_dup);
    1903             : }
    1904             : /* }}} */
    1905             : 
    1906             : /* {{{ proto string strstr(string haystack, string needle[, bool part])
    1907             :    Finds first occurrence of a string within another */
    1908        8547 : PHP_FUNCTION(strstr)
    1909             : {
    1910             :         zval *needle;
    1911             :         zend_string *haystack;
    1912        8547 :         char *found = NULL;
    1913             :         char needle_char[2];
    1914             :         zend_long found_offset;
    1915        8547 :         zend_bool part = 0;
    1916             : 
    1917        8547 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|b", &haystack, &needle, &part) == FAILURE) {
    1918           6 :                 return;
    1919             :         }
    1920             : 
    1921       17082 :         if (Z_TYPE_P(needle) == IS_STRING) {
    1922        8529 :                 if (!Z_STRLEN_P(needle)) {
    1923           5 :                         php_error_docref(NULL, E_WARNING, "Empty needle");
    1924           5 :                         RETURN_FALSE;
    1925             :                 }
    1926             : 
    1927       17048 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    1928             :         } else {
    1929          12 :                 if (php_needle_char(needle, needle_char) != SUCCESS) {
    1930           0 :                         RETURN_FALSE;
    1931             :                 }
    1932          12 :                 needle_char[1] = 0;
    1933             : 
    1934          24 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack), needle_char, 1, ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    1935             :         }
    1936             : 
    1937        8536 :         if (found) {
    1938        3069 :                 found_offset = found - ZSTR_VAL(haystack);
    1939        3069 :                 if (part) {
    1940          10 :                         RETURN_STRINGL(ZSTR_VAL(haystack), found_offset);
    1941             :                 } else {
    1942        6128 :                         RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
    1943             :                 }
    1944             :         }
    1945        5467 :         RETURN_FALSE;
    1946             : }
    1947             : /* }}} */
    1948             : 
    1949             : /* {{{ proto string strchr(string haystack, string needle)
    1950             :    An alias for strstr */
    1951             : /* }}} */
    1952             : 
    1953             : /* {{{ proto int strpos(string haystack, string needle [, int offset])
    1954             :    Finds position of first occurrence of a string within another */
    1955      958538 : PHP_FUNCTION(strpos)
    1956             : {
    1957             :         zval *needle;
    1958             :         zend_string *haystack;
    1959      958538 :         char *found = NULL;
    1960             :         char  needle_char[2];
    1961      958538 :         zend_long  offset = 0;
    1962             : 
    1963             : #ifndef FAST_ZPP
    1964             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &needle, &offset) == FAILURE) {
    1965             :                 return;
    1966             :         }
    1967             : #else
    1968      958538 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    1969     2875599 :                 Z_PARAM_STR(haystack)
    1970      958530 :                 Z_PARAM_ZVAL(needle)
    1971      958530 :                 Z_PARAM_OPTIONAL
    1972      977002 :                 Z_PARAM_LONG(offset)
    1973      958538 :         ZEND_PARSE_PARAMETERS_END();
    1974             : #endif
    1975             : 
    1976      958527 :         if (offset < 0) {
    1977          10 :                 offset += (zend_long)ZSTR_LEN(haystack);
    1978             :         }
    1979      958527 :         if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
    1980           6 :                 php_error_docref(NULL, E_WARNING, "Offset not contained in string");
    1981           6 :                 RETURN_FALSE;
    1982             :         }
    1983             : 
    1984     1917042 :         if (Z_TYPE_P(needle) == IS_STRING) {
    1985      958508 :                 if (!Z_STRLEN_P(needle)) {
    1986           6 :                         php_error_docref(NULL, E_WARNING, "Empty needle");
    1987           6 :                         RETURN_FALSE;
    1988             :                 }
    1989             : 
    1990     4792510 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
    1991      958502 :                                         Z_STRVAL_P(needle),
    1992      958502 :                                         Z_STRLEN_P(needle),
    1993     1917004 :                                         ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    1994             :         } else {
    1995          13 :                 if (php_needle_char(needle, needle_char) != SUCCESS) {
    1996           0 :                         RETURN_FALSE;
    1997             :                 }
    1998          13 :                 needle_char[1] = 0;
    1999             : 
    2000          39 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
    2001             :                                                         needle_char,
    2002             :                                                         1,
    2003          26 :                                     ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
    2004             :         }
    2005             : 
    2006      958515 :         if (found) {
    2007      517290 :                 RETURN_LONG(found - ZSTR_VAL(haystack));
    2008             :         } else {
    2009      441225 :                 RETURN_FALSE;
    2010             :         }
    2011             : }
    2012             : /* }}} */
    2013             : 
    2014             : /* {{{ proto int stripos(string haystack, string needle [, int offset])
    2015             :    Finds position of first occurrence of a string within another, case insensitive */
    2016         623 : PHP_FUNCTION(stripos)
    2017             : {
    2018         623 :         char *found = NULL;
    2019             :         zend_string *haystack;
    2020         623 :         zend_long offset = 0;
    2021             :         char needle_char[2];
    2022             :         zval *needle;
    2023         623 :         zend_string *needle_dup = NULL, *haystack_dup;
    2024             : 
    2025         623 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &needle, &offset) == FAILURE) {
    2026          39 :                 return;
    2027             :         }
    2028             : 
    2029         584 :         if (offset < 0) {
    2030          18 :                 offset += (zend_long)ZSTR_LEN(haystack);
    2031             :         }
    2032         584 :         if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
    2033          21 :                 php_error_docref(NULL, E_WARNING, "Offset not contained in string");
    2034          21 :                 RETURN_FALSE;
    2035             :         }
    2036             : 
    2037         563 :         if (ZSTR_LEN(haystack) == 0) {
    2038          30 :                 RETURN_FALSE;
    2039             :         }
    2040             : 
    2041        1066 :         if (Z_TYPE_P(needle) == IS_STRING) {
    2042         455 :                 if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > ZSTR_LEN(haystack)) {
    2043          20 :                         RETURN_FALSE;
    2044             :                 }
    2045             : 
    2046         435 :                 haystack_dup = php_string_tolower(haystack);
    2047         435 :                 needle_dup = php_string_tolower(Z_STR_P(needle));
    2048        1305 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
    2049         435 :                                 ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
    2050             :         } else {
    2051          78 :                 if (php_needle_char(needle, needle_char) != SUCCESS) {
    2052           6 :                         RETURN_FALSE;
    2053             :                 }
    2054          72 :                 haystack_dup = php_string_tolower(haystack);
    2055          72 :                 needle_char[0] = tolower(needle_char[0]);
    2056          72 :                 needle_char[1] = '\0';
    2057         216 :                 found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
    2058             :                                                         needle_char,
    2059             :                                                         sizeof(needle_char) - 1,
    2060          72 :                                                         ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
    2061             :         }
    2062             : 
    2063             : 
    2064         507 :         if (found) {
    2065         331 :                 RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
    2066             :         } else {
    2067         176 :                 RETVAL_FALSE;
    2068             :         }
    2069             : 
    2070             :         zend_string_release(haystack_dup);
    2071         507 :         if (needle_dup) {
    2072             :                 zend_string_release(needle_dup);
    2073             :         }
    2074             : }
    2075             : /* }}} */
    2076             : 
    2077             : /* {{{ proto int strrpos(string haystack, string needle [, int offset])
    2078             :    Finds position of last occurrence of a string within another string */
    2079         466 : PHP_FUNCTION(strrpos)
    2080             : {
    2081             :         zval *zneedle;
    2082             :         char *needle;
    2083             :         zend_string *haystack;
    2084             :         size_t needle_len;
    2085         466 :         zend_long offset = 0;
    2086             :         char *p, *e, ord_needle[2];
    2087             :         char *found;
    2088             : 
    2089             : #ifndef FAST_ZPP
    2090             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &zneedle, &offset) == FAILURE) {
    2091             :                 RETURN_FALSE;
    2092             :         }
    2093             : #else
    2094         466 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    2095        1389 :                 Z_PARAM_STR(haystack)
    2096         445 :                 Z_PARAM_ZVAL(zneedle)
    2097         445 :                 Z_PARAM_OPTIONAL
    2098         779 :                 Z_PARAM_LONG(offset)
    2099         466 :         ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
    2100             : #endif
    2101             : 
    2102         890 :         if (Z_TYPE_P(zneedle) == IS_STRING) {
    2103         365 :                 needle = Z_STRVAL_P(zneedle);
    2104         365 :                 needle_len = Z_STRLEN_P(zneedle);
    2105             :         } else {
    2106          80 :                 if (php_needle_char(zneedle, ord_needle) != SUCCESS) {
    2107           6 :                         RETURN_FALSE;
    2108             :                 }
    2109          74 :                 ord_needle[1] = '\0';
    2110          74 :                 needle = ord_needle;
    2111          74 :                 needle_len = 1;
    2112             :         }
    2113             : 
    2114         439 :         if ((ZSTR_LEN(haystack) == 0) || (needle_len == 0)) {
    2115          38 :                 RETURN_FALSE;
    2116             :         }
    2117             : 
    2118         401 :         if (offset >= 0) {
    2119         384 :                 if ((size_t)offset > ZSTR_LEN(haystack)) {
    2120           2 :                         php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2121           2 :                         RETURN_FALSE;
    2122             :                 }
    2123         382 :                 p = ZSTR_VAL(haystack) + (size_t)offset;
    2124         382 :                 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
    2125             :         } else {
    2126          17 :                 if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
    2127           4 :                         php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2128           4 :                         RETURN_FALSE;
    2129             :                 }
    2130          13 :                 p = ZSTR_VAL(haystack);
    2131          13 :                 if ((size_t)-offset < needle_len) {
    2132           3 :                         e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
    2133             :                 } else {
    2134          10 :                         e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + needle_len;
    2135             :                 }
    2136             :         }
    2137             : 
    2138         395 :         if ((found = (char *)zend_memnrstr(p, needle, needle_len, e))) {
    2139         240 :                 RETURN_LONG(found - ZSTR_VAL(haystack));
    2140             :         }
    2141             : 
    2142         155 :         RETURN_FALSE;
    2143             : }
    2144             : /* }}} */
    2145             : 
    2146             : /* {{{ proto int strripos(string haystack, string needle [, int offset])
    2147             :    Finds position of last occurrence of a string within another string */
    2148         365 : PHP_FUNCTION(strripos)
    2149             : {
    2150             :         zval *zneedle;
    2151             :         zend_string *needle;
    2152             :         zend_string *haystack;
    2153         365 :         zend_long offset = 0;
    2154             :         char *p, *e;
    2155             :         char *found;
    2156         365 :         zend_string *needle_dup, *haystack_dup, *ord_needle = NULL;
    2157             :         ALLOCA_FLAG(use_heap);
    2158             : 
    2159             : 
    2160         365 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &zneedle, &offset) == FAILURE) {
    2161           3 :                 RETURN_FALSE;
    2162             :         }
    2163             : 
    2164         724 :         ZSTR_ALLOCA_ALLOC(ord_needle, 1, use_heap);
    2165         724 :         if (Z_TYPE_P(zneedle) == IS_STRING) {
    2166         325 :                 needle = Z_STR_P(zneedle);
    2167             :         } else {
    2168          37 :                 if (php_needle_char(zneedle, ZSTR_VAL(ord_needle)) != SUCCESS) {
    2169           1 :                         ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2170           1 :                         RETURN_FALSE;
    2171             :                 }
    2172          36 :                 ZSTR_VAL(ord_needle)[1] = '\0';
    2173          36 :                 needle = ord_needle;
    2174             :         }
    2175             : 
    2176         361 :         if ((ZSTR_LEN(haystack) == 0) || (ZSTR_LEN(needle) == 0)) {
    2177          12 :                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2178          12 :                 RETURN_FALSE;
    2179             :         }
    2180             : 
    2181         349 :         if (ZSTR_LEN(needle) == 1) {
    2182             :                 /* Single character search can shortcut memcmps
    2183             :                    Can also avoid tolower emallocs */
    2184         162 :                 if (offset >= 0) {
    2185         119 :                         if ((size_t)offset > ZSTR_LEN(haystack)) {
    2186           0 :                                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2187           0 :                                 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2188           0 :                                 RETURN_FALSE;
    2189             :                         }
    2190         119 :                         p = ZSTR_VAL(haystack) + (size_t)offset;
    2191         119 :                         e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - 1;
    2192             :                 } else {
    2193          43 :                         p = ZSTR_VAL(haystack);
    2194          43 :                         if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
    2195           1 :                                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2196           1 :                                 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2197           1 :                                 RETURN_FALSE;
    2198             :                         }
    2199          42 :                         e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + (size_t)offset;
    2200             :                 }
    2201             :                 /* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */
    2202         161 :                 *ZSTR_VAL(ord_needle) = tolower(*ZSTR_VAL(needle));
    2203        4087 :                 while (e >= p) {
    2204        3890 :                         if (tolower(*e) == *ZSTR_VAL(ord_needle)) {
    2205         125 :                                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2206         125 :                                 RETURN_LONG(e - p + (offset > 0 ? offset : 0));
    2207             :                         }
    2208        3765 :                         e--;
    2209             :                 }
    2210          36 :                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2211          36 :                 RETURN_FALSE;
    2212             :         }
    2213             : 
    2214         187 :         haystack_dup = php_string_tolower(haystack);
    2215         187 :         if (offset >= 0) {
    2216         143 :                 if ((size_t)offset > ZSTR_LEN(haystack)) {
    2217             :                         zend_string_release(haystack_dup);
    2218           2 :                         ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2219           2 :                         php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2220           2 :                         RETURN_FALSE;
    2221             :                 }
    2222         141 :                 p = ZSTR_VAL(haystack_dup) + offset;
    2223         141 :                 e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
    2224             :         } else {
    2225          44 :                 if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
    2226             :                         zend_string_release(haystack_dup);
    2227           1 :                         ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2228           1 :                         php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
    2229           1 :                         RETURN_FALSE;
    2230             :                 }
    2231          43 :                 p = ZSTR_VAL(haystack_dup);
    2232          43 :                 if ((size_t)-offset < ZSTR_LEN(needle)) {
    2233          37 :                         e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
    2234             :                 } else {
    2235           6 :                         e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack) + offset + ZSTR_LEN(needle);
    2236             :                 }
    2237             :         }
    2238             : 
    2239         184 :         needle_dup = php_string_tolower(needle);
    2240         368 :         if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) {
    2241         133 :                 RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
    2242             :                 zend_string_release(needle_dup);
    2243             :                 zend_string_release(haystack_dup);
    2244         133 :                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2245             :         } else {
    2246             :                 zend_string_release(needle_dup);
    2247             :                 zend_string_release(haystack_dup);
    2248          51 :                 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
    2249          51 :                 RETURN_FALSE;
    2250             :         }
    2251             : }
    2252             : /* }}} */
    2253             : 
    2254             : /* {{{ proto string strrchr(string haystack, string needle)
    2255             :    Finds the last occurrence of a character in a string within another */
    2256         244 : PHP_FUNCTION(strrchr)
    2257             : {
    2258             :         zval *needle;
    2259             :         zend_string *haystack;
    2260         244 :         const char *found = NULL;
    2261             :         zend_long found_offset;
    2262             : 
    2263         244 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &haystack, &needle) == FAILURE) {
    2264          15 :                 return;
    2265             :         }
    2266             : 
    2267         458 :         if (Z_TYPE_P(needle) == IS_STRING) {
    2268         334 :                 found = zend_memrchr(ZSTR_VAL(haystack), *Z_STRVAL_P(needle), ZSTR_LEN(haystack));
    2269             :         } else {
    2270             :                 char needle_chr;
    2271          62 :                 if (php_needle_char(needle, &needle_chr) != SUCCESS) {
    2272           6 :                         RETURN_FALSE;
    2273             :                 }
    2274             : 
    2275         112 :                 found = zend_memrchr(ZSTR_VAL(haystack),  needle_chr, ZSTR_LEN(haystack));
    2276             :         }
    2277             : 
    2278         223 :         if (found) {
    2279         143 :                 found_offset = found - ZSTR_VAL(haystack);
    2280         286 :                 RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
    2281             :         } else {
    2282          80 :                 RETURN_FALSE;
    2283             :         }
    2284             : }
    2285             : /* }}} */
    2286             : 
    2287             : /* {{{ php_chunk_split
    2288             :  */
    2289         132 : static zend_string *php_chunk_split(char *src, size_t srclen, char *end, size_t endlen, size_t chunklen)
    2290             : {
    2291             :         char *p, *q;
    2292             :         size_t chunks; /* complete chunks! */
    2293             :         size_t restlen;
    2294             :         size_t out_len;
    2295             :         zend_string *dest;
    2296             : 
    2297         132 :         chunks = srclen / chunklen;
    2298         132 :         restlen = srclen - chunks * chunklen; /* srclen % chunklen */
    2299             : 
    2300         132 :         if (chunks > INT_MAX - 1) {
    2301           0 :                 return NULL;
    2302             :         }
    2303         132 :         out_len = chunks + 1;
    2304         132 :         if (endlen !=0 && out_len > INT_MAX/endlen) {
    2305           2 :                 return NULL;
    2306             :         }
    2307         130 :         out_len *= endlen;
    2308         130 :         if (out_len > INT_MAX - srclen - 1) {
    2309           0 :                 return NULL;
    2310             :         }
    2311         130 :         out_len += srclen + 1;
    2312             : 
    2313         130 :         dest = zend_string_alloc(out_len * sizeof(char), 0);
    2314             : 
    2315        1497 :         for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) {
    2316        1237 :                 memcpy(q, p, chunklen);
    2317        1237 :                 q += chunklen;
    2318        1237 :                 memcpy(q, end, endlen);
    2319        1237 :                 q += endlen;
    2320        1237 :                 p += chunklen;
    2321             :         }
    2322             : 
    2323         130 :         if (restlen) {
    2324         116 :                 memcpy(q, p, restlen);
    2325         116 :                 q += restlen;
    2326         116 :                 memcpy(q, end, endlen);
    2327         116 :                 q += endlen;
    2328             :         }
    2329             : 
    2330         130 :         *q = '\0';
    2331         130 :         ZSTR_LEN(dest) = q - ZSTR_VAL(dest);
    2332             : 
    2333         130 :         return dest;
    2334             : }
    2335             : /* }}} */
    2336             : 
    2337             : /* {{{ proto string chunk_split(string str [, int chunklen [, string ending]])
    2338             :    Returns split line */
    2339         204 : PHP_FUNCTION(chunk_split)
    2340             : {
    2341             :         zend_string *str;
    2342         204 :         char *end    = "\r\n";
    2343         204 :         size_t endlen   = 2;
    2344         204 :         zend_long chunklen = 76;
    2345             :         zend_string *result;
    2346             : 
    2347         204 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls", &str, &chunklen, &end, &endlen) == FAILURE) {
    2348          28 :                 return;
    2349             :         }
    2350             : 
    2351         176 :         if (chunklen <= 0) {
    2352          15 :                 php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
    2353          15 :                 RETURN_FALSE;
    2354             :         }
    2355             : 
    2356         161 :         if ((size_t)chunklen > ZSTR_LEN(str)) {
    2357             :                 /* to maintain BC, we must return original string + ending */
    2358          58 :                 result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0);
    2359          29 :                 memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str));
    2360          29 :                 memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen);
    2361          29 :                 ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
    2362          29 :                 RETURN_NEW_STR(result);
    2363             :         }
    2364             : 
    2365         132 :         if (!ZSTR_LEN(str)) {
    2366           0 :                 RETURN_EMPTY_STRING();
    2367             :         }
    2368             : 
    2369         132 :         result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen);
    2370             : 
    2371         132 :         if (result) {
    2372         130 :                 RETURN_STR(result);
    2373             :         } else {
    2374           2 :                 RETURN_FALSE;
    2375             :         }
    2376             : }
    2377             : /* }}} */
    2378             : 
    2379             : /* {{{ proto string substr(string str, int start [, int length])
    2380             :    Returns part of a string */
    2381      567990 : PHP_FUNCTION(substr)
    2382             : {
    2383             :         zend_string *str;
    2384      567990 :         zend_long l = 0, f;
    2385      567990 :         int argc = ZEND_NUM_ARGS();
    2386             : 
    2387             : #ifndef FAST_ZPP
    2388             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &str, &f, &l) == FAILURE) {
    2389             :                 return;
    2390             :         }
    2391             : #else
    2392      567990 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    2393     1703952 :                 Z_PARAM_STR(str)
    2394     1703952 :                 Z_PARAM_LONG(f)
    2395      567984 :                 Z_PARAM_OPTIONAL
    2396     1596540 :                 Z_PARAM_LONG(l)
    2397      567990 :         ZEND_PARSE_PARAMETERS_END();
    2398             : #endif
    2399             : 
    2400      567984 :         if (argc > 2) {
    2401      514278 :                 if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) {
    2402           8 :                         RETURN_FALSE;
    2403      514270 :                 } else if (l > (zend_long)ZSTR_LEN(str)) {
    2404         715 :                         l = ZSTR_LEN(str);
    2405             :                 }
    2406             :         } else {
    2407       53706 :                 l = ZSTR_LEN(str);
    2408             :         }
    2409             : 
    2410      567976 :         if (f > (zend_long)ZSTR_LEN(str)) {
    2411          14 :                 RETURN_FALSE;
    2412      567962 :         } else if (f < 0 && (size_t)-f > ZSTR_LEN(str)) {
    2413        2050 :                 f = 0;
    2414             :         }
    2415             : 
    2416      567962 :         if (l < 0 && (l + (zend_long)ZSTR_LEN(str) - f) < 0) {
    2417           2 :                 RETURN_FALSE;
    2418             :         }
    2419             : 
    2420             :         /* if "from" position is negative, count start position from the end
    2421             :          * of the string
    2422             :          */
    2423      567960 :         if (f < 0) {
    2424       50472 :                 f = (zend_long)ZSTR_LEN(str) + f;
    2425       50472 :                 if (f < 0) {
    2426           0 :                         f = 0;
    2427             :                 }
    2428             :         }
    2429             : 
    2430             :         /* if "length" position is negative, set it to the length
    2431             :          * needed to stop that many chars from the end of the string
    2432             :          */
    2433      567960 :         if (l < 0) {
    2434         110 :                 l = ((zend_long)ZSTR_LEN(str) - f) + l;
    2435         110 :                 if (l < 0) {
    2436           5 :                         l = 0;
    2437             :                 }
    2438             :         }
    2439             : 
    2440      567960 :         if ((f + l) > (zend_long)ZSTR_LEN(str)) {
    2441       52179 :                 l = ZSTR_LEN(str) - f;
    2442             :         }
    2443             : 
    2444     1135920 :         RETURN_STRINGL(ZSTR_VAL(str) + f, l);
    2445             : }
    2446             : /* }}} */
    2447             : 
    2448             : /* {{{ proto mixed substr_replace(mixed str, mixed repl, mixed start [, mixed length])
    2449             :    Replaces part of a string with another string */
    2450          62 : PHP_FUNCTION(substr_replace)
    2451             : {
    2452             :         zval *str;
    2453             :         zval *from;
    2454          62 :         zval *len = NULL;
    2455             :         zval *repl;
    2456          62 :         zend_long l = 0;
    2457             :         zend_long f;
    2458          62 :         int argc = ZEND_NUM_ARGS();
    2459             :         zend_string *result;
    2460             :         HashPosition from_idx, repl_idx, len_idx;
    2461          62 :         zval *tmp_str = NULL, *tmp_from = NULL, *tmp_repl = NULL, *tmp_len= NULL;
    2462             : 
    2463          62 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z/", &str, &repl, &from, &len) == FAILURE) {
    2464           3 :                 return;
    2465             :         }
    2466             : 
    2467         118 :         if (Z_TYPE_P(str) != IS_ARRAY) {
    2468          28 :                 convert_to_string_ex(str);
    2469             :         }
    2470         118 :         if (Z_TYPE_P(repl) != IS_ARRAY) {
    2471          68 :                 convert_to_string_ex(repl);
    2472             :         }
    2473         118 :         if (Z_TYPE_P(from) != IS_ARRAY) {
    2474          46 :                 convert_to_long_ex(from);
    2475             :         }
    2476             : 
    2477          59 :         if (argc > 3) {
    2478          96 :                 if (Z_TYPE_P(len) != IS_ARRAY) {
    2479          58 :                         convert_to_long_ex(len);
    2480          58 :                         l = zval_get_long(len);
    2481             :                 }
    2482             :         } else {
    2483          22 :                 if (Z_TYPE_P(str) != IS_ARRAY) {
    2484           5 :                         l = Z_STRLEN_P(str);
    2485             :                 }
    2486             :         }
    2487             : 
    2488         118 :         if (Z_TYPE_P(str) == IS_STRING) {
    2489          28 :                 if (
    2490           5 :                         (argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
    2491          18 :                         (argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
    2492             :                 ) {
    2493           2 :                         php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array ");
    2494           2 :                         RETURN_STR_COPY(Z_STR_P(str));
    2495             :                 }
    2496          20 :                 if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
    2497           2 :                         if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
    2498           1 :                                 php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements");
    2499           1 :                                 RETURN_STR_COPY(Z_STR_P(str));
    2500             :                         }
    2501             :                 }
    2502             :         }
    2503             : 
    2504         112 :         if (Z_TYPE_P(str) != IS_ARRAY) {
    2505          22 :                 if (Z_TYPE_P(from) != IS_ARRAY) {
    2506             :                         zend_string *repl_str;
    2507          10 :                         zend_bool repl_release = 0;
    2508          10 :                         f = Z_LVAL_P(from);
    2509             : 
    2510             :                         /* if "from" position is negative, count start position from the end
    2511             :                          * of the string
    2512             :                          */
    2513          10 :                         if (f < 0) {
    2514           0 :                                 f = (zend_long)Z_STRLEN_P(str) + f;
    2515           0 :                                 if (f < 0) {
    2516           0 :                                         f = 0;
    2517             :                                 }
    2518          10 :                         } else if ((size_t)f > Z_STRLEN_P(str)) {
    2519           1 :                                 f = Z_STRLEN_P(str);
    2520             :                         }
    2521             :                         /* if "length" position is negative, set it to the length
    2522             :                          * needed to stop that many chars from the end of the string
    2523             :                          */
    2524          10 :                         if (l < 0) {
    2525           1 :                                 l = ((zend_long)Z_STRLEN_P(str) - f) + l;
    2526           1 :                                 if (l < 0) {
    2527           0 :                                         l = 0;
    2528             :                                 }
    2529             :                         }
    2530             : 
    2531          10 :                         if ((size_t)l > Z_STRLEN_P(str) || (l < 0 && (size_t)(-l) > Z_STRLEN_P(str))) {
    2532           1 :                                 l = Z_STRLEN_P(str);
    2533             :                         }
    2534             : 
    2535          10 :                         if ((f + l) > (zend_long)Z_STRLEN_P(str)) {
    2536           5 :                                 l = Z_STRLEN_P(str) - f;
    2537             :                         }
    2538          20 :                         if (Z_TYPE_P(repl) == IS_ARRAY) {
    2539           3 :                                 repl_idx = 0;
    2540           6 :                                 while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
    2541           3 :                                         tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
    2542           3 :                                         if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
    2543           3 :                                                 break;
    2544             :                                         }
    2545           0 :                                         repl_idx++;
    2546             :                                 }
    2547           3 :                                 if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
    2548           3 :                                         repl_str = zval_get_string(tmp_repl);
    2549           3 :                                         repl_release = 1;
    2550             :                                 } else {
    2551           0 :                                         repl_str = STR_EMPTY_ALLOC();
    2552             :                                 }
    2553             :                         } else {
    2554           7 :                                 repl_str = Z_STR_P(repl);
    2555             :                         }
    2556             : 
    2557          20 :                         result = zend_string_alloc(Z_STRLEN_P(str) - l + ZSTR_LEN(repl_str), 0);
    2558             : 
    2559          10 :                         memcpy(ZSTR_VAL(result), Z_STRVAL_P(str), f);
    2560          10 :                         if (ZSTR_LEN(repl_str)) {
    2561          10 :                                 memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
    2562             :                         }
    2563          10 :                         memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l);
    2564          10 :                         ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
    2565          10 :                         if (repl_release) {
    2566             :                                 zend_string_release(repl_str);
    2567             :                         }
    2568          10 :                         RETURN_NEW_STR(result);
    2569             :                 } else {
    2570           1 :                         php_error_docref(NULL, E_WARNING, "Functionality of 'start' and 'length' as arrays is not implemented");
    2571           1 :                         RETURN_STR_COPY(Z_STR_P(str));
    2572             :                 }
    2573             :         } else { /* str is array of strings */
    2574          45 :                 zend_string *str_index = NULL;
    2575             :                 size_t result_len;
    2576             :                 zend_ulong num_index;
    2577             : 
    2578          45 :                 array_init(return_value);
    2579             : 
    2580          45 :                 from_idx = len_idx = repl_idx = 0;
    2581             : 
    2582         203 :                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(str), num_index, str_index, tmp_str) {
    2583          79 :                         zend_string *orig_str = zval_get_string(tmp_str);
    2584             : 
    2585         158 :                         if (Z_TYPE_P(from) == IS_ARRAY) {
    2586         114 :                                 while (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
    2587          51 :                                         tmp_from = &Z_ARRVAL_P(from)->arData[from_idx].val;
    2588          51 :                                         if (Z_TYPE_P(tmp_from) != IS_UNDEF) {
    2589          51 :                                                 break;
    2590             :                                         }
    2591           0 :                                         from_idx++;
    2592             :                                 }
    2593          57 :                                 if (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
    2594          51 :                                         f = zval_get_long(tmp_from);
    2595             : 
    2596          51 :                                         if (f < 0) {
    2597           0 :                                                 f = (zend_long)ZSTR_LEN(orig_str) + f;
    2598           0 :                                                 if (f < 0) {
    2599           0 :                                                         f = 0;
    2600             :                                                 }
    2601          51 :                                         } else if (f > (zend_long)ZSTR_LEN(orig_str)) {
    2602           0 :                                                 f = ZSTR_LEN(orig_str);
    2603             :                                         }
    2604          51 :                                         from_idx++;
    2605             :                                 } else {
    2606           6 :                                         f = 0;
    2607             :                                 }
    2608             :                         } else {
    2609          22 :                                 f = Z_LVAL_P(from);
    2610          22 :                                 if (f < 0) {
    2611           0 :                                         f = (zend_long)ZSTR_LEN(orig_str) + f;
    2612           0 :                                         if (f < 0) {
    2613           0 :                                                 f = 0;
    2614             :                                         }
    2615          22 :                                 } else if (f > (zend_long)ZSTR_LEN(orig_str)) {
    2616           0 :                                         f = ZSTR_LEN(orig_str);
    2617             :                                 }
    2618             :                         }
    2619             : 
    2620         181 :                         if (argc > 3 && Z_TYPE_P(len) == IS_ARRAY) {
    2621          58 :                                 while (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
    2622          23 :                                         tmp_len = &Z_ARRVAL_P(len)->arData[len_idx].val;
    2623          23 :                                         if (Z_TYPE_P(tmp_len) != IS_UNDEF) {
    2624          23 :                                                 break;
    2625             :                                         }
    2626           0 :                                         len_idx++;
    2627             :                                 }
    2628          29 :                                 if (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
    2629          23 :                                         l = zval_get_long(tmp_len);
    2630          23 :                                         len_idx++;
    2631             :                                 } else {
    2632           6 :                                         l = ZSTR_LEN(orig_str);
    2633             :                                 }
    2634          50 :                         } else if (argc > 3) {
    2635          44 :                                 l = Z_LVAL_P(len);
    2636             :                         } else {
    2637           6 :                                 l = ZSTR_LEN(orig_str);
    2638             :                         }
    2639             : 
    2640          79 :                         if (l < 0) {
    2641          23 :                                 l = (ZSTR_LEN(orig_str) - f) + l;
    2642          23 :                                 if (l < 0) {
    2643           0 :                                         l = 0;
    2644             :                                 }
    2645             :                         }
    2646             : 
    2647          79 :                         if ((f + l) > (zend_long)ZSTR_LEN(orig_str)) {
    2648          14 :                                 l = ZSTR_LEN(orig_str) - f;
    2649             :                         }
    2650             : 
    2651          79 :                         result_len = ZSTR_LEN(orig_str) - l;
    2652             : 
    2653         158 :                         if (Z_TYPE_P(repl) == IS_ARRAY) {
    2654          76 :                                 while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
    2655          23 :                                         tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
    2656          23 :                                         if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
    2657          23 :                                                 break;
    2658             :                                         }
    2659           0 :                                         repl_idx++;
    2660             :                                 }
    2661          38 :                                 if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
    2662          23 :                                         zend_string *repl_str = zval_get_string(tmp_repl);
    2663             : 
    2664          23 :                                         result_len += ZSTR_LEN(repl_str);
    2665          23 :                                         repl_idx++;
    2666          23 :                                         result = zend_string_alloc(result_len, 0);
    2667             : 
    2668          23 :                                         memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
    2669          23 :                                         memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
    2670          23 :                                         memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
    2671             :                                         zend_string_release(repl_str);
    2672             :                                 } else {
    2673          15 :                                         result = zend_string_alloc(result_len, 0);
    2674             : 
    2675          15 :                                         memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
    2676          15 :                                         memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
    2677             :                                 }
    2678             :                         } else {
    2679          41 :                                 result_len += Z_STRLEN_P(repl);
    2680             : 
    2681          41 :                                 result = zend_string_alloc(result_len, 0);
    2682             : 
    2683          41 :                                 memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
    2684          41 :                                 memcpy((ZSTR_VAL(result) + f), Z_STRVAL_P(repl), Z_STRLEN_P(repl));
    2685          41 :                                 memcpy((ZSTR_VAL(result) + f + Z_STRLEN_P(repl)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
    2686             :                         }
    2687             : 
    2688          79 :                         ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
    2689             : 
    2690          79 :                         if (str_index) {
    2691             :                                 zval tmp;
    2692             : 
    2693           2 :                                 ZVAL_NEW_STR(&tmp, result);
    2694           2 :                                 zend_symtable_update(Z_ARRVAL_P(return_value), str_index, &tmp);
    2695             :                         } else {
    2696          77 :                                 add_index_str(return_value, num_index, result);
    2697             :                         }
    2698             : 
    2699             :                         zend_string_release(orig_str);
    2700             :                 } ZEND_HASH_FOREACH_END();
    2701             :         } /* if */
    2702             : }
    2703             : /* }}} */
    2704             : 
    2705             : /* {{{ proto string quotemeta(string str)
    2706             :    Quotes meta characters */
    2707           6 : PHP_FUNCTION(quotemeta)
    2708             : {
    2709             :         zend_string *old;
    2710             :         char *old_end;
    2711             :         char *p, *q;
    2712             :         char c;
    2713             :         zend_string *str;
    2714             : 
    2715           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &old) == FAILURE) {
    2716           2 :                 return;
    2717             :         }
    2718             : 
    2719           4 :         old_end = ZSTR_VAL(old) + ZSTR_LEN(old);
    2720             : 
    2721           4 :         if (ZSTR_VAL(old) == old_end) {
    2722           0 :                 RETURN_FALSE;
    2723             :         }
    2724             : 
    2725           8 :         str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0);
    2726             : 
    2727          60 :         for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) {
    2728          56 :                 c = *p;
    2729          56 :                 switch (c) {
    2730             :                         case '.':
    2731             :                         case '\\':
    2732             :                         case '+':
    2733             :                         case '*':
    2734             :                         case '?':
    2735             :                         case '[':
    2736             :                         case '^':
    2737             :                         case ']':
    2738             :                         case '$':
    2739             :                         case '(':
    2740             :                         case ')':
    2741          24 :                                 *q++ = '\\';
    2742             :                                 /* break is missing _intentionally_ */
    2743             :                         default:
    2744          56 :                                 *q++ = c;
    2745             :                 }
    2746             :         }
    2747             : 
    2748           4 :         *q = '\0';
    2749             : 
    2750           8 :         RETURN_NEW_STR(zend_string_truncate(str, q - ZSTR_VAL(str), 0));
    2751             : }
    2752             : /* }}} */
    2753             : 
    2754             : /* {{{ proto int ord(string character)
    2755             :    Returns ASCII value of character
    2756             :    Warning: This function is special-cased by zend_compile.c and so is bypassed for constant string argument */
    2757       74304 : PHP_FUNCTION(ord)
    2758             : {
    2759             :         char   *str;
    2760             :         size_t str_len;
    2761             : 
    2762             : #ifndef FAST_ZPP
    2763             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) {
    2764             :                 return;
    2765             :         }
    2766             : #else
    2767       74304 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    2768      222900 :                 Z_PARAM_STRING(str, str_len)
    2769       74304 :         ZEND_PARSE_PARAMETERS_END();
    2770             : #endif
    2771             : 
    2772       74295 :         RETURN_LONG((unsigned char) str[0]);
    2773             : }
    2774             : /* }}} */
    2775             : 
    2776             : /* {{{ proto string chr(int ascii)
    2777             :    Converts ASCII code to a character
    2778             :    Warning: This function is special-cased by zend_compile.c and so is bypassed for constant integer argument */
    2779      660826 : PHP_FUNCTION(chr)
    2780             : {
    2781             :         zend_long c;
    2782             : 
    2783      660826 :         if (ZEND_NUM_ARGS() != 1) {
    2784           4 :                 WRONG_PARAM_COUNT;
    2785             :         }
    2786             : 
    2787             : #ifndef FAST_ZPP
    2788             :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l", &c) == FAILURE) {
    2789             :                 c = 0;
    2790             :         }
    2791             : #else
    2792      660822 :         ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
    2793     1982466 :                 Z_PARAM_LONG(c)
    2794      660822 :         ZEND_PARSE_PARAMETERS_END_EX(c = 0);
    2795             : #endif
    2796             : 
    2797      660822 :         c &= 0xff;
    2798      660822 :         if (CG(one_char_string)[c]) {
    2799           0 :                 ZVAL_INTERNED_STR(return_value, CG(one_char_string)[c]);
    2800             :         } else {
    2801     1321644 :                 ZVAL_NEW_STR(return_value, zend_string_alloc(1, 0));
    2802      660822 :                 Z_STRVAL_P(return_value)[0] = (char)c;
    2803      660822 :                 Z_STRVAL_P(return_value)[1] = '\0';
    2804             :         }
    2805             : }
    2806             : /* }}} */
    2807             : 
    2808             : /* {{{ php_ucfirst
    2809             :    Uppercase the first character of the word in a native string */
    2810          59 : static void php_ucfirst(char *str)
    2811             : {
    2812             :         register char *r;
    2813          59 :         r = str;
    2814          59 :         *r = toupper((unsigned char) *r);
    2815          59 : }
    2816             : /* }}} */
    2817             : 
    2818             : /* {{{ proto string ucfirst(string str)
    2819             :    Makes a string's first character uppercase */
    2820          67 : PHP_FUNCTION(ucfirst)
    2821             : {
    2822             :         zend_string *str;
    2823             : 
    2824             : #ifndef FAST_ZPP
    2825             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    2826             :                 return;
    2827             :         }
    2828             : #else
    2829          67 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    2830         192 :                 Z_PARAM_STR(str)
    2831          67 :         ZEND_PARSE_PARAMETERS_END();
    2832             : #endif
    2833             : 
    2834          63 :         if (!ZSTR_LEN(str)) {
    2835           4 :                 RETURN_EMPTY_STRING();
    2836             :         }
    2837             : 
    2838         118 :         ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    2839          59 :         php_ucfirst(Z_STRVAL_P(return_value));
    2840             : }
    2841             : /* }}} */
    2842             : 
    2843             : /* {{{
    2844             :    Lowercase the first character of the word in a native string */
    2845          41 : static void php_lcfirst(char *str)
    2846             : {
    2847             :         register char *r;
    2848          41 :         r = str;
    2849          41 :         *r = tolower((unsigned char) *r);
    2850          41 : }
    2851             : /* }}} */
    2852             : 
    2853             : /* {{{ proto string lcfirst(string str)
    2854             :    Make a string's first character lowercase */
    2855          49 : PHP_FUNCTION(lcfirst)
    2856             : {
    2857             :         zend_string  *str;
    2858             : 
    2859          49 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    2860           4 :                 return;
    2861             :         }
    2862             : 
    2863          45 :         if (!ZSTR_LEN(str)) {
    2864           4 :                 RETURN_EMPTY_STRING();
    2865             :         }
    2866             : 
    2867          82 :         ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    2868          41 :         php_lcfirst(Z_STRVAL_P(return_value));
    2869             : }
    2870             : /* }}} */
    2871             : 
    2872             : /* {{{ proto string ucwords(string str [, string delims])
    2873             :    Uppercase the first character of every word in a string */
    2874         115 : PHP_FUNCTION(ucwords)
    2875             : {
    2876             :         zend_string *str;
    2877         115 :         char *delims = " \t\r\n\f\v";
    2878             :         register char *r, *r_end;
    2879         115 :         size_t delims_len = 6;
    2880             :         char mask[256];
    2881             : 
    2882             : #ifndef FAST_ZPP
    2883             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|s", &str, &delims, &delims_len) == FAILURE) {
    2884             :                 return;
    2885             :         }
    2886             : #else
    2887         115 :         ZEND_PARSE_PARAMETERS_START(1, 2)
    2888         339 :                 Z_PARAM_STR(str)
    2889         107 :                 Z_PARAM_OPTIONAL
    2890         115 :                 Z_PARAM_STRING(delims, delims_len)
    2891         115 :         ZEND_PARSE_PARAMETERS_END();
    2892             : #endif
    2893             : 
    2894         107 :         if (!ZSTR_LEN(str)) {
    2895          10 :                 RETURN_EMPTY_STRING();
    2896             :         }
    2897             : 
    2898          97 :         php_charmask((unsigned char *)delims, delims_len, mask);
    2899             : 
    2900         194 :         ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    2901          97 :         r = Z_STRVAL_P(return_value);
    2902             : 
    2903          97 :         *r = toupper((unsigned char) *r);
    2904        2021 :         for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
    2905        1827 :                 if (mask[(unsigned char)*r++]) {
    2906         208 :                         *r = toupper((unsigned char) *r);
    2907             :                 }
    2908             :         }
    2909             : }
    2910             : /* }}} */
    2911             : 
    2912             : /* {{{ php_strtr
    2913             :  */
    2914          31 : PHPAPI char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen)
    2915             : {
    2916             :         size_t i;
    2917             : 
    2918          31 :         if (UNEXPECTED(trlen < 1)) {
    2919           0 :                 return str;
    2920          31 :         } else if (trlen == 1) {
    2921           0 :                 char ch_from = *str_from;
    2922           0 :                 char ch_to = *str_to;
    2923             : 
    2924           0 :                 for (i = 0; i < len; i++) {
    2925           0 :                         if (str[i] == ch_from) {
    2926           0 :                                 str[i] = ch_to;
    2927             :                         }
    2928             :                 }
    2929             :         } else {
    2930          31 :                 unsigned char xlat[256], j = 0;
    2931             : 
    2932        7936 :                 do { xlat[j] = j; } while (++j != 0);
    2933             : 
    2934        1539 :                 for (i = 0; i < trlen; i++) {
    2935        1508 :                         xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
    2936             :                 }
    2937             :                 
    2938       66288 :                 for (i = 0; i < len; i++) {
    2939       66257 :                         str[i] = xlat[(size_t)(unsigned char) str[i]];
    2940             :                 }
    2941             :         }
    2942             : 
    2943          31 :         return str;
    2944             : }
    2945             : /* }}} */
    2946             : 
    2947             : /* {{{ php_strtr_ex
    2948             :  */
    2949         113 : static zend_string *php_strtr_ex(zend_string *str, char *str_from, char *str_to, size_t trlen)
    2950             : {
    2951         113 :         zend_string *new_str = NULL;
    2952             :         size_t i;
    2953             : 
    2954         113 :         if (UNEXPECTED(trlen < 1)) {
    2955          12 :                 return zend_string_copy(str);
    2956         101 :         } else if (trlen == 1) {
    2957          17 :                 char ch_from = *str_from;
    2958          17 :                 char ch_to = *str_to;
    2959             : 
    2960          66 :                 for (i = 0; i < ZSTR_LEN(str); i++) {
    2961          66 :                         if (ZSTR_VAL(str)[i] == ch_from) {
    2962          34 :                                 new_str = zend_string_alloc(ZSTR_LEN(str), 0);
    2963          17 :                                 memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
    2964          17 :                                 ZSTR_VAL(new_str)[i] = ch_to;
    2965          17 :                                 break;
    2966             :                         }
    2967             :                 }
    2968          90 :                 for (; i < ZSTR_LEN(str); i++) {
    2969          73 :                         ZSTR_VAL(new_str)[i] = (ZSTR_VAL(str)[i] != ch_from) ? ZSTR_VAL(str)[i] : ch_to;
    2970             :                 }
    2971             :         } else {
    2972          84 :                 unsigned char xlat[256], j = 0;
    2973             : 
    2974       21504 :                 do { xlat[j] = j; } while (++j != 0);
    2975             : 
    2976        1658 :                 for (i = 0; i < trlen; i++) {
    2977        1574 :                         xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
    2978             :                 }
    2979             : 
    2980         253 :                 for (i = 0; i < ZSTR_LEN(str); i++) {
    2981         243 :                         if (ZSTR_VAL(str)[i] != xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]]) {
    2982         148 :                                 new_str = zend_string_alloc(ZSTR_LEN(str), 0);
    2983          74 :                                 memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
    2984          74 :                                 ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
    2985          74 :                                 break;
    2986             :                         }
    2987             :                 }
    2988             : 
    2989       16814 :                 for (;i < ZSTR_LEN(str); i++) {
    2990       16730 :                         ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
    2991             :                 }
    2992             :         }
    2993             : 
    2994         101 :         if (!new_str) {
    2995          10 :                 return zend_string_copy(str);
    2996             :         }
    2997             : 
    2998          91 :         ZSTR_VAL(new_str)[ZSTR_LEN(new_str)] = 0;
    2999          91 :         return new_str;
    3000             : }
    3001             : /* }}} */
    3002             : 
    3003             : /* {{{ php_strtr_array */
    3004          39 : static void php_strtr_array(zval *return_value, zend_string *input, HashTable *pats)
    3005             : {
    3006          39 :         char *str = ZSTR_VAL(input);
    3007          39 :         size_t slen = ZSTR_LEN(input);
    3008             :         zend_ulong num_key;
    3009             :         zend_string *str_key;
    3010             :         size_t len, pos, old_pos;
    3011          39 :         int num_keys = 0;
    3012          39 :         size_t minlen = 128*1024;
    3013          39 :         size_t maxlen = 0;
    3014             :         HashTable str_hash;
    3015             :         zval *entry;
    3016             :         char *key;
    3017          39 :         smart_str result = {0};
    3018             :         zend_ulong bitset[256/sizeof(zend_ulong)];
    3019             :         zend_ulong *num_bitset;
    3020             : 
    3021             :         /* we will collect all possible key lengths */
    3022          39 :         num_bitset = ecalloc((slen + sizeof(zend_ulong)) / sizeof(zend_ulong), sizeof(zend_ulong));
    3023          39 :         memset(bitset, 0, sizeof(bitset));
    3024             : 
    3025             :         /* check if original array has numeric keys */
    3026         279 :         ZEND_HASH_FOREACH_STR_KEY(pats, str_key) {
    3027         120 :                 if (UNEXPECTED(!str_key)) {
    3028           9 :                         num_keys = 1;
    3029             :                 } else {
    3030         111 :                         len = ZSTR_LEN(str_key);
    3031         111 :                         if (UNEXPECTED(len < 1)) {
    3032           0 :                                 RETURN_FALSE;
    3033         111 :                         } else if (UNEXPECTED(len > slen)) {
    3034             :                                 /* skip long patterns */
    3035          15 :                                 continue;
    3036             :                         }
    3037          96 :                         if (len > maxlen) {
    3038          74 :                                 maxlen = len;
    3039             :                         }
    3040          96 :                         if (len < minlen) {
    3041          41 :                                 minlen = len;
    3042             :                         }
    3043             :                         /* remember possible key length */
    3044          96 :                         num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
    3045          96 :                         bitset[((unsigned char)ZSTR_VAL(str_key)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(str_key)[0]) % sizeof(zend_ulong));
    3046             :                 }
    3047             :         } ZEND_HASH_FOREACH_END();
    3048             : 
    3049          39 :         if (UNEXPECTED(num_keys)) {
    3050             :                 zend_string *key_used;
    3051             :                 /* we have to rebuild HashTable with numeric keys */
    3052           8 :                 zend_hash_init(&str_hash, zend_hash_num_elements(pats), NULL, NULL, 0);
    3053          68 :                 ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
    3054          30 :                         if (UNEXPECTED(!str_key)) {
    3055           9 :                                 key_used = zend_long_to_str(num_key);
    3056           9 :                                 len = ZSTR_LEN(key_used);
    3057           9 :                                 if (UNEXPECTED(len > slen)) {
    3058             :                                         /* skip long patterns */
    3059           0 :                                         continue;
    3060             :                                 }
    3061           9 :                                 if (len > maxlen) {
    3062           1 :                                         maxlen = len;
    3063             :                                 }
    3064           9 :                                 if (len < minlen) {
    3065           1 :                                         minlen = len;
    3066             :                                 }
    3067             :                                 /* remember possible key length */
    3068           9 :                                 num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
    3069           9 :                                 bitset[((unsigned char)ZSTR_VAL(key_used)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(key_used)[0]) % sizeof(zend_ulong));
    3070             :                         } else {
    3071          21 :                                 key_used = str_key;
    3072          21 :                                 len = ZSTR_LEN(key_used);
    3073          21 :                                 if (UNEXPECTED(len > slen)) {
    3074             :                                         /* skip long patterns */
    3075           8 :                                         continue;
    3076             :                                 }
    3077             :                         }
    3078          22 :                         zend_hash_add(&str_hash, key_used, entry);
    3079          22 :                         if (UNEXPECTED(!str_key)) {
    3080             :                                 zend_string_release(key_used);
    3081             :                         }
    3082             :                 } ZEND_HASH_FOREACH_END();
    3083           8 :                 pats = &str_hash;
    3084             :         }
    3085             : 
    3086          39 :         if (UNEXPECTED(minlen > maxlen)) {
    3087             :                 /* return the original string */
    3088           0 :                 if (pats == &str_hash) {
    3089           0 :                         zend_hash_destroy(&str_hash);
    3090             :                 }
    3091           0 :                 efree(num_bitset);
    3092           0 :                 RETURN_STR_COPY(input);
    3093             :         }
    3094             : 
    3095          39 :         old_pos = pos = 0;
    3096         983 :         while (pos <= slen - minlen) {
    3097         905 :                 key = str + pos;
    3098         905 :                 if (bitset[((unsigned char)key[0]) / sizeof(zend_ulong)] & (Z_UL(1) << (((unsigned char)key[0]) % sizeof(zend_ulong)))) {
    3099          95 :                         len = maxlen;
    3100          95 :                         if (len > slen - pos) {
    3101           2 :                                 len = slen - pos;
    3102             :                         }
    3103         305 :                         while (len >= minlen) {
    3104         206 :                                 if ((num_bitset[len / sizeof(zend_ulong)] & (Z_UL(1) << (len % sizeof(zend_ulong))))) {
    3105         160 :                                         entry = zend_hash_str_find(pats, key, len);
    3106         160 :                                         if (entry != NULL) {
    3107          91 :                                                 zend_string *s = zval_get_string(entry);
    3108          91 :                                                 smart_str_appendl(&result, str + old_pos, pos - old_pos);
    3109             :                                                 smart_str_append(&result, s);
    3110          91 :                                                 old_pos = pos + len;
    3111          91 :                                                 pos = old_pos - 1;
    3112             :                                                 zend_string_release(s);
    3113          91 :                                                 break;
    3114             :                                         }
    3115             :                                 }
    3116         115 :                                 len--;
    3117             :                         }
    3118             :                 }
    3119         905 :                 pos++;
    3120             :         }
    3121             : 
    3122          39 :         if (result.s) {
    3123          26 :                 smart_str_appendl(&result, str + old_pos, slen - old_pos);
    3124             :                 smart_str_0(&result);
    3125          26 :                 RETVAL_NEW_STR(result.s);
    3126             :         } else {
    3127             :                 smart_str_free(&result);
    3128          13 :                 RETVAL_STR_COPY(input);
    3129             :         }
    3130             : 
    3131          39 :         if (pats == &str_hash) {
    3132           8 :                 zend_hash_destroy(&str_hash);
    3133             :         }
    3134          39 :         efree(num_bitset);
    3135             : }
    3136             : /* }}} */
    3137             : 
    3138             : /* {{{ php_char_to_str_ex
    3139             :  */
    3140        6545 : static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, size_t to_len, int case_sensitivity, zend_long *replace_count)
    3141             : {
    3142             :         zend_string *result;
    3143        6545 :         size_t char_count = 0;
    3144        6545 :         char lc_from = 0;
    3145        6545 :         char *source, *target, *source_end= ZSTR_VAL(str) + ZSTR_LEN(str);
    3146             : 
    3147        6545 :         if (case_sensitivity) {
    3148        6535 :                 char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str);
    3149       22287 :                 while ((p = memchr(p, from, (e - p)))) {
    3150        9217 :                         char_count++;
    3151        9217 :                         p++;
    3152             :                 }
    3153             :         } else {
    3154          10 :                 lc_from = tolower(from);
    3155         327 :                 for (source = ZSTR_VAL(str); source < source_end; source++) {
    3156         317 :                         if (tolower(*source) == lc_from) {
    3157          29 :                                 char_count++;
    3158             :                         }
    3159             :                 }
    3160             :         }
    3161             : 
    3162        6545 :         if (char_count == 0) {
    3163        1363 :                 return zend_string_copy(str);
    3164             :         }
    3165             : 
    3166        5182 :         if (to_len > 0) {
    3167        3318 :                 result = zend_string_safe_alloc(char_count, to_len - 1, ZSTR_LEN(str), 0);
    3168             :         } else {
    3169        7046 :                 result = zend_string_alloc(ZSTR_LEN(str) - char_count, 0);
    3170             :         }
    3171        5182 :         target = ZSTR_VAL(result);
    3172             : 
    3173        5182 :         if (case_sensitivity) {
    3174        5177 :                 char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str), *s = ZSTR_VAL(str);
    3175       19571 :                 while ((p = memchr(p, from, (e - p)))) {
    3176        9217 :                         memcpy(target, s, (p - s));
    3177        9217 :                         target += p - s;
    3178        9217 :                         memcpy(target, to, to_len);
    3179        9217 :                         target += to_len;
    3180        9217 :                         p++;
    3181        9217 :                         s = p;
    3182        9217 :                         if (replace_count) {
    3183        8946 :                                 *replace_count += 1;
    3184             :                         }
    3185             :                 }
    3186        5177 :                 if (s < e) {
    3187        1387 :                         memcpy(target, s, (e - s));
    3188        1387 :                         target += e - s;
    3189             :                 }
    3190             :         } else {
    3191         212 :                 for (source = ZSTR_VAL(str); source < source_end; source++) {
    3192         207 :                         if (tolower(*source) == lc_from) {
    3193          29 :                                 if (replace_count) {
    3194          29 :                                         *replace_count += 1;
    3195             :                                 }
    3196          29 :                                 memcpy(target, to, to_len);
    3197          29 :                                 target += to_len;
    3198             :                         } else {
    3199         178 :                                 *target = *source;
    3200         178 :                                 target++;
    3201             :                         }
    3202             :                 }
    3203             :         }
    3204        5182 :         *target = 0;
    3205        5182 :         return result;
    3206             : }
    3207             : /* }}} */
    3208             : 
    3209             : /* {{{ php_str_to_str_ex
    3210             :  */
    3211      186922 : static zend_string *php_str_to_str_ex(zend_string *haystack,
    3212             :         char *needle, size_t needle_len, char *str, size_t str_len, zend_long *replace_count)
    3213             : {
    3214             :         zend_string *new_str;
    3215             : 
    3216      186922 :         if (needle_len < ZSTR_LEN(haystack)) {
    3217             :                 char *end;
    3218             :                 char *e, *s, *p, *r;
    3219             : 
    3220      184378 :                 if (needle_len == str_len) {
    3221       27131 :                         new_str = NULL;
    3222       27131 :                         end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
    3223       56884 :                         for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3224        1311 :                                 if (!new_str) {
    3225        1002 :                                         new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
    3226             :                                 }
    3227        1311 :                                 memcpy(ZSTR_VAL(new_str) + (r - ZSTR_VAL(haystack)), str, str_len);
    3228        1311 :                                 (*replace_count)++;
    3229             :                         }
    3230       27131 :                         if (!new_str) {
    3231       26630 :                                 goto nothing_todo;
    3232             :                         }
    3233         501 :                         return new_str;
    3234             :                 } else {
    3235      157247 :                         size_t count = 0;
    3236      157247 :                         char *o = ZSTR_VAL(haystack);
    3237      157247 :                         char *n = needle;
    3238      157247 :                         char *endp = o + ZSTR_LEN(haystack);
    3239             : 
    3240      418446 :                         while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
    3241      103952 :                                 o += needle_len;
    3242      103952 :                                 count++;
    3243             :                         }
    3244      157247 :                         if (count == 0) {
    3245             :                                 /* Needle doesn't occur, shortcircuit the actual replacement. */
    3246      112241 :                                 goto nothing_todo;
    3247             :                         }
    3248       45006 :                         if (str_len > needle_len) {
    3249       22000 :                                 new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0);
    3250             :                         } else {
    3251       68012 :                                 new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0);
    3252             :                         }
    3253             : 
    3254       45006 :                         e = s = ZSTR_VAL(new_str);
    3255       45006 :                         end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
    3256      297916 :                         for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3257      103952 :                                 memcpy(e, p, r - p);
    3258      103952 :                                 e += r - p;
    3259      103952 :                                 memcpy(e, str, str_len);
    3260      103952 :                                 e += str_len;
    3261      103952 :                                 (*replace_count)++;
    3262             :                         }
    3263             : 
    3264       45006 :                         if (p < end) {
    3265       43754 :                                 memcpy(e, p, end - p);
    3266       43754 :                                 e += end - p;
    3267             :                         }
    3268             : 
    3269       45006 :                         *e = '\0';
    3270       45006 :                         return new_str;
    3271             :                 }
    3272        2544 :         } else if (needle_len > ZSTR_LEN(haystack) || memcmp(ZSTR_VAL(haystack), needle, ZSTR_LEN(haystack))) {
    3273             : nothing_todo:
    3274      141388 :                 return zend_string_copy(haystack);
    3275             :         } else {
    3276          27 :                 new_str = zend_string_init(str, str_len, 0);
    3277          27 :                 (*replace_count)++;
    3278          27 :                 return new_str;
    3279             :         }
    3280             : }
    3281             : /* }}} */
    3282             : 
    3283             : /* {{{ php_str_to_str_i_ex
    3284             :  */
    3285         106 : static zend_string *php_str_to_str_i_ex(zend_string *haystack, char *lc_haystack,
    3286             :         zend_string *needle, char *str, size_t str_len, zend_long *replace_count)
    3287             : {
    3288         106 :         zend_string *new_str = NULL;
    3289             :         zend_string *lc_needle;
    3290             : 
    3291         106 :         if (ZSTR_LEN(needle) < ZSTR_LEN(haystack)) {
    3292             :                 char *end;
    3293             :                 char *e, *s, *p, *r;
    3294             : 
    3295          71 :                 if (ZSTR_LEN(needle) == str_len) {
    3296           2 :                         lc_needle = php_string_tolower(needle);
    3297           2 :                         end = lc_haystack + ZSTR_LEN(haystack);
    3298          32 :                         for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
    3299          14 :                                 if (!new_str) {
    3300           4 :                                         new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
    3301             :                                 }
    3302          14 :                                 memcpy(ZSTR_VAL(new_str) + (r - lc_haystack), str, str_len);
    3303          14 :                                 (*replace_count)++;
    3304             :                         }
    3305             :                         zend_string_release(lc_needle);
    3306             : 
    3307           2 :                         if (!new_str) {
    3308           0 :                                 goto nothing_todo;
    3309             :                         }
    3310           2 :                         return new_str;
    3311             :                 } else {
    3312          69 :                         size_t count = 0;
    3313          69 :                         char *o = lc_haystack;
    3314             :                         char *n;
    3315          69 :                         char *endp = o + ZSTR_LEN(haystack);
    3316             : 
    3317          69 :                         lc_needle = php_string_tolower(needle);
    3318          69 :                         n = ZSTR_VAL(lc_needle);
    3319             : 
    3320         509 :                         while ((o = (char*)php_memnstr(o, n, ZSTR_LEN(lc_needle), endp))) {
    3321         151 :                                 o += ZSTR_LEN(lc_needle);
    3322         151 :                                 count++;
    3323             :                         }
    3324          69 :                         if (count == 0) {
    3325             :                                 /* Needle doesn't occur, shortcircuit the actual replacement. */
    3326             :                                 zend_string_release(lc_needle);
    3327           8 :                                 goto nothing_todo;
    3328             :                         }
    3329             :                         
    3330          61 :                         if (str_len > ZSTR_LEN(lc_needle)) {
    3331          26 :                                 new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0);
    3332             :                         } else {
    3333          96 :                                 new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0);
    3334             :                         }
    3335             : 
    3336          61 :                         e = s = ZSTR_VAL(new_str);
    3337          61 :                         end = lc_haystack + ZSTR_LEN(haystack);
    3338             : 
    3339         424 :                         for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
    3340         151 :                                 memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), r - p);
    3341         151 :                                 e += r - p;
    3342         151 :                                 memcpy(e, str, str_len);
    3343         151 :                                 e += str_len;
    3344         151 :                                 (*replace_count)++;
    3345             :                         }
    3346             : 
    3347          61 :                         if (p < end) {
    3348          21 :                                 memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), end - p);
    3349          21 :                                 e += end - p;
    3350             :                         }
    3351          61 :                         *e = '\0';
    3352             : 
    3353             :                         zend_string_release(lc_needle);
    3354             : 
    3355          61 :                         return new_str;
    3356             :                 }
    3357          35 :         } else if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
    3358             : nothing_todo:
    3359           9 :                 return zend_string_copy(haystack);
    3360             :         } else {
    3361          35 :                 lc_needle = php_string_tolower(needle);
    3362             : 
    3363          35 :                 if (memcmp(lc_haystack, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle))) {
    3364             :                         zend_string_release(lc_needle);
    3365           1 :                         goto nothing_todo;
    3366             :                 }
    3367             :                 zend_string_release(lc_needle);
    3368             : 
    3369          34 :                 new_str = zend_string_init(str, str_len, 0);
    3370             : 
    3371          34 :                 (*replace_count)++;
    3372          34 :                 return new_str;
    3373             :         }
    3374             : }
    3375             : /* }}} */
    3376             : 
    3377             : /* {{{ php_str_to_str
    3378             :  */
    3379        1440 : PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle, size_t needle_len, char *str, size_t str_len)
    3380             : {
    3381             :         zend_string *new_str;
    3382             : 
    3383        1440 :         if (needle_len < length) {
    3384             :                 char *end;
    3385             :                 char *e, *s, *p, *r;
    3386             : 
    3387        1052 :                 if (needle_len == str_len) {
    3388           0 :                         new_str = zend_string_init(haystack, length, 0);
    3389           0 :                         end = ZSTR_VAL(new_str) + length;
    3390           0 :                         for (p = ZSTR_VAL(new_str); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3391           0 :                                 memcpy(r, str, str_len);
    3392             :                         }
    3393           0 :                         return new_str;
    3394             :                 } else {
    3395        1052 :                         if (str_len < needle_len) {
    3396           0 :                                 new_str = zend_string_alloc(length, 0);
    3397             :                         } else {
    3398        1052 :                                 size_t count = 0;
    3399        1052 :                                 char *o = haystack;
    3400        1052 :                                 char *n = needle;
    3401        1052 :                                 char *endp = o + length;
    3402             : 
    3403        2125 :                                 while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
    3404          21 :                                         o += needle_len;
    3405          21 :                                         count++;
    3406             :                                 }
    3407        1052 :                                 if (count == 0) {
    3408             :                                         /* Needle doesn't occur, shortcircuit the actual replacement. */
    3409        1041 :                                         new_str = zend_string_init(haystack, length, 0);
    3410        1041 :                                         return new_str;
    3411             :                                 } else {
    3412          11 :                                         if (str_len > needle_len) {
    3413          22 :                                                 new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0);
    3414             :                                         } else {
    3415           0 :                                                 new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0);
    3416             :                                         }
    3417             :                                 }
    3418             :                         }
    3419             : 
    3420          11 :                         e = s = ZSTR_VAL(new_str);
    3421          11 :                         end = haystack + length;
    3422          64 :                         for (p = haystack; (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3423          21 :                                 memcpy(e, p, r - p);
    3424          21 :                                 e += r - p;
    3425          21 :                                 memcpy(e, str, str_len);
    3426          21 :                                 e += str_len;
    3427             :                         }
    3428             : 
    3429          11 :                         if (p < end) {
    3430           8 :                                 memcpy(e, p, end - p);
    3431           8 :                                 e += end - p;
    3432             :                         }
    3433             : 
    3434          11 :                         *e = '\0';
    3435          22 :                         new_str = zend_string_truncate(new_str, e - s, 0);
    3436          11 :                         return new_str;
    3437             :                 }
    3438         388 :         } else if (needle_len > length || memcmp(haystack, needle, length)) {
    3439         380 :                 new_str = zend_string_init(haystack, length, 0);
    3440         380 :                 return new_str;
    3441             :         } else {
    3442           8 :                 new_str = zend_string_init(str, str_len, 0);
    3443             : 
    3444           8 :                 return new_str;
    3445             :         }
    3446             : }
    3447             : /* }}} */
    3448             : 
    3449             : /* {{{ proto string strtr(string str, string from[, string to])
    3450             :    Translates characters in str using given translation tables */
    3451         217 : PHP_FUNCTION(strtr)
    3452             : {
    3453             :         zval *from;
    3454             :         zend_string *str;
    3455         217 :         char *to = NULL;
    3456         217 :         size_t to_len = 0;
    3457         217 :         int ac = ZEND_NUM_ARGS();
    3458             : 
    3459             : #ifndef FAST_ZPP
    3460             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|s", &str, &from, &to, &to_len) == FAILURE) {
    3461             :                 return;
    3462             :         }
    3463             : #else
    3464         217 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    3465         642 :                 Z_PARAM_STR(str)
    3466         198 :                 Z_PARAM_ZVAL(from)
    3467         198 :                 Z_PARAM_OPTIONAL
    3468         422 :                 Z_PARAM_STRING(to, to_len)
    3469         217 :         ZEND_PARSE_PARAMETERS_END();
    3470             : #endif
    3471             : 
    3472         280 :         if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
    3473          31 :                 php_error_docref(NULL, E_WARNING, "The second argument is not an array");
    3474          31 :                 RETURN_FALSE;
    3475             :         }
    3476             : 
    3477             :         /* shortcut for empty string */
    3478         163 :         if (ZSTR_LEN(str) == 0) {
    3479          27 :                 RETURN_EMPTY_STRING();
    3480             :         }
    3481             : 
    3482         136 :         if (ac == 2) {
    3483          47 :                 HashTable *pats = Z_ARRVAL_P(from);
    3484             : 
    3485          47 :                 if (zend_hash_num_elements(pats) < 1) {
    3486           2 :                         RETURN_STR_COPY(str);
    3487          45 :                 } else if (zend_hash_num_elements(pats) == 1) {
    3488             :                         zend_long num_key;
    3489             :                         zend_string *str_key, *replace;
    3490             :                         zval *entry, tmp;
    3491             : 
    3492          18 :                         ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
    3493           6 :                                 ZVAL_UNDEF(&tmp);
    3494           6 :                                 if (UNEXPECTED(!str_key)) {
    3495           2 :                                         ZVAL_LONG(&tmp, num_key);
    3496           2 :                                         convert_to_string(&tmp);
    3497           2 :                                         str_key = Z_STR(tmp);
    3498             :                                 }               
    3499           6 :                                 replace = zval_get_string(entry);
    3500           6 :                                 if (ZSTR_LEN(str_key) < 1) {
    3501           0 :                                         RETVAL_STR_COPY(str);
    3502           6 :                                 } else if (ZSTR_LEN(str_key) == 1) {
    3503           3 :                                         RETVAL_STR(php_char_to_str_ex(str,
    3504             :                                                                 ZSTR_VAL(str_key)[0],
    3505             :                                                                 ZSTR_VAL(replace),
    3506             :                                                                 ZSTR_LEN(replace),
    3507             :                                                                 1,
    3508             :                                                                 NULL));
    3509             :                                 } else {
    3510             :                                         zend_long dummy;
    3511           3 :                                         RETVAL_STR(php_str_to_str_ex(str,
    3512             :                                                                 ZSTR_VAL(str_key), ZSTR_LEN(str_key),
    3513             :                                                                 ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy));
    3514             :                                 }
    3515             :                                 zend_string_release(replace);
    3516             :                                 zval_dtor(&tmp);
    3517           6 :                                 return;
    3518             :                         } ZEND_HASH_FOREACH_END();
    3519             :                 } else {
    3520          39 :                         php_strtr_array(return_value, str, pats);
    3521             :                 }
    3522             :         } else {
    3523         206 :                 convert_to_string_ex(from);
    3524             : 
    3525          89 :                 RETURN_STR(php_strtr_ex(str,
    3526             :                                   Z_STRVAL_P(from),
    3527             :                                   to,
    3528             :                                   MIN(Z_STRLEN_P(from), to_len)));
    3529             :         }
    3530             : }
    3531             : /* }}} */
    3532             : 
    3533             : /* {{{ proto string strrev(string str)
    3534             :    Reverse a string */
    3535         104 : PHP_FUNCTION(strrev)
    3536             : {
    3537             :         zend_string *str;
    3538             :         char *e, *p;
    3539             :         zend_string *n;
    3540             : 
    3541         104 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    3542           8 :                 return;
    3543             :         }
    3544             : 
    3545         192 :         n = zend_string_alloc(ZSTR_LEN(str), 0);
    3546          96 :         p = ZSTR_VAL(n);
    3547             : 
    3548          96 :         e = ZSTR_VAL(str) + ZSTR_LEN(str);
    3549             : 
    3550        4317 :         while (--e >= ZSTR_VAL(str)) {
    3551        4125 :                 *p++ = *e;
    3552             :         }
    3553             : 
    3554          96 :         *p = '\0';
    3555             : 
    3556          96 :         RETVAL_NEW_STR(n);
    3557             : }
    3558             : /* }}} */
    3559             : 
    3560             : /* {{{ php_similar_str
    3561             :  */
    3562          10 : static void php_similar_str(const char *txt1, size_t len1, const char *txt2, size_t len2, size_t *pos1, size_t *pos2, size_t *max)
    3563             : {
    3564             :         char *p, *q;
    3565          10 :         char *end1 = (char *) txt1 + len1;
    3566          10 :         char *end2 = (char *) txt2 + len2;
    3567             :         size_t l;
    3568             : 
    3569          10 :         *max = 0;
    3570         104 :         for (p = (char *) txt1; p < end1; p++) {
    3571         602 :                 for (q = (char *) txt2; q < end2; q++) {
    3572         508 :                         for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
    3573         508 :                         if (l > *max) {
    3574           6 :                                 *max = l;
    3575           6 :                                 *pos1 = p - txt1;
    3576           6 :                                 *pos2 = q - txt2;
    3577             :                         }
    3578             :                 }
    3579             :         }
    3580          10 : }
    3581             : /* }}} */
    3582             : 
    3583             : /* {{{ php_similar_char
    3584             :  */
    3585          10 : static size_t php_similar_char(const char *txt1, size_t len1, const char *txt2, size_t len2)
    3586             : {
    3587             :         size_t sum;
    3588          10 :         size_t pos1 = 0, pos2 = 0, max;
    3589             : 
    3590          10 :         php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);
    3591          10 :         if ((sum = max)) {
    3592           6 :                 if (pos1 && pos2) {
    3593           0 :                         sum += php_similar_char(txt1, pos1,
    3594             :                                                                         txt2, pos2);
    3595             :                 }
    3596           6 :                 if ((pos1 + max < len1) && (pos2 + max < len2)) {
    3597           2 :                         sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
    3598           2 :                                                                         txt2 + pos2 + max, len2 - pos2 - max);
    3599             :                 }
    3600             :         }
    3601             : 
    3602          10 :         return sum;
    3603             : }
    3604             : /* }}} */
    3605             : 
    3606             : /* {{{ proto int similar_text(string str1, string str2 [, float percent])
    3607             :    Calculates the similarity between two strings */
    3608          10 : PHP_FUNCTION(similar_text)
    3609             : {
    3610             :         zend_string *t1, *t2;
    3611          10 :         zval *percent = NULL;
    3612          10 :         int ac = ZEND_NUM_ARGS();
    3613             :         size_t sim;
    3614             : 
    3615          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|z/", &t1, &t2, &percent) == FAILURE) {
    3616           2 :                 return;
    3617             :         }
    3618             : 
    3619           8 :         if (ac > 2) {
    3620           8 :                 convert_to_double_ex(percent);
    3621             :         }
    3622             : 
    3623           8 :         if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) {
    3624           0 :                 if (ac > 2) {
    3625           0 :                         Z_DVAL_P(percent) = 0;
    3626             :                 }
    3627             : 
    3628           0 :                 RETURN_LONG(0);
    3629             :         }
    3630             : 
    3631           8 :         sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2));
    3632             : 
    3633           8 :         if (ac > 2) {
    3634           4 :                 Z_DVAL_P(percent) = sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2));
    3635             :         }
    3636             : 
    3637           8 :         RETURN_LONG(sim);
    3638             : }
    3639             : /* }}} */
    3640             : 
    3641             : /* {{{ php_stripslashes
    3642             :  *
    3643             :  * be careful, this edits the string in-place */
    3644         103 : PHPAPI void php_stripslashes(zend_string *str)
    3645             : {
    3646             :         char *s, *t;
    3647             :         size_t l;
    3648             : 
    3649         103 :         s = ZSTR_VAL(str);
    3650         103 :         t = ZSTR_VAL(str);
    3651         103 :         l = ZSTR_LEN(str);
    3652             : 
    3653        1609 :         while (l > 0) {
    3654        1403 :                 if (*t == '\\') {
    3655         116 :                         t++;                            /* skip the slash */
    3656         116 :                         ZSTR_LEN(str)--;
    3657         116 :                         l--;
    3658         116 :                         if (l > 0) {
    3659         116 :                                 if (*t == '0') {
    3660          15 :                                         *s++='\0';
    3661          15 :                                         t++;
    3662             :                                 } else {
    3663         101 :                                         *s++ = *t++;    /* preserve the next character */
    3664             :                                 }
    3665         116 :                                 l--;
    3666             :                         }
    3667             :                 } else {
    3668        1287 :                         *s++ = *t++;
    3669        1287 :                         l--;
    3670             :                 }
    3671             :         }
    3672         103 :         if (s != t) {
    3673          67 :                 *s = '\0';
    3674             :         }
    3675         103 : }
    3676             : /* }}} */
    3677             : 
    3678             : /* {{{ proto string addcslashes(string str, string charlist)
    3679             :    Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...) */
    3680          45 : PHP_FUNCTION(addcslashes)
    3681             : {
    3682             :         zend_string *str, *what;
    3683             : 
    3684          45 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str, &what) == FAILURE) {
    3685           4 :                 return;
    3686             :         }
    3687             : 
    3688          41 :         if (ZSTR_LEN(str) == 0) {
    3689           6 :                 RETURN_EMPTY_STRING();
    3690             :         }
    3691             : 
    3692          35 :         if (ZSTR_LEN(what) == 0) {
    3693          10 :                 RETURN_STRINGL(ZSTR_VAL(str), ZSTR_LEN(str));
    3694             :         }
    3695             : 
    3696          30 :         RETURN_STR(php_addcslashes(str, 0, ZSTR_VAL(what), ZSTR_LEN(what)));
    3697             : }
    3698             : /* }}} */
    3699             : 
    3700             : /* {{{ proto string addslashes(string str)
    3701             :    Escapes single quote, double quotes and backslash characters in a string with backslashes */
    3702      494880 : PHP_FUNCTION(addslashes)
    3703             : {
    3704             :         zend_string *str;
    3705             : 
    3706             : #ifndef FAST_ZPP
    3707             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    3708             :                 return;
    3709             :         }
    3710             : #else
    3711      494880 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    3712     1484634 :                 Z_PARAM_STR(str)
    3713      494880 :         ZEND_PARSE_PARAMETERS_END();
    3714             : #endif
    3715             : 
    3716      494872 :         if (ZSTR_LEN(str) == 0) {
    3717      131250 :                 RETURN_EMPTY_STRING();
    3718             :         }
    3719             : 
    3720      363622 :         RETURN_STR(php_addslashes(str, 0));
    3721             : }
    3722             : /* }}} */
    3723             : 
    3724             : /* {{{ proto string stripcslashes(string str)
    3725             :    Strips backslashes from a string. Uses C-style conventions */
    3726          41 : PHP_FUNCTION(stripcslashes)
    3727             : {
    3728             :         zend_string *str;
    3729             : 
    3730          41 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    3731           8 :                 return;
    3732             :         }
    3733             : 
    3734          66 :         ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    3735          33 :         php_stripcslashes(Z_STR_P(return_value));
    3736             : }
    3737             : /* }}} */
    3738             : 
    3739             : /* {{{ proto string stripslashes(string str)
    3740             :    Strips backslashes from a string */
    3741         111 : PHP_FUNCTION(stripslashes)
    3742             : {
    3743             :         zend_string *str;
    3744             : 
    3745         111 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
    3746           8 :                 return;
    3747             :         }
    3748             : 
    3749         206 :         ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    3750         103 :         php_stripslashes(Z_STR_P(return_value));
    3751             : }
    3752             : /* }}} */
    3753             : 
    3754             : #ifndef HAVE_STRERROR
    3755             : /* {{{ php_strerror
    3756             :  */
    3757             : char *php_strerror(int errnum)
    3758             : {
    3759             :         extern int sys_nerr;
    3760             :         extern char *sys_errlist[];
    3761             : 
    3762             :         if ((unsigned int) errnum < sys_nerr) {
    3763             :                 return(sys_errlist[errnum]);
    3764             :         }
    3765             : 
    3766             :         (void) snprintf(BG(str_ebuf), sizeof(php_basic_globals.str_ebuf), "Unknown error: %d", errnum);
    3767             :         return(BG(str_ebuf));
    3768             : }
    3769             : /* }}} */
    3770             : #endif
    3771             : 
    3772             : /* {{{ php_stripcslashes
    3773             :  */
    3774          33 : PHPAPI void php_stripcslashes(zend_string *str)
    3775             : {
    3776             :         char *source, *target, *end;
    3777          33 :         size_t  nlen = ZSTR_LEN(str), i;
    3778             :         char numtmp[4];
    3779             : 
    3780         157 :         for (source = (char*)ZSTR_VAL(str), end = source + ZSTR_LEN(str), target = ZSTR_VAL(str); source < end; source++) {
    3781         165 :                 if (*source == '\\' && source + 1 < end) {
    3782          41 :                         source++;
    3783          41 :                         switch (*source) {
    3784           2 :                                 case 'n':  *target++='\n'; nlen--; break;
    3785           2 :                                 case 'r':  *target++='\r'; nlen--; break;
    3786           1 :                                 case 'a':  *target++='\a'; nlen--; break;
    3787           1 :                                 case 't':  *target++='\t'; nlen--; break;
    3788           1 :                                 case 'v':  *target++='\v'; nlen--; break;
    3789           1 :                                 case 'b':  *target++='\b'; nlen--; break;
    3790           1 :                                 case 'f':  *target++='\f'; nlen--; break;
    3791           1 :                                 case '\\': *target++='\\'; nlen--; break;
    3792             :                                 case 'x':
    3793          11 :                                         if (source+1 < end && isxdigit((int)(*(source+1)))) {
    3794          11 :                                                 numtmp[0] = *++source;
    3795          22 :                                                 if (source+1 < end && isxdigit((int)(*(source+1)))) {
    3796          11 :                                                         numtmp[1] = *++source;
    3797          11 :                                                         numtmp[2] = '\0';
    3798          11 :                                                         nlen-=3;
    3799             :                                                 } else {
    3800           0 :                                                         numtmp[1] = '\0';
    3801           0 :                                                         nlen-=2;
    3802             :                                                 }
    3803          11 :                                                 *target++=(char)strtol(numtmp, NULL, 16);
    3804          11 :                                                 break;
    3805             :                                         }
    3806             :                                         /* break is left intentionally */
    3807             :                                 default:
    3808          20 :                                         i=0;
    3809          73 :                                         while (source < end && *source >= '0' && *source <= '7' && i<3) {
    3810          33 :                                                 numtmp[i++] = *source++;
    3811             :                                         }
    3812          20 :                                         if (i) {
    3813          11 :                                                 numtmp[i]='\0';
    3814          11 :                                                 *target++=(char)strtol(numtmp, NULL, 8);
    3815          11 :                                                 nlen-=i;
    3816          11 :                                                 source--;
    3817             :                                         } else {
    3818           9 :                                                 *target++=*source;
    3819           9 :                                                 nlen--;
    3820             :                                         }
    3821             :                         }
    3822             :                 } else {
    3823          83 :                         *target++=*source;
    3824             :                 }
    3825             :         }
    3826             : 
    3827          33 :         if (nlen != 0) {
    3828          24 :                 *target='\0';
    3829             :         }
    3830             : 
    3831          33 :         ZSTR_LEN(str) = nlen;
    3832          33 : }
    3833             : /* }}} */
    3834             : 
    3835             : /* {{{ php_addcslashes
    3836             :  */
    3837        1879 : PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *what, size_t wlength)
    3838             : {
    3839             :         char flags[256];
    3840             :         char *source, *target;
    3841             :         char *end;
    3842             :         char c;
    3843             :         size_t  newlen;
    3844        3758 :         zend_string *new_str = zend_string_safe_alloc(4, ZSTR_LEN(str), 0, 0);
    3845             : 
    3846        1879 :         php_charmask((unsigned char *)what, wlength, flags);
    3847             : 
    3848       21334 :         for (source = (char*)ZSTR_VAL(str), end = source + ZSTR_LEN(str), target = ZSTR_VAL(new_str); source < end; source++) {
    3849       19455 :                 c = *source;
    3850       19455 :                 if (flags[(unsigned char)c]) {
    3851         165 :                         if ((unsigned char) c < 32 || (unsigned char) c > 126) {
    3852          16 :                                 *target++ = '\\';
    3853          16 :                                 switch (c) {
    3854           2 :                                         case '\n': *target++ = 'n'; break;
    3855           2 :                                         case '\t': *target++ = 't'; break;
    3856           2 :                                         case '\r': *target++ = 'r'; break;
    3857           0 :                                         case '\a': *target++ = 'a'; break;
    3858           2 :                                         case '\v': *target++ = 'v'; break;
    3859           0 :                                         case '\b': *target++ = 'b'; break;
    3860           2 :                                         case '\f': *target++ = 'f'; break;
    3861           6 :                                         default: target += sprintf(target, "%03o", (unsigned char) c);
    3862             :                                 }
    3863          16 :                                 continue;
    3864             :                         }
    3865         149 :                         *target++ = '\\';
    3866             :                 }
    3867       19439 :                 *target++ = c;
    3868             :         }
    3869        1879 :         *target = 0;
    3870        1879 :         newlen = target - ZSTR_VAL(new_str);
    3871        1879 :         if (newlen < ZSTR_LEN(str) * 4) {
    3872        1830 :                 new_str = zend_string_truncate(new_str, newlen, 0);
    3873             :         }
    3874        1879 :         if (should_free) {
    3875             :                 zend_string_release(str);
    3876             :         }
    3877        1879 :         return new_str;
    3878             : }
    3879             : /* }}} */
    3880             : 
    3881             : /* {{{ php_addslashes
    3882             :  */
    3883      363684 : PHPAPI zend_string *php_addslashes(zend_string *str, int should_free)
    3884             : {
    3885             :         /* maximum string length, worst case situation */
    3886             :         char *source, *target;
    3887             :         char *end;
    3888             :         size_t offset;
    3889             :         zend_string *new_str;
    3890             : 
    3891      363684 :         if (!str) {
    3892           0 :                 return ZSTR_EMPTY_ALLOC();
    3893             :         }
    3894             : 
    3895      363684 :         source = ZSTR_VAL(str);
    3896      363684 :         end = source + ZSTR_LEN(str);
    3897             : 
    3898     2515663 :         while (source < end) {
    3899     1788410 :                 switch (*source) {
    3900             :                         case '\0':
    3901             :                         case '\'':
    3902             :                         case '\"':
    3903             :                         case '\\':
    3904         115 :                                 goto do_escape;
    3905             :                         default:
    3906     1788295 :                                 source++;
    3907             :                                 break;
    3908             :                 }
    3909             :         }
    3910             : 
    3911      363569 :         if (!should_free) {
    3912      363569 :                 return zend_string_copy(str);
    3913             :         }
    3914             : 
    3915           0 :         return str;
    3916             : 
    3917             : do_escape:
    3918         115 :         offset = source - (char *)ZSTR_VAL(str);
    3919         230 :         new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0);
    3920         115 :         memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
    3921         115 :         target = ZSTR_VAL(new_str) + offset;
    3922             : 
    3923        2027 :         while (source < end) {
    3924        1797 :                 switch (*source) {
    3925             :                         case '\0':
    3926          29 :                                 *target++ = '\\';
    3927          29 :                                 *target++ = '0';
    3928          29 :                                 break;
    3929             :                         case '\'':
    3930             :                         case '\"':
    3931             :                         case '\\':
    3932         225 :                                 *target++ = '\\';
    3933             :                                 /* break is missing *intentionally* */
    3934             :                         default:
    3935        1768 :                                 *target++ = *source;
    3936             :                                 break;
    3937             :                 }
    3938             : 
    3939        1797 :                 source++;
    3940             :         }
    3941             : 
    3942         115 :         *target = 0;
    3943         115 :         if (should_free) {
    3944             :                 zend_string_release(str);
    3945             :         }
    3946             : 
    3947         115 :         if (ZSTR_LEN(new_str) - (target - ZSTR_VAL(new_str)) > 16) {
    3948          48 :                 new_str = zend_string_truncate(new_str, target - ZSTR_VAL(new_str), 0);
    3949             :         } else {
    3950          91 :                 ZSTR_LEN(new_str) = target - ZSTR_VAL(new_str);
    3951             :         }
    3952             : 
    3953         115 :         return new_str;
    3954             : }
    3955             : /* }}} */
    3956             : 
    3957             : #define _HEB_BLOCK_TYPE_ENG 1
    3958             : #define _HEB_BLOCK_TYPE_HEB 2
    3959             : #define isheb(c)      (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)
    3960             : #define _isblank(c)   (((((unsigned char) c) == ' '  || ((unsigned char) c) == '\t')) ? 1 : 0)
    3961             : #define _isnewline(c) (((((unsigned char) c) == '\n' || ((unsigned char) c) == '\r')) ? 1 : 0)
    3962             : 
    3963             : /* {{{ php_str_replace_in_subject
    3964             :  */
    3965      174359 : static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *subject, zval *result, int case_sensitivity)
    3966             : {
    3967             :         zval            *search_entry,
    3968      174359 :                                 *replace_entry = NULL;
    3969             :         zend_string     *tmp_result,
    3970      174359 :                                 *replace_entry_str = NULL;
    3971      174359 :         char            *replace_value = NULL;
    3972      174359 :         size_t           replace_len = 0;
    3973      174359 :         zend_long        replace_count = 0;
    3974             :         zend_string     *subject_str;
    3975      174359 :         zend_string *lc_subject_str = NULL;
    3976             :         uint32_t     replace_idx;
    3977             : 
    3978             :         /* Make sure we're dealing with strings. */
    3979      174359 :         subject_str = zval_get_string(subject);
    3980      174359 :         if (ZSTR_LEN(subject_str) == 0) {
    3981             :                 zend_string_release(subject_str);
    3982          99 :                 ZVAL_EMPTY_STRING(result);
    3983          99 :                 return 0;
    3984             :         }
    3985             : 
    3986             :         /* If search is an array */
    3987      174260 :         if (Z_TYPE_P(search) == IS_ARRAY) {
    3988             :                 /* Duplicate subject string for repeated replacement */
    3989       37283 :                 ZVAL_STR_COPY(result, subject_str);
    3990             : 
    3991       37283 :                 if (Z_TYPE_P(replace) == IS_ARRAY) {
    3992          30 :                         replace_idx = 0;
    3993             :                 } else {
    3994             :                         /* Set replacement value to the passed one */
    3995       37253 :                         replace_value = Z_STRVAL_P(replace);
    3996       37253 :                         replace_len = Z_STRLEN_P(replace);
    3997             :                 }
    3998             : 
    3999             :                 /* For each entry in the search array, get the entry */
    4000      150501 :                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(search), search_entry) {
    4001             :                         /* Make sure we're dealing with strings. */
    4002       56610 :                         zend_string *search_str = zval_get_string(search_entry);
    4003       56610 :                         if (ZSTR_LEN(search_str) == 0) {
    4004           0 :                                 if (Z_TYPE_P(replace) == IS_ARRAY) {
    4005           0 :                                         replace_idx++;
    4006             :                                 }
    4007             :                                 zend_string_release(search_str);
    4008           0 :                                 continue;
    4009             :                         }
    4010             : 
    4011             :                         /* If replace is an array. */
    4012       56610 :                         if (Z_TYPE_P(replace) == IS_ARRAY) {
    4013             :                                 /* Get current entry */
    4014         150 :                                 while (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
    4015          65 :                                         replace_entry = &Z_ARRVAL_P(replace)->arData[replace_idx].val;
    4016          65 :                                         if (Z_TYPE_P(replace_entry) != IS_UNDEF) {
    4017          65 :                                                 break;
    4018             :                                         }
    4019           0 :                                         replace_idx++;
    4020             :                                 }
    4021          75 :                                 if (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
    4022             :                                         /* Make sure we're dealing with strings. */
    4023          65 :                                         replace_entry_str = zval_get_string(replace_entry);
    4024             : 
    4025             :                                         /* Set replacement value to the one we got from array */
    4026          65 :                                         replace_value = ZSTR_VAL(replace_entry_str);
    4027          65 :                                         replace_len = ZSTR_LEN(replace_entry_str);
    4028             : 
    4029          65 :                                         replace_idx++;
    4030             :                                 } else {
    4031             :                                         /* We've run out of replacement strings, so use an empty one. */
    4032          10 :                                         replace_value = "";
    4033          10 :                                         replace_len = 0;
    4034             :                                 }
    4035             :                         }
    4036             : 
    4037       56610 :                         if (ZSTR_LEN(search_str) == 1) {
    4038        2761 :                                 zend_long old_replace_count = replace_count;
    4039             : 
    4040        2761 :                                 tmp_result = php_char_to_str_ex(Z_STR_P(result),
    4041        2761 :                                                                 ZSTR_VAL(search_str)[0],
    4042             :                                                                 replace_value,
    4043             :                                                                 replace_len,
    4044             :                                                                 case_sensitivity,
    4045             :                                                                 &replace_count);
    4046        2761 :                                 if (lc_subject_str && replace_count != old_replace_count) {
    4047             :                                         zend_string_release(lc_subject_str);
    4048           3 :                                         lc_subject_str = NULL;
    4049             :                                 }
    4050       53849 :                         } else if (ZSTR_LEN(search_str) > 1) {
    4051       53849 :                                 if (case_sensitivity) {
    4052       53833 :                                         tmp_result = php_str_to_str_ex(Z_STR_P(result),
    4053             :                                                         ZSTR_VAL(search_str), ZSTR_LEN(search_str),
    4054             :                                                         replace_value, replace_len, &replace_count);
    4055             :                                 } else {
    4056          16 :                                         zend_long old_replace_count = replace_count;
    4057             : 
    4058          16 :                                         if (!lc_subject_str) {
    4059          16 :                                                 lc_subject_str = php_string_tolower(Z_STR_P(result));
    4060             :                                         }
    4061          16 :                                         tmp_result = php_str_to_str_i_ex(Z_STR_P(result), ZSTR_VAL(lc_subject_str),
    4062             :                                                         search_str, replace_value, replace_len, &replace_count);
    4063          16 :                                         if (replace_count != old_replace_count) {
    4064             :                                                 zend_string_release(lc_subject_str);
    4065           9 :                                                 lc_subject_str = NULL;
    4066             :                                         }
    4067             :                                 }                               
    4068             :                         }
    4069             : 
    4070             :                         zend_string_release(search_str);
    4071             : 
    4072       56610 :                         if (replace_entry_str) {
    4073             :                                 zend_string_release(replace_entry_str);
    4074          65 :                                 replace_entry_str = NULL;
    4075             :                         }
    4076       56610 :                         zend_string_release(Z_STR_P(result));
    4077       56610 :                         ZVAL_STR(result, tmp_result);
    4078             : 
    4079       56610 :                         if (Z_STRLEN_P(result) == 0) {
    4080           2 :                                 if (lc_subject_str) {
    4081             :                                         zend_string_release(lc_subject_str);
    4082             :                                 }
    4083             :                                 zend_string_release(subject_str);
    4084           2 :                                 return replace_count;
    4085             :                         }
    4086             :                 } ZEND_HASH_FOREACH_END();
    4087       37281 :                 if (lc_subject_str) {
    4088             :                         zend_string_release(lc_subject_str);
    4089             :                 }
    4090             :         } else {
    4091             :                 ZEND_ASSERT(Z_TYPE_P(search) == IS_STRING);
    4092      136977 :                 if (Z_STRLEN_P(search) == 1) {
    4093        3747 :                         ZVAL_STR(result,
    4094             :                                 php_char_to_str_ex(subject_str,
    4095             :                                                         Z_STRVAL_P(search)[0],
    4096             :                                                         Z_STRVAL_P(replace),
    4097             :                                                         Z_STRLEN_P(replace),
    4098             :                                                         case_sensitivity,
    4099             :                                                         &replace_count));
    4100      133230 :                 } else if (Z_STRLEN_P(search) > 1) {
    4101      133176 :                         if (case_sensitivity) {
    4102      133086 :                                 ZVAL_STR(result, php_str_to_str_ex(subject_str,
    4103             :                                                 Z_STRVAL_P(search), Z_STRLEN_P(search),
    4104             :                                                 Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
    4105             :                         } else {
    4106          90 :                                 lc_subject_str = php_string_tolower(subject_str);
    4107          90 :                                 ZVAL_STR(result, php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
    4108             :                                                 Z_STR_P(search),
    4109             :                                                 Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
    4110             :                                 zend_string_release(lc_subject_str);
    4111             :                         }
    4112             :                 } else {
    4113          54 :                         ZVAL_STR_COPY(result, subject_str);
    4114             :                 }
    4115             :         }
    4116             :         zend_string_release(subject_str);
    4117      174258 :         return replace_count;
    4118             : }
    4119             : /* }}} */
    4120             : 
    4121             : /* {{{ php_str_replace_common
    4122             :  */
    4123      174104 : static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
    4124             : {
    4125      174104 :         zval *subject, *search, *replace, *subject_entry, *zcount = NULL;
    4126             :         zval result;
    4127             :         zend_string *string_key;
    4128             :         zend_ulong num_key;
    4129      174104 :         zend_long count = 0;
    4130      174104 :         int argc = ZEND_NUM_ARGS();
    4131             : 
    4132             : #ifndef FAST_ZPP
    4133             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z/", &search, &replace, &subject, &zcount) == FAILURE) {
    4134             :                 return;
    4135             :         }
    4136             : #else
    4137      174104 :         ZEND_PARSE_PARAMETERS_START(3, 4)
    4138      174089 :                 Z_PARAM_ZVAL(search)
    4139      174089 :                 Z_PARAM_ZVAL(replace)
    4140      174089 :                 Z_PARAM_ZVAL(subject)
    4141      174089 :                 Z_PARAM_OPTIONAL
    4142      174225 :                 Z_PARAM_ZVAL_EX(zcount, 0, 1)
    4143      174104 :         ZEND_PARSE_PARAMETERS_END();
    4144             : #endif
    4145             : 
    4146             :         /* Make sure we're dealing with strings and do the replacement. */
    4147      348178 :         if (Z_TYPE_P(search) != IS_ARRAY) {
    4148      273680 :                 convert_to_string_ex(search);
    4149      273650 :                 if (Z_TYPE_P(replace) != IS_STRING) {
    4150          24 :                         convert_to_string_ex(replace);
    4151             :                 }
    4152       74528 :         } else if (Z_TYPE_P(replace) != IS_ARRAY) {
    4153       74486 :                 convert_to_string_ex(replace);
    4154             :         }
    4155             : 
    4156             :         /* if subject is an array */
    4157      348178 :         if (Z_TYPE_P(subject) == IS_ARRAY) {
    4158          47 :                 array_init(return_value);
    4159             : 
    4160             :                 /* For each subject entry, convert it to string, then perform replacement
    4161             :                    and add the result to the return_value array. */
    4162         739 :                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(subject), num_key, string_key, subject_entry) {
    4163         346 :                         ZVAL_DEREF(subject_entry);
    4164         980 :                         if (Z_TYPE_P(subject_entry) != IS_ARRAY && Z_TYPE_P(subject_entry) != IS_OBJECT) {
    4165         317 :                                 count += php_str_replace_in_subject(search, replace, subject_entry, &result, case_sensitivity);
    4166             :                         } else {
    4167          29 :                                 ZVAL_COPY(&result, subject_entry);
    4168             :                         }
    4169             :                         /* Add to return array */
    4170         346 :                         if (string_key) {
    4171           4 :                                 zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, &result);
    4172             :                         } else {
    4173         342 :                                 zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
    4174             :                         }
    4175             :                 } ZEND_HASH_FOREACH_END();
    4176             :         } else {        /* if subject is not an array */
    4177      174042 :                 count = php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity);
    4178             :         }
    4179      174089 :         if (argc > 3) {
    4180         135 :                 zval_ptr_dtor(zcount);
    4181         135 :                 ZVAL_LONG(zcount, count);
    4182             :         }
    4183             : }
    4184             : /* }}} */
    4185             : 
    4186             : /* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject [, int &replace_count])
    4187             :    Replaces all occurrences of search in haystack with replace */
    4188      173999 : PHP_FUNCTION(str_replace)
    4189             : {
    4190      173999 :         php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    4191      173999 : }
    4192             : /* }}} */
    4193             : 
    4194             : /* {{{ proto mixed str_ireplace(mixed search, mixed replace, mixed subject [, int &replace_count])
    4195             :    Replaces all occurrences of search in haystack with replace / case-insensitive */
    4196         105 : PHP_FUNCTION(str_ireplace)
    4197             : {
    4198         105 :         php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    4199         105 : }
    4200             : /* }}} */
    4201             : 
    4202             : /* {{{ php_hebrev
    4203             :  *
    4204             :  * Converts Logical Hebrew text (Hebrew Windows style) to Visual text
    4205             :  * Cheers/complaints/flames - Zeev Suraski <zeev@php.net>
    4206             :  */
    4207         116 : static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
    4208             : {
    4209             :         char *str;
    4210             :         char *heb_str, *tmp, *target;
    4211             :         size_t block_start, block_end, block_type, block_length, i;
    4212         116 :         zend_long max_chars=0, char_count;
    4213             :         size_t begin, end, orig_begin;
    4214             :         size_t str_len;
    4215             :         zend_string *broken_str;
    4216             : 
    4217         116 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &max_chars) == FAILURE) {
    4218          26 :                 return;
    4219             :         }
    4220             : 
    4221          90 :         if (str_len == 0) {
    4222          12 :                 RETURN_FALSE;
    4223             :         }
    4224             : 
    4225          78 :         tmp = str;
    4226          78 :         block_start=block_end=0;
    4227             : 
    4228          78 :         heb_str = (char *) emalloc(str_len+1);
    4229          78 :         target = heb_str+str_len;
    4230          78 :         *target = 0;
    4231          78 :         target--;
    4232             : 
    4233          78 :         block_length=0;
    4234             : 
    4235          78 :         if (isheb(*tmp)) {
    4236           0 :                 block_type = _HEB_BLOCK_TYPE_HEB;
    4237             :         } else {
    4238          78 :                 block_type = _HEB_BLOCK_TYPE_ENG;
    4239             :         }
    4240             : 
    4241             :         do {
    4242         307 :                 if (block_type == _HEB_BLOCK_TYPE_HEB) {
    4243         696 :                         while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
    4244         414 :                                 tmp++;
    4245         414 :                                 block_end++;
    4246         414 :                                 block_length++;
    4247             :                         }
    4248         555 :                         for (i = block_start+1; i<= block_end+1; i++) {
    4249         414 :                                 *target = str[i-1];
    4250         414 :                                 switch (*target) {
    4251             :                                         case '(':
    4252          23 :                                                 *target = ')';
    4253          23 :                                                 break;
    4254             :                                         case ')':
    4255          23 :                                                 *target = '(';
    4256          23 :                                                 break;
    4257             :                                         case '[':
    4258           1 :                                                 *target = ']';
    4259           1 :                                                 break;
    4260             :                                         case ']':
    4261           1 :                                                 *target = '[';
    4262           1 :                                                 break;
    4263             :                                         case '{':
    4264           1 :                                                 *target = '}';
    4265           1 :                                                 break;
    4266             :                                         case '}':
    4267           1 :                                                 *target = '{';
    4268           1 :                                                 break;
    4269             :                                         case '<':
    4270           1 :                                                 *target = '>';
    4271           1 :                                                 break;
    4272             :                                         case '>':
    4273          23 :                                                 *target = '<';
    4274          23 :                                                 break;
    4275             :                                         case '\\':
    4276           1 :                                                 *target = '/';
    4277           1 :                                                 break;
    4278             :                                         case '/':
    4279           0 :                                                 *target = '\\';
    4280             :                                                 break;
    4281             :                                         default:
    4282             :                                                 break;
    4283             :                                 }
    4284         414 :                                 target--;
    4285             :                         }
    4286         141 :                         block_type = _HEB_BLOCK_TYPE_ENG;
    4287             :                 } else {
    4288        7419 :                         while (!isheb(*(tmp+1)) && (int)*(tmp+1)!='\n' && block_end < str_len-1) {
    4289        7087 :                                 tmp++;
    4290        7087 :                                 block_end++;
    4291        7087 :                                 block_length++;
    4292             :                         }
    4293         504 :                         while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
    4294         172 :                                 tmp--;
    4295         172 :                                 block_end--;
    4296             :                         }
    4297        7159 :                         for (i = block_end+1; i >= block_start+1; i--) {
    4298        6993 :                                 *target = str[i-1];
    4299        6993 :                                 target--;
    4300             :                         }
    4301         166 :                         block_type = _HEB_BLOCK_TYPE_HEB;
    4302             :                 }
    4303         307 :                 block_start=block_end+1;
    4304         307 :         } while (block_end < str_len-1);
    4305             : 
    4306             : 
    4307         156 :         broken_str = zend_string_alloc(str_len, 0);
    4308          78 :         begin = end = str_len-1;
    4309          78 :         target = ZSTR_VAL(broken_str);
    4310             : 
    4311             :         while (1) {
    4312        1412 :                 char_count=0;
    4313        8883 :                 while ((!max_chars || (max_chars > 0 && char_count < max_chars)) && begin > 0) {
    4314        6205 :                         char_count++;
    4315        6205 :                         begin--;
    4316        6205 :                         if (begin <= 0 || _isnewline(heb_str[begin])) {
    4317         292 :                                 while (begin > 0 && _isnewline(heb_str[begin-1])) {
    4318           0 :                                         begin--;
    4319           0 :                                         char_count++;
    4320             :                                 }
    4321         146 :                                 break;
    4322             :                         }
    4323             :                 }
    4324        1412 :                 if (max_chars >= 0 && char_count == max_chars) { /* try to avoid breaking words */
    4325         627 :                         size_t new_char_count=char_count, new_begin=begin;
    4326             : 
    4327        2037 :                         while (new_char_count > 0) {
    4328         939 :                                 if (_isblank(heb_str[new_begin]) || _isnewline(heb_str[new_begin])) {
    4329             :                                         break;
    4330             :                                 }
    4331         783 :                                 new_begin++;
    4332         783 :                                 new_char_count--;
    4333             :                         }
    4334         627 :                         if (new_char_count > 0) {
    4335         156 :                                 begin=new_begin;
    4336             :                         }
    4337             :                 }
    4338        1412 :                 orig_begin=begin;
    4339             : 
    4340        1412 :                 if (_isblank(heb_str[begin])) {
    4341         239 :                         heb_str[begin]='\n';
    4342             :                 }
    4343        3203 :                 while (begin <= end && _isnewline(heb_str[begin])) { /* skip leading newlines */
    4344         379 :                         begin++;
    4345             :                 }
    4346        8440 :                 for (i = begin; i <= end; i++) { /* copy content */
    4347        7028 :                         *target = heb_str[i];
    4348        7028 :                         target++;
    4349             :                 }
    4350        1791 :                 for (i = orig_begin; i <= end && _isnewline(heb_str[i]); i++) {
    4351         379 :                         *target = heb_str[i];
    4352         379 :                         target++;
    4353             :                 }
    4354        1412 :                 begin=orig_begin;
    4355             : 
    4356        1412 :                 if (begin <= 0) {
    4357          78 :                         *target = 0;
    4358          78 :                         break;
    4359             :                 }
    4360        1334 :                 begin--;
    4361        1334 :                 end=begin;
    4362        1334 :         }
    4363          78 :         efree(heb_str);
    4364             : 
    4365          78 :         if (convert_newlines) {
    4366          34 :                 RETVAL_STR(php_char_to_str_ex(broken_str, '\n', "<br />\n", 7, 1, NULL));
    4367             :                 zend_string_release(broken_str);
    4368             :         } else {
    4369          44 :                 RETURN_NEW_STR(broken_str);
    4370             :         }
    4371             : }
    4372             : /* }}} */
    4373             : 
    4374             : /* {{{ proto string hebrev(string str [, int max_chars_per_line])
    4375             :    Converts logical Hebrew text to visual text */
    4376          63 : PHP_FUNCTION(hebrev)
    4377             : {
    4378          63 :         php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    4379          63 : }
    4380             : /* }}} */
    4381             : 
    4382             : /* {{{ proto string hebrevc(string str [, int max_chars_per_line])
    4383             :    Converts logical Hebrew text to visual text with newline conversion */
    4384          53 : PHP_FUNCTION(hebrevc)
    4385             : {
    4386          53 :         php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    4387          53 : }
    4388             : /* }}} */
    4389             : 
    4390             : /* {{{ proto string nl2br(string str [, bool is_xhtml])
    4391             :    Converts newlines to HTML line breaks */
    4392          60 : PHP_FUNCTION(nl2br)
    4393             : {
    4394             :         /* in brief this inserts <br /> or <br> before matched regexp \n\r?|\r\n? */
    4395             :         char    *tmp;
    4396             :         zend_string *str;
    4397             :         char    *end, *target;
    4398          60 :         size_t  repl_cnt = 0;
    4399          60 :         zend_bool       is_xhtml = 1;
    4400             :         zend_string *result;
    4401             : 
    4402             : #ifndef FAST_ZPP
    4403             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &str, &is_xhtml) == FAILURE) {
    4404             :                 return;
    4405             :         }
    4406             : #else
    4407          60 :         ZEND_PARSE_PARAMETERS_START(1, 2)
    4408         174 :                 Z_PARAM_STR(str)
    4409          52 :                 Z_PARAM_OPTIONAL
    4410          52 :                 Z_PARAM_BOOL(is_xhtml)
    4411          60 :         ZEND_PARSE_PARAMETERS_END();
    4412             : #endif
    4413             : 
    4414          52 :         tmp = ZSTR_VAL(str);
    4415          52 :         end = ZSTR_VAL(str) + ZSTR_LEN(str);
    4416             : 
    4417             :         /* it is really faster to scan twice and allocate mem once instead of scanning once
    4418             :            and constantly reallocing */
    4419         513 :         while (tmp < end) {
    4420         409 :                 if (*tmp == '\r') {
    4421          33 :                         if (*(tmp+1) == '\n') {
    4422          14 :                                 tmp++;
    4423             :                         }
    4424          33 :                         repl_cnt++;
    4425         376 :                 } else if (*tmp == '\n') {
    4426          46 :                         if (*(tmp+1) == '\r') {
    4427          13 :                                 tmp++;
    4428             :                         }
    4429          46 :                         repl_cnt++;
    4430             :                 }
    4431             : 
    4432         409 :                 tmp++;
    4433             :         }
    4434             : 
    4435          52 :         if (repl_cnt == 0) {
    4436          29 :                 RETURN_STR_COPY(str);
    4437             :         }
    4438             : 
    4439             :         {
    4440          23 :                 size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
    4441             : 
    4442          46 :                 result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0);
    4443          23 :                 target = ZSTR_VAL(result);
    4444             :         }
    4445             : 
    4446          23 :         tmp = ZSTR_VAL(str);
    4447         303 :         while (tmp < end) {
    4448         257 :                 switch (*tmp) {
    4449             :                         case '\r':
    4450             :                         case '\n':
    4451          79 :                                 *target++ = '<';
    4452          79 :                                 *target++ = 'b';
    4453          79 :                                 *target++ = 'r';
    4454             : 
    4455          79 :                                 if (is_xhtml) {
    4456          79 :                                         *target++ = ' ';
    4457          79 :                                         *target++ = '/';
    4458             :                                 }
    4459             : 
    4460          79 :                                 *target++ = '>';
    4461             : 
    4462          79 :                                 if ((*tmp == '\r' && *(tmp+1) == '\n') || (*tmp == '\n' && *(tmp+1) == '\r')) {
    4463          27 :                                         *target++ = *tmp++;
    4464             :                                 }
    4465             :                                 /* lack of a break; is intentional */
    4466             :                         default:
    4467         257 :                                 *target++ = *tmp;
    4468             :                 }
    4469             : 
    4470         257 :                 tmp++;
    4471             :         }
    4472             : 
    4473          23 :         *target = '\0';
    4474             : 
    4475          23 :         RETURN_NEW_STR(result);
    4476             : }
    4477             : /* }}} */
    4478             : 
    4479             : /* {{{ proto string strip_tags(string str [, string allowable_tags])
    4480             :    Strips HTML and PHP tags from a string */
    4481         207 : PHP_FUNCTION(strip_tags)
    4482             : {
    4483             :         zend_string *buf;
    4484             :         zend_string *str;
    4485         207 :         zval *allow=NULL;
    4486         207 :         char *allowed_tags=NULL;
    4487         207 :         size_t allowed_tags_len=0;
    4488             : 
    4489         207 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &str, &allow) == FAILURE) {
    4490          14 :                 return;
    4491             :         }
    4492             : 
    4493             :         /* To maintain a certain BC, we allow anything for the second parameter and return original string */
    4494         193 :         if (allow) {
    4495         226 :                 convert_to_string(allow);
    4496         113 :                 allowed_tags = Z_STRVAL_P(allow);
    4497         113 :                 allowed_tags_len = Z_STRLEN_P(allow);
    4498             :         }
    4499             : 
    4500         386 :         buf = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
    4501         193 :         ZSTR_LEN(buf) = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0);
    4502         193 :         RETURN_NEW_STR(buf);
    4503             : }
    4504             : /* }}} */
    4505             : 
    4506             : /* {{{ proto string setlocale(mixed category, string locale [, string ...])
    4507             :    Set locale information */
    4508        1016 : PHP_FUNCTION(setlocale)
    4509             : {
    4510        1016 :         zval *args = NULL;
    4511             :         zval *plocale;
    4512             :         zend_string *loc;
    4513             :         char *retval;
    4514             :         zend_long cat;
    4515        1016 :         int num_args, i = 0;
    4516             :         uint32_t idx;
    4517             : 
    4518        1016 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l+", &cat, &args, &num_args) == FAILURE) {
    4519           2 :                 return;
    4520             :         }
    4521             : 
    4522             : #ifdef HAVE_SETLOCALE
    4523        1014 :         idx = 0;
    4524             :         while (1) {
    4525        2066 :                 if (Z_TYPE(args[0]) == IS_ARRAY) {
    4526          10 :                         while (idx < Z_ARRVAL(args[0])->nNumUsed) {
    4527           4 :                                 plocale = &Z_ARRVAL(args[0])->arData[idx].val;
    4528           4 :                                 if (Z_TYPE_P(plocale) != IS_UNDEF) {
    4529           4 :                                         break;
    4530             :                                 }
    4531           0 :                                 idx++;
    4532             :                         }
    4533           5 :                         if (idx >= Z_ARRVAL(args[0])->nNumUsed) {
    4534           1 :                                 break;
    4535             :                         }
    4536             :                 } else {
    4537        1028 :                         plocale = &args[i];
    4538             :                 }
    4539             : 
    4540        1032 :                 loc = zval_get_string(plocale);
    4541             : 
    4542        1032 :                 if (!strcmp("0", ZSTR_VAL(loc))) {
    4543             :                         zend_string_release(loc);
    4544           8 :                         loc = NULL;
    4545             :                 } else {
    4546        1024 :                         if (ZSTR_LEN(loc) >= 255) {
    4547           1 :                                 php_error_docref(NULL, E_WARNING, "Specified locale name is too long");
    4548             :                                 zend_string_release(loc);
    4549           1 :                                 break;
    4550             :                         }
    4551             :                 }
    4552             : 
    4553        1031 :                 retval = php_my_setlocale(cat, loc ? ZSTR_VAL(loc) : NULL);
    4554             :                 zend_update_current_locale();
    4555        1031 :                 if (retval) {
    4556        1011 :                         if (loc) {
    4557             :                                 /* Remember if locale was changed */
    4558        1003 :                                 size_t len = strlen(retval);
    4559             : 
    4560        1003 :                                 BG(locale_changed) = 1;
    4561        1003 :                                 if (cat == LC_CTYPE || cat == LC_ALL) {
    4562         986 :                                         if (BG(locale_string)) {
    4563         815 :                                                 zend_string_release(BG(locale_string));
    4564             :                                         }
    4565         986 :                                         if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
    4566         980 :                                                 BG(locale_string) = zend_string_copy(loc);
    4567         980 :                                                 RETURN_STR(BG(locale_string));
    4568             :                                         } else {
    4569           6 :                                                 BG(locale_string) = zend_string_init(retval, len, 0);
    4570             :                                                 zend_string_release(loc);
    4571           6 :                                                 RETURN_STR_COPY(BG(locale_string));
    4572             :                                         }
    4573          17 :                                 } else if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
    4574          15 :                                         RETURN_STR(loc);
    4575             :                                 }
    4576             :                                 zend_string_release(loc);
    4577             :                         }
    4578          20 :                         RETURN_STRING(retval);
    4579             :                 }
    4580          20 :                 if (loc) {
    4581             :                         zend_string_release(loc);
    4582             :                 }
    4583             : 
    4584          40 :                 if (Z_TYPE(args[0]) == IS_ARRAY) {
    4585           3 :                         idx++;
    4586             :                 } else {
    4587          17 :                         if (++i >= num_args) break;
    4588             :                 }
    4589          19 :         }
    4590             : 
    4591             : #endif
    4592           3 :         RETURN_FALSE;
    4593             : }
    4594             : /* }}} */
    4595             : 
    4596             : /* {{{ proto void parse_str(string encoded_string [, array result])
    4597             :    Parses GET/POST/COOKIE data and sets global variables */
    4598          33 : PHP_FUNCTION(parse_str)
    4599             : {
    4600             :         char *arg;
    4601          33 :         zval *arrayArg = NULL;
    4602          33 :         char *res = NULL;
    4603             :         size_t arglen;
    4604             : 
    4605          33 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z/", &arg, &arglen, &arrayArg) == FAILURE) {
    4606           2 :                 return;
    4607             :         }
    4608             : 
    4609          31 :         res = estrndup(arg, arglen);
    4610             : 
    4611          31 :         if (arrayArg == NULL) {
    4612             :                 zval tmp;
    4613             :                 zend_array *symbol_table;
    4614          17 :                 if (zend_forbid_dynamic_call("parse_str() with a single argument") == FAILURE) {
    4615           1 :                         efree(res);
    4616           1 :                         return;
    4617             :                 }
    4618             : 
    4619          16 :                 symbol_table = zend_rebuild_symbol_table();
    4620          16 :                 ZVAL_ARR(&tmp, symbol_table);
    4621          16 :                 sapi_module.treat_data(PARSE_STRING, res, &tmp);
    4622          16 :                 if (UNEXPECTED(zend_hash_del(symbol_table, CG(known_strings)[ZEND_STR_THIS]) == SUCCESS)) {
    4623           0 :                         zend_throw_error(NULL, "Cannot re-assign $this");
    4624             :                 }
    4625             :         } else  {
    4626             :                 zval ret;
    4627             : 
    4628             :                 /* Clear out the array that was passed in. */
    4629          14 :                 zval_dtor(arrayArg);
    4630          14 :                 array_init(&ret);
    4631          14 :                 sapi_module.treat_data(PARSE_STRING, res, &ret);
    4632          14 :                 ZVAL_COPY_VALUE(arrayArg, &ret);
    4633             :         }
    4634             : }
    4635             : /* }}} */
    4636             : 
    4637             : #define PHP_TAG_BUF_SIZE 1023
    4638             : 
    4639             : /* {{{ php_tag_find
    4640             :  *
    4641             :  * Check if tag is in a set of tags
    4642             :  *
    4643             :  * states:
    4644             :  *
    4645             :  * 0 start tag
    4646             :  * 1 first non-whitespace char seen
    4647             :  */
    4648         567 : int php_tag_find(char *tag, size_t len, const char *set) {
    4649             :         char c, *n, *t;
    4650         567 :         int state=0, done=0;
    4651             :         char *norm;
    4652             : 
    4653         567 :         if (len <= 0) {
    4654           0 :                 return 0;
    4655             :         }
    4656             : 
    4657         567 :         norm = emalloc(len+1);
    4658             : 
    4659         567 :         n = norm;
    4660         567 :         t = tag;
    4661         567 :         c = tolower(*t);
    4662             :         /*
    4663             :            normalize the tag removing leading and trailing whitespace
    4664             :            and turn any <a whatever...> into just <a> and any </tag>
    4665             :            into <tag>
    4666             :         */
    4667        3954 :         while (!done) {
    4668        2820 :                 switch (c) {
    4669             :                         case '<':
    4670         566 :                                 *(n++) = c;
    4671         566 :                                 break;
    4672             :                         case '>':
    4673         536 :                                 done =1;
    4674         536 :                                 break;
    4675             :                         default:
    4676        1718 :                                 if (!isspace((int)c)) {
    4677        1685 :                                         if (state == 0) {
    4678         566 :                                                 state=1;
    4679             :                                         }
    4680        1685 :                                         if (c != '/') {
    4681        1418 :                                                 *(n++) = c;
    4682             :                                         }
    4683             :                                 } else {
    4684          33 :                                         if (state == 1)
    4685          31 :                                                 done=1;
    4686             :                                 }
    4687             :                                 break;
    4688             :                 }
    4689        2820 :                 c = tolower(*(++t));
    4690             :         }
    4691         567 :         *(n++) = '>';
    4692         567 :         *n = '\0';
    4693         567 :         if (strstr(set, norm)) {
    4694         152 :                 done=1;
    4695             :         } else {
    4696         415 :                 done=0;
    4697             :         }
    4698         567 :         efree(norm);
    4699         567 :         return done;
    4700             : }
    4701             : /* }}} */
    4702             : 
    4703         237 : PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len) /* {{{ */
    4704             : {
    4705         237 :         return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0);
    4706             : }
    4707             : /* }}} */
    4708             : 
    4709             : /* {{{ php_strip_tags
    4710             : 
    4711             :         A simple little state-machine to strip out html and php tags
    4712             : 
    4713             :         State 0 is the output state, State 1 means we are inside a
    4714             :         normal html tag and state 2 means we are inside a php tag.
    4715             : 
    4716             :         The state variable is passed in to allow a function like fgetss
    4717             :         to maintain state across calls to the function.
    4718             : 
    4719             :         lc holds the last significant character read and br is a bracket
    4720             :         counter.
    4721             : 
    4722             :         When an allow string is passed in we keep track of the string
    4723             :         in state 1 and when the tag is closed check it against the
    4724             :         allow string to see if we should allow it.
    4725             : 
    4726             :         swm: Added ability to strip <?xml tags without assuming it PHP
    4727             :         code.
    4728             : */
    4729         742 : PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces)
    4730             : {
    4731             :         char *tbuf, *buf, *p, *tp, *rp, c, lc;
    4732         742 :         int br, depth=0, in_q = 0;
    4733         742 :         int state = 0;
    4734         742 :         size_t pos, i = 0;
    4735         742 :         char *allow_free = NULL;
    4736             :         const char *allow_actual;
    4737         742 :         char is_xml = 0;
    4738             : 
    4739         742 :         if (stateptr)
    4740         237 :                 state = *stateptr;
    4741             : 
    4742         742 :         buf = estrndup(rbuf, len);
    4743         742 :         c = *buf;
    4744         742 :         lc = '\0';
    4745         742 :         p = buf;
    4746         742 :         rp = rbuf;
    4747         742 :         br = 0;
    4748         742 :         if (allow) {
    4749         286 :                 allow_free = zend_str_tolower_dup_ex(allow, allow_len);
    4750         286 :                 allow_actual = allow_free ? allow_free : allow;
    4751         286 :                 tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
    4752         286 :                 tp = tbuf;
    4753             :         } else {
    4754         456 :                 tbuf = tp = NULL;
    4755             :         }
    4756             : 
    4757      137432 :         while (i < len) {
    4758      135948 :                 switch (c) {
    4759             :                         case '\0':
    4760           2 :                                 break;
    4761             :                         case '<':
    4762        1026 :                                 if (in_q) {
    4763           3 :                                         break;
    4764             :                                 }
    4765        1023 :                                 if (isspace(*(p + 1)) && !allow_tag_spaces) {
    4766           6 :                                         goto reg_char;
    4767             :                                 }
    4768        1017 :                                 if (state == 0) {
    4769         992 :                                         lc = '<';
    4770         992 :                                         state = 1;
    4771         992 :                                         if (allow) {
    4772         675 :                                                 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4773           0 :                                                         pos = tp - tbuf;
    4774           0 :                                                         tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4775           0 :                                                         tp = tbuf + pos;
    4776             :                                                 }
    4777         675 :                                                 *(tp++) = '<';
    4778             :                                         }
    4779          25 :                                 } else if (state == 1) {
    4780          20 :                                         depth++;
    4781             :                                 }
    4782        1017 :                                 break;
    4783             : 
    4784             :                         case '(':
    4785         133 :                                 if (state == 2) {
    4786           3 :                                         if (lc != '"' && lc != '\'') {
    4787           3 :                                                 lc = '(';
    4788           3 :                                                 br++;
    4789             :                                         }
    4790         131 :                                 } else if (allow && state == 1) {
    4791           1 :                                         if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4792           0 :                                                 pos = tp - tbuf;
    4793           0 :                                                 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4794           0 :                                                 tp = tbuf + pos;
    4795             :                                         }
    4796           1 :                                         *(tp++) = c;
    4797         129 :                                 } else if (state == 0) {
    4798         128 :                                         *(rp++) = c;
    4799             :                                 }
    4800         133 :                                 break;
    4801             : 
    4802             :                         case ')':
    4803         133 :                                 if (state == 2) {
    4804           3 :                                         if (lc != '"' && lc != '\'') {
    4805           3 :                                                 lc = ')';
    4806           3 :                                                 br--;
    4807             :                                         }
    4808         131 :                                 } else if (allow && state == 1) {
    4809           1 :                                         if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4810           0 :                                                 pos = tp - tbuf;
    4811           0 :                                                 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4812           0 :                                                 tp = tbuf + pos;
    4813             :                                         }
    4814           1 :                                         *(tp++) = c;
    4815         129 :                                 } else if (state == 0) {
    4816         128 :                                         *(rp++) = c;
    4817             :                                 }
    4818         133 :                                 break;
    4819             : 
    4820             :                         case '>':
    4821        4559 :                                 if (depth) {
    4822          20 :                                         depth--;
    4823          20 :                                         break;
    4824             :                                 }
    4825             : 
    4826        4539 :                                 if (in_q) {
    4827           4 :                                         break;
    4828             :                                 }
    4829             : 
    4830        4535 :                                 switch (state) {
    4831             :                                         case 1: /* HTML/XML */
    4832         850 :                                                 lc = '>';
    4833         850 :                                                 if (is_xml && *(p -1) == '-') {
    4834           0 :                                                         break;
    4835             :                                                 }
    4836         850 :                                                 in_q = state = is_xml = 0;
    4837         850 :                                                 if (allow) {
    4838         567 :                                                         if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4839           1 :                                                                 pos = tp - tbuf;
    4840           1 :                                                                 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4841           1 :                                                                 tp = tbuf + pos;
    4842             :                                                         }
    4843         567 :                                                         *(tp++) = '>';
    4844         567 :                                                         *tp='\0';
    4845         567 :                                                         if (php_tag_find(tbuf, tp-tbuf, allow_actual)) {
    4846         152 :                                                                 memcpy(rp, tbuf, tp-tbuf);
    4847         152 :                                                                 rp += tp-tbuf;
    4848             :                                                         }
    4849         567 :                                                         tp = tbuf;
    4850             :                                                 }
    4851         850 :                                                 break;
    4852             : 
    4853             :                                         case 2: /* PHP */
    4854         103 :                                                 if (!br && lc != '\"' && *(p-1) == '?') {
    4855          94 :                                                         in_q = state = 0;
    4856          94 :                                                         tp = tbuf;
    4857             :                                                 }
    4858         103 :                                                 break;
    4859             : 
    4860             :                                         case 3:
    4861           1 :                                                 in_q = state = 0;
    4862           1 :                                                 tp = tbuf;
    4863           1 :                                                 break;
    4864             : 
    4865             :                                         case 4: /* JavaScript/CSS/etc... */
    4866          37 :                                                 if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
    4867          36 :                                                         in_q = state = 0;
    4868          36 :                                                         tp = tbuf;
    4869             :                                                 }
    4870          37 :                                                 break;
    4871             : 
    4872             :                                         default:
    4873        3544 :                                                 *(rp++) = c;
    4874             :                                                 break;
    4875             :                                 }
    4876        4535 :                                 break;
    4877             : 
    4878             :                         case '"':
    4879             :                         case '\'':
    4880        1280 :                                 if (state == 4) {
    4881             :                                         /* Inside <!-- comment --> */
    4882           1 :                                         break;
    4883        1343 :                                 } else if (state == 2 && *(p-1) != '\\') {
    4884          64 :                                         if (lc == c) {
    4885          32 :                                                 lc = '\0';
    4886          32 :                                         } else if (lc != '\\') {
    4887          32 :                                                 lc = c;
    4888             :                                         }
    4889        1215 :                                 } else if (state == 0) {
    4890        1036 :                                         *(rp++) = c;
    4891         179 :                                 } else if (allow && state == 1) {
    4892          43 :                                         if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4893           1 :                                                 pos = tp - tbuf;
    4894           1 :                                                 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4895           1 :                                                 tp = tbuf + pos;
    4896             :                                         }
    4897          43 :                                         *(tp++) = c;
    4898             :                                 }
    4899        1279 :                                 if (state && p != buf && (state == 1 || *(p-1) != '\\') && (!in_q || *p == in_q)) {
    4900         238 :                                         if (in_q) {
    4901         118 :                                                 in_q = 0;
    4902             :                                         } else {
    4903         120 :                                                 in_q = *p;
    4904             :                                         }
    4905             :                                 }
    4906        1279 :                                 break;
    4907             : 
    4908             :                         case '!':
    4909             :                                 /* JavaScript & Other HTML scripting languages */
    4910         109 :                                 if (state == 1 && *(p-1) == '<') {
    4911          40 :                                         state = 3;
    4912          40 :                                         lc = c;
    4913             :                                 } else {
    4914          29 :                                         if (state == 0) {
    4915          20 :                                                 *(rp++) = c;
    4916           9 :                                         } else if (allow && state == 1) {
    4917           6 :                                                 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4918           0 :                                                         pos = tp - tbuf;
    4919           0 :                                                         tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4920           0 :                                                         tp = tbuf + pos;
    4921             :                                                 }
    4922           6 :                                                 *(tp++) = c;
    4923             :                                         }
    4924             :                                 }
    4925          69 :                                 break;
    4926             : 
    4927             :                         case '-':
    4928        1251 :                                 if (state == 3 && p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
    4929          36 :                                         state = 4;
    4930             :                                 } else {
    4931             :                                         goto reg_char;
    4932             :                                 }
    4933          36 :                                 break;
    4934             : 
    4935             :                         case '?':
    4936             : 
    4937         210 :                                 if (state == 1 && *(p-1) == '<') {
    4938          97 :                                         br=0;
    4939          97 :                                         state=2;
    4940          97 :                                         break;
    4941             :                                 }
    4942             : 
    4943             :                         case 'E':
    4944             :                         case 'e':
    4945             :                                 /* !DOCTYPE exception */
    4946       10228 :                                 if (state==3 && p > buf+6
    4947           6 :                                                      && tolower(*(p-1)) == 'p'
    4948           6 :                                                  && tolower(*(p-2)) == 'y'
    4949           6 :                                                      && tolower(*(p-3)) == 't'
    4950           6 :                                                      && tolower(*(p-4)) == 'c'
    4951           6 :                                                      && tolower(*(p-5)) == 'o'
    4952           6 :                                                      && tolower(*(p-6)) == 'd') {
    4953           3 :                                         state = 1;
    4954           3 :                                         break;
    4955             :                                 }
    4956             :                                 /* fall-through */
    4957             : 
    4958             :                         case 'l':
    4959             :                         case 'L':
    4960             : 
    4961             :                                 /* swm: If we encounter '<?xml' then we shouldn't be in
    4962             :                                  * state == 2 (PHP). Switch back to HTML.
    4963             :                                  */
    4964             : 
    4965       15614 :                                 if (state == 2 && p > buf+4 && strncasecmp(p-4, "<?xm", 4) == 0) {
    4966           2 :                                         state = 1; is_xml=1;
    4967           2 :                                         break;
    4968             :                                 }
    4969             : 
    4970             :                                 /* fall-through */
    4971             :                         default:
    4972             : reg_char:
    4973      128614 :                                 if (state == 0) {
    4974      117404 :                                         *(rp++) = c;
    4975       11210 :                                 } else if (allow && state == 1) {
    4976        4175 :                                         if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
    4977        1041 :                                                 pos = tp - tbuf;
    4978        1041 :                                                 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
    4979        1041 :                                                 tp = tbuf + pos;
    4980             :                                         }
    4981        4175 :                                         *(tp++) = c;
    4982             :                                 }
    4983             :                                 break;
    4984             :                 }
    4985      135948 :                 c = *(++p);
    4986      135948 :                 i++;
    4987             :         }
    4988         742 :         if (rp < rbuf + len) {
    4989         274 :                 *rp = '\0';
    4990             :         }
    4991         742 :         efree(buf);
    4992         742 :         if (allow) {
    4993         286 :                 efree(tbuf);
    4994         286 :                 if (allow_free) {
    4995          10 :                         efree(allow_free);
    4996             :                 }
    4997             :         }
    4998         742 :         if (stateptr)
    4999         237 :                 *stateptr = state;
    5000             : 
    5001         742 :         return (size_t)(rp - rbuf);
    5002             : }
    5003             : /* }}} */
    5004             : 
    5005             : /* {{{ proto array str_getcsv(string input[, string delimiter[, string enclosure[, string escape]]])
    5006             : Parse a CSV string into an array */
    5007          16 : PHP_FUNCTION(str_getcsv)
    5008             : {
    5009             :         zend_string *str;
    5010          16 :         char delim = ',', enc = '"', esc = '\\';
    5011          16 :         char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
    5012          16 :         size_t delim_len = 0, enc_len = 0, esc_len = 0;
    5013             : 
    5014          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|sss", &str, &delim_str, &delim_len,
    5015             :                 &enc_str, &enc_len, &esc_str, &esc_len) == FAILURE) {
    5016           0 :                 return;
    5017             :         }
    5018             : 
    5019          16 :         delim = delim_len ? delim_str[0] : delim;
    5020          16 :         enc = enc_len ? enc_str[0] : enc;
    5021          16 :         esc = esc_len ? esc_str[0] : esc;
    5022             : 
    5023          16 :         php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str), return_value);
    5024             : }
    5025             : /* }}} */
    5026             : 
    5027             : /* {{{ proto string str_repeat(string input, int mult)
    5028             :    Returns the input string repeat mult times */
    5029      174499 : PHP_FUNCTION(str_repeat)
    5030             : {
    5031             :         zend_string             *input_str;             /* Input string */
    5032             :         zend_long               mult;                   /* Multiplier */
    5033             :         zend_string     *result;                /* Resulting string */
    5034             :         size_t          result_len;             /* Length of the resulting string */
    5035             : 
    5036      174499 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl", &input_str, &mult) == FAILURE) {
    5037          80 :                 return;
    5038             :         }
    5039             : 
    5040      174419 :         if (mult < 0) {
    5041           1 :                 php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
    5042           1 :                 return;
    5043             :         }
    5044             : 
    5045             :         /* Don't waste our time if it's empty */
    5046             :         /* ... or if the multiplier is zero */
    5047      174418 :         if (ZSTR_LEN(input_str) == 0 || mult == 0)
    5048          52 :                 RETURN_EMPTY_STRING();
    5049             : 
    5050             :         /* Initialize the result string */
    5051      348732 :         result = zend_string_safe_alloc(ZSTR_LEN(input_str), mult, 0, 0);
    5052      174366 :         result_len = ZSTR_LEN(input_str) * mult;
    5053             : 
    5054             :         /* Heavy optimization for situations where input string is 1 byte long */
    5055      174366 :         if (ZSTR_LEN(input_str) == 1) {
    5056      160727 :                 memset(ZSTR_VAL(result), *ZSTR_VAL(input_str), mult);
    5057             :         } else {
    5058             :                 char *s, *e, *ee;
    5059       13639 :                 ptrdiff_t l=0;
    5060       13639 :                 memcpy(ZSTR_VAL(result), ZSTR_VAL(input_str), ZSTR_LEN(input_str));
    5061       13639 :                 s = ZSTR_VAL(result);
    5062       13639 :                 e = ZSTR_VAL(result) + ZSTR_LEN(input_str);
    5063       13639 :                 ee = ZSTR_VAL(result) + result_len;
    5064             : 
    5065       40633 :                 while (e<ee) {
    5066       13355 :                         l = (e-s) < (ee-e) ? (e-s) : (ee-e);
    5067       13355 :                         memmove(e, s, l);
    5068       13355 :                         e += l;
    5069             :                 }
    5070             :         }
    5071             : 
    5072      174366 :         ZSTR_VAL(result)[result_len] = '\0';
    5073             : 
    5074      174366 :         RETURN_NEW_STR(result);
    5075             : }
    5076             : /* }}} */
    5077             : 
    5078             : /* {{{ proto mixed count_chars(string input [, int mode])
    5079             :    Returns info about what characters are used in input */
    5080          60 : PHP_FUNCTION(count_chars)
    5081             : {
    5082             :         zend_string *input;
    5083             :         int chars[256];
    5084          60 :         zend_long mymode=0;
    5085             :         unsigned char *buf;
    5086             :         int inx;
    5087             :         char retstr[256];
    5088          60 :         size_t retlen=0;
    5089          60 :         size_t tmp = 0;
    5090             : 
    5091          60 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &input, &mymode) == FAILURE) {
    5092          11 :                 return;
    5093             :         }
    5094             : 
    5095          49 :         if (mymode < 0 || mymode > 4) {
    5096           7 :                 php_error_docref(NULL, E_WARNING, "Unknown mode");
    5097           7 :                 RETURN_FALSE;
    5098             :         }
    5099             : 
    5100          42 :         buf = (unsigned char *) ZSTR_VAL(input);
    5101          42 :         memset((void*) chars, 0, sizeof(chars));
    5102             : 
    5103        1462 :         while (tmp < ZSTR_LEN(input)) {
    5104        1378 :                 chars[*buf]++;
    5105        1378 :                 buf++;
    5106        1378 :                 tmp++;
    5107             :         }
    5108             : 
    5109          42 :         if (mymode < 3) {
    5110          38 :                 array_init(return_value);
    5111             :         }
    5112             : 
    5113       10794 :         for (inx = 0; inx < 256; inx++) {
    5114       10752 :                 switch (mymode) {
    5115             :                         case 0:
    5116        2816 :                                 add_index_long(return_value, inx, chars[inx]);
    5117        2816 :                                 break;
    5118             :                         case 1:
    5119        6400 :                                 if (chars[inx] != 0) {
    5120         180 :                                         add_index_long(return_value, inx, chars[inx]);
    5121             :                                 }
    5122        6400 :                                 break;
    5123             :                         case 2:
    5124         512 :                                 if (chars[inx] == 0) {
    5125         475 :                                         add_index_long(return_value, inx, chars[inx]);
    5126             :                                 }
    5127         512 :                                 break;
    5128             :                         case 3:
    5129         512 :                                 if (chars[inx] != 0) {
    5130          37 :                                         retstr[retlen++] = inx;
    5131             :                                 }
    5132         512 :                                 break;
    5133             :                         case 4:
    5134         512 :                                 if (chars[inx] == 0) {
    5135         475 :                                         retstr[retlen++] = inx;
    5136             :                                 }
    5137             :                                 break;
    5138             :                 }
    5139             :         }
    5140             : 
    5141          42 :         if (mymode >= 3 && mymode <= 4) {
    5142           8 :                 RETURN_STRINGL(retstr, retlen);
    5143             :         }
    5144             : }
    5145             : /* }}} */
    5146             : 
    5147             : /* {{{ php_strnatcmp
    5148             :  */
    5149          54 : static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
    5150             : {
    5151             :         zend_string *s1, *s2;
    5152             : 
    5153          54 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
    5154           4 :                 return;
    5155             :         }
    5156             : 
    5157          50 :         RETURN_LONG(strnatcmp_ex(ZSTR_VAL(s1), ZSTR_LEN(s1),
    5158             :                                                          ZSTR_VAL(s2), ZSTR_LEN(s2),
    5159             :                                                          fold_case));
    5160             : }
    5161             : /* }}} */
    5162             : 
    5163           0 : PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
    5164             : {
    5165           0 :         zend_string *str1 = zval_get_string(op1);
    5166           0 :         zend_string *str2 = zval_get_string(op2);
    5167             : 
    5168           0 :         ZVAL_LONG(result, strnatcmp_ex(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2), case_insensitive));
    5169             : 
    5170             :         zend_string_release(str1);
    5171             :         zend_string_release(str2);
    5172           0 :         return SUCCESS;
    5173             : }
    5174             : /* }}} */
    5175             : 
    5176           0 : PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
    5177             : {
    5178           0 :         return string_natural_compare_function_ex(result, op1, op2, 1);
    5179             : }
    5180             : /* }}} */
    5181             : 
    5182           0 : PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
    5183             : {
    5184           0 :         return string_natural_compare_function_ex(result, op1, op2, 0);
    5185             : }
    5186             : /* }}} */
    5187             : 
    5188             : /* {{{ proto int strnatcmp(string s1, string s2)
    5189             :    Returns the result of string comparison using 'natural' algorithm */
    5190          33 : PHP_FUNCTION(strnatcmp)
    5191             : {
    5192          33 :         php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    5193          33 : }
    5194             : /* }}} */
    5195             : 
    5196             : /* {{{ proto array localeconv(void)
    5197             :    Returns numeric formatting information based on the current locale */
    5198          11 : PHP_FUNCTION(localeconv)
    5199             : {
    5200             :         zval grouping, mon_grouping;
    5201             :         int len, i;
    5202             : 
    5203             :         /* We don't need no stinkin' parameters... */
    5204          11 :         if (zend_parse_parameters_none() == FAILURE) {
    5205           0 :                 return;
    5206             :         }
    5207             : 
    5208          11 :         array_init(return_value);
    5209          11 :         array_init(&grouping);
    5210          11 :         array_init(&mon_grouping);
    5211             : 
    5212             : #ifdef HAVE_LOCALECONV
    5213             :         {
    5214             :                 struct lconv currlocdata;
    5215             : 
    5216          11 :                 localeconv_r( &currlocdata );
    5217             : 
    5218             :                 /* Grab the grouping data out of the array */
    5219          11 :                 len = (int)strlen(currlocdata.grouping);
    5220             : 
    5221          33 :                 for (i = 0; i < len; i++) {
    5222          22 :                         add_index_long(&grouping, i, currlocdata.grouping[i]);
    5223             :                 }
    5224             : 
    5225             :                 /* Grab the monetary grouping data out of the array */
    5226          11 :                 len = (int)strlen(currlocdata.mon_grouping);
    5227             : 
    5228          31 :                 for (i = 0; i < len; i++) {
    5229          20 :                         add_index_long(&mon_grouping, i, currlocdata.mon_grouping[i]);
    5230             :                 }
    5231             : 
    5232          11 :                 add_assoc_string(return_value, "decimal_point",     currlocdata.decimal_point);
    5233          11 :                 add_assoc_string(return_value, "thousands_sep",     currlocdata.thousands_sep);
    5234          11 :                 add_assoc_string(return_value, "int_curr_symbol",   currlocdata.int_curr_symbol);
    5235          11 :                 add_assoc_string(return_value, "currency_symbol",   currlocdata.currency_symbol);
    5236          11 :                 add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point);
    5237          11 :                 add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep);
    5238          11 :                 add_assoc_string(return_value, "positive_sign",     currlocdata.positive_sign);
    5239          11 :                 add_assoc_string(return_value, "negative_sign",     currlocdata.negative_sign);
    5240          11 :                 add_assoc_long(  return_value, "int_frac_digits",   currlocdata.int_frac_digits);
    5241          11 :                 add_assoc_long(  return_value, "frac_digits",       currlocdata.frac_digits);
    5242          11 :                 add_assoc_long(  return_value, "p_cs_precedes",     currlocdata.p_cs_precedes);
    5243          11 :                 add_assoc_long(  return_value, "p_sep_by_space",    currlocdata.p_sep_by_space);
    5244          11 :                 add_assoc_long(  return_value, "n_cs_precedes",     currlocdata.n_cs_precedes);
    5245          11 :                 add_assoc_long(  return_value, "n_sep_by_space",    currlocdata.n_sep_by_space);
    5246          11 :                 add_assoc_long(  return_value, "p_sign_posn",       currlocdata.p_sign_posn);
    5247          11 :                 add_assoc_long(  return_value, "n_sign_posn",       currlocdata.n_sign_posn);
    5248             :         }
    5249             : #else
    5250             :         /* Ok, it doesn't look like we have locale info floating around, so I guess it
    5251             :            wouldn't hurt to just go ahead and return the POSIX locale information?  */
    5252             : 
    5253             :         add_index_long(&grouping, 0, -1);
    5254             :         add_index_long(&mon_grouping, 0, -1);
    5255             : 
    5256             :         add_assoc_string(return_value, "decimal_point",     "\x2E");
    5257             :         add_assoc_string(return_value, "thousands_sep",     "");
    5258             :         add_assoc_string(return_value, "int_curr_symbol",   "");
    5259             :         add_assoc_string(return_value, "currency_symbol",   "");
    5260             :         add_assoc_string(return_value, "mon_decimal_point", "\x2E");
    5261             :         add_assoc_string(return_value, "mon_thousands_sep", "");
    5262             :         add_assoc_string(return_value, "positive_sign",     "");
    5263             :         add_assoc_string(return_value, "negative_sign",     "");
    5264             :         add_assoc_long(  return_value, "int_frac_digits",   CHAR_MAX);
    5265             :         add_assoc_long(  return_value, "frac_digits",       CHAR_MAX);
    5266             :         add_assoc_long(  return_value, "p_cs_precedes",     CHAR_MAX);
    5267             :         add_assoc_long(  return_value, "p_sep_by_space",    CHAR_MAX);
    5268             :         add_assoc_long(  return_value, "n_cs_precedes",     CHAR_MAX);
    5269             :         add_assoc_long(  return_value, "n_sep_by_space",    CHAR_MAX);
    5270             :         add_assoc_long(  return_value, "p_sign_posn",       CHAR_MAX);
    5271             :         add_assoc_long(  return_value, "n_sign_posn",       CHAR_MAX);
    5272             : #endif
    5273             : 
    5274          11 :         zend_hash_str_update(Z_ARRVAL_P(return_value), "grouping", sizeof("grouping")-1, &grouping);
    5275          11 :         zend_hash_str_update(Z_ARRVAL_P(return_value), "mon_grouping", sizeof("mon_grouping")-1, &mon_grouping);
    5276             : }
    5277             : /* }}} */
    5278             : 
    5279             : /* {{{ proto int strnatcasecmp(string s1, string s2)
    5280             :    Returns the result of case-insensitive string comparison using 'natural' algorithm */
    5281          21 : PHP_FUNCTION(strnatcasecmp)
    5282             : {
    5283          21 :         php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    5284          21 : }
    5285             : /* }}} */
    5286             : 
    5287             : /* {{{ proto int substr_count(string haystack, string needle [, int offset [, int length]])
    5288             :    Returns the number of times a substring occurs in the string */
    5289          50 : PHP_FUNCTION(substr_count)
    5290             : {
    5291             :         char *haystack, *needle;
    5292          50 :         zend_long offset = 0, length = 0;
    5293          50 :         int ac = ZEND_NUM_ARGS();
    5294          50 :         int count = 0;
    5295             :         size_t haystack_len, needle_len;
    5296             :         char *p, *endp, cmp;
    5297             : 
    5298          50 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ll", &haystack, &haystack_len, &needle, &needle_len, &offset, &length) == FAILURE) {
    5299           6 :                 return;
    5300             :         }
    5301             : 
    5302          44 :         if (needle_len == 0) {
    5303           2 :                 php_error_docref(NULL, E_WARNING, "Empty substring");
    5304           2 :                 RETURN_FALSE;
    5305             :         }
    5306             : 
    5307          42 :         p = haystack;
    5308          42 :         endp = p + haystack_len;
    5309             : 
    5310          42 :         if (offset < 0) {
    5311           4 :                 offset += (zend_long)haystack_len;
    5312             :         }
    5313          42 :         if ((offset < 0) || ((size_t)offset > haystack_len)) {
    5314           4 :                 php_error_docref(NULL, E_WARNING, "Offset not contained in string");
    5315           4 :                 RETURN_FALSE;
    5316             :         }
    5317          38 :         p += offset;
    5318             : 
    5319          38 :         if (ac == 4) {
    5320             : 
    5321           9 :                 if (length <= 0) {
    5322           2 :                         length += (haystack_len - offset);
    5323             :                 }
    5324           9 :                 if ((length <= 0) || ((size_t)length > (haystack_len - offset))) {
    5325           3 :                         php_error_docref(NULL, E_WARNING, "Invalid length value");
    5326           3 :                         RETURN_FALSE;
    5327             :                 }
    5328           6 :                 endp = p + length;
    5329             :         }
    5330             : 
    5331          35 :         if (needle_len == 1) {
    5332          19 :                 cmp = needle[0];
    5333             : 
    5334          56 :                 while ((p = memchr(p, cmp, endp - p))) {
    5335          18 :                         count++;
    5336          18 :                         p++;
    5337             :                 }
    5338             :         } else {
    5339        1276 :                 while ((p = (char*)php_memnstr(p, needle, needle_len, endp))) {
    5340         614 :                         p += needle_len;
    5341         614 :                         count++;
    5342             :                 }
    5343             :         }
    5344             : 
    5345          35 :         RETURN_LONG(count);
    5346             : }
    5347             : /* }}} */
    5348             : 
    5349             : /* {{{ proto string str_pad(string input, int pad_length [, string pad_string [, int pad_type]])
    5350             :    Returns input string padded on the left or right to specified length with pad_string */
    5351         586 : PHP_FUNCTION(str_pad)
    5352             : {
    5353             :         /* Input arguments */
    5354             :         zend_string *input;                             /* Input string */
    5355             :         zend_long pad_length;                   /* Length to pad to */
    5356             : 
    5357             :         /* Helper variables */
    5358             :         size_t num_pad_chars;           /* Number of padding characters (total - input size) */
    5359         586 :         char *pad_str = " "; /* Pointer to padding string */
    5360         586 :         size_t pad_str_len = 1;
    5361         586 :         zend_long   pad_type_val = STR_PAD_RIGHT; /* The padding type value */
    5362         586 :         size_t     i, left_pad=0, right_pad=0;
    5363         586 :         zend_string *result = NULL;     /* Resulting string */
    5364             : 
    5365         586 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|sl", &input, &pad_length, &pad_str, &pad_str_len, &pad_type_val) == FAILURE) {
    5366          23 :                 return;
    5367             :         }
    5368             : 
    5369             :         /* If resulting string turns out to be shorter than input string,
    5370             :            we simply copy the input and return. */
    5371         563 :         if (pad_length < 0  || (size_t)pad_length <= ZSTR_LEN(input)) {
    5372         278 :                 RETURN_STRINGL(ZSTR_VAL(input), ZSTR_LEN(input));
    5373             :         }
    5374             : 
    5375         424 :         if (pad_str_len == 0) {
    5376           8 :                 php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
    5377           8 :                 return;
    5378             :         }
    5379             : 
    5380         416 :         if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
    5381           7 :                 php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
    5382           7 :                 return;
    5383             :         }
    5384             : 
    5385         409 :         num_pad_chars = pad_length - ZSTR_LEN(input);
    5386         409 :         if (num_pad_chars >= INT_MAX) {
    5387           0 :                 php_error_docref(NULL, E_WARNING, "Padding length is too long");
    5388           0 :                 return;
    5389             :         }
    5390             : 
    5391         818 :         result = zend_string_safe_alloc(1, ZSTR_LEN(input), num_pad_chars, 0);
    5392         409 :         ZSTR_LEN(result) = 0;
    5393             : 
    5394             :         /* We need to figure out the left/right padding lengths. */
    5395         409 :         switch (pad_type_val) {
    5396             :                 case STR_PAD_RIGHT:
    5397         326 :                         left_pad = 0;
    5398         326 :                         right_pad = num_pad_chars;
    5399         326 :                         break;
    5400             : 
    5401             :                 case STR_PAD_LEFT:
    5402          49 :                         left_pad = num_pad_chars;
    5403          49 :                         right_pad = 0;
    5404          49 :                         break;
    5405             : 
    5406             :                 case STR_PAD_BOTH:
    5407          34 :                         left_pad = num_pad_chars / 2;
    5408          34 :                         right_pad = num_pad_chars - left_pad;
    5409             :                         break;
    5410             :         }
    5411             : 
    5412             :         /* First we pad on the left. */
    5413         956 :         for (i = 0; i < left_pad; i++)
    5414         547 :                 ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
    5415             : 
    5416             :         /* Then we copy the input string. */
    5417         409 :         memcpy(ZSTR_VAL(result) + ZSTR_LEN(result), ZSTR_VAL(input), ZSTR_LEN(input));
    5418         409 :         ZSTR_LEN(result) += ZSTR_LEN(input);
    5419             : 
    5420             :         /* Finally, we pad on the right. */
    5421     6303132 :         for (i = 0; i < right_pad; i++)
    5422     6302723 :                 ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
    5423             : 
    5424         409 :         ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
    5425             : 
    5426         409 :         RETURN_NEW_STR(result);
    5427             : }
    5428             : /* }}} */
    5429             : 
    5430             : /* {{{ proto mixed sscanf(string str, string format [, string ...])
    5431             :    Implements an ANSI C compatible sscanf */
    5432          81 : PHP_FUNCTION(sscanf)
    5433             : {
    5434          81 :         zval *args = NULL;
    5435             :         char *str, *format;
    5436             :         size_t str_len, format_len;
    5437          81 :         int result, num_args = 0;
    5438             : 
    5439          81 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss*", &str, &str_len, &format, &format_len,
    5440             :                 &args, &num_args) == FAILURE) {
    5441          10 :                 return;
    5442             :         }
    5443             : 
    5444          71 :         result = php_sscanf_internal(str, format, num_args, args, 0, return_value);
    5445             : 
    5446          71 :         if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
    5447           0 :                 WRONG_PARAM_COUNT;
    5448             :         }
    5449             : }
    5450             : /* }}} */
    5451             : 
    5452             : static char rot13_from[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    5453             : static char rot13_to[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
    5454             : 
    5455             : /* {{{ proto string str_rot13(string str)
    5456             :    Perform the rot13 transform on a string */
    5457          29 : PHP_FUNCTION(str_rot13)
    5458             : {
    5459             :         zend_string *arg;
    5460             : 
    5461          29 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
    5462           5 :                 return;
    5463             :         }
    5464             : 
    5465          24 :         if (ZSTR_LEN(arg) == 0) {
    5466           0 :                 RETURN_EMPTY_STRING();
    5467             :         } else {
    5468          24 :                 RETURN_STR(php_strtr_ex(arg, rot13_from, rot13_to, 52));
    5469             :         }
    5470             : }
    5471             : /* }}} */
    5472             : 
    5473       91009 : static void php_string_shuffle(char *str, zend_long len) /* {{{ */
    5474             : {
    5475             :         zend_long n_elems, rnd_idx, n_left;
    5476             :         char temp;
    5477             :         /* The implementation is stolen from array_data_shuffle       */
    5478             :         /* Thus the characteristics of the randomization are the same */
    5479       91009 :         n_elems = len;
    5480             : 
    5481       91009 :         if (n_elems <= 1) {
    5482           0 :                 return;
    5483             :         }
    5484             : 
    5485       91009 :         n_left = n_elems;
    5486             : 
    5487      455116 :         while (--n_left) {
    5488      273098 :                 rnd_idx = php_rand();
    5489      273098 :                 RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    5490      273098 :                 if (rnd_idx != n_left) {
    5491      174616 :                         temp = str[n_left];
    5492      174616 :                         str[n_left] = str[rnd_idx];
    5493      174616 :                         str[rnd_idx] = temp;
    5494             :                 }
    5495             :         }
    5496             : }
    5497             : /* }}} */
    5498             : 
    5499             : /* {{{ proto void str_shuffle(string str)
    5500             :    Shuffles string. One permutation of all possible is created */
    5501       91025 : PHP_FUNCTION(str_shuffle)
    5502             : {
    5503             :         zend_string *arg;
    5504             : 
    5505       91025 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
    5506           6 :                 return;
    5507             :         }
    5508             : 
    5509      182038 :         RETVAL_STRINGL(ZSTR_VAL(arg), ZSTR_LEN(arg));
    5510       91019 :         if (Z_STRLEN_P(return_value) > 1) {
    5511       91009 :                 php_string_shuffle(Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value));
    5512             :         }
    5513             : }
    5514             : /* }}} */
    5515             : 
    5516             : /* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
    5517             :         Counts the number of words inside a string. If format of 1 is specified,
    5518             :         then the function will return an array containing all the words
    5519             :         found inside the string. If format of 2 is specified, then the function
    5520             :         will return an associated array where the position of the word is the key
    5521             :         and the word itself is the value.
    5522             : 
    5523             :         For the purpose of this function, 'word' is defined as a locale dependent
    5524             :         string containing alphabetic characters, which also may contain, but not start
    5525             :         with "'" and "-" characters.
    5526             : */
    5527          35 : PHP_FUNCTION(str_word_count)
    5528             : {
    5529             :         zend_string *str;
    5530          35 :         char *char_list = NULL, *p, *e, *s, ch[256];
    5531          35 :         size_t char_list_len = 0, word_count = 0;
    5532          35 :         zend_long type = 0;
    5533             : 
    5534          35 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls", &str, &type, &char_list, &char_list_len) == FAILURE) {
    5535           8 :                 return;
    5536             :         }
    5537             : 
    5538          27 :         switch(type) {
    5539             :                 case 1:
    5540             :                 case 2:
    5541          15 :                         array_init(return_value);
    5542          15 :                         if (!ZSTR_LEN(str)) {
    5543           0 :                                 return;
    5544             :                         }
    5545          15 :                         break;
    5546             :                 case 0:
    5547           6 :                         if (!ZSTR_LEN(str)) {
    5548           1 :                                 RETURN_LONG(0);
    5549             :                         }
    5550             :                         /* nothing to be done */
    5551           5 :                         break;
    5552             :                 default:
    5553           6 :                         php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
    5554           6 :                         RETURN_FALSE;
    5555             :         }
    5556             : 
    5557          20 :         if (char_list) {
    5558          15 :                 php_charmask((unsigned char *)char_list, char_list_len, ch);
    5559             :         }
    5560             : 
    5561          20 :         p = ZSTR_VAL(str);
    5562          20 :         e = ZSTR_VAL(str) + ZSTR_LEN(str);
    5563             : 
    5564             :         /* first character cannot be ' or -, unless explicitly allowed by the user */
    5565          20 :         if ((*p == '\'' && (!char_list || !ch['\''])) || (*p == '-' && (!char_list || !ch['-']))) {
    5566           2 :                 p++;
    5567             :         }
    5568             :         /* last character cannot be -, unless explicitly allowed by the user */
    5569          20 :         if (*(e - 1) == '-' && (!char_list || !ch['-'])) {
    5570           1 :                 e--;
    5571             :         }
    5572             : 
    5573         187 :         while (p < e) {
    5574         147 :                 s = p;
    5575         576 :                 while (p < e && (isalpha((unsigned char)*p) || (char_list && ch[(unsigned char)*p]) || *p == '\'' || *p == '-')) {
    5576         282 :                         p++;
    5577             :                 }
    5578         147 :                 if (p > s) {
    5579          93 :                         switch (type)
    5580             :                         {
    5581             :                                 case 1:
    5582          29 :                                         add_next_index_stringl(return_value, s, p - s);
    5583          29 :                                         break;
    5584             :                                 case 2:
    5585          35 :                                         add_index_stringl(return_value, (s - ZSTR_VAL(str)), s, p - s);
    5586          35 :                                         break;
    5587             :                                 default:
    5588          29 :                                         word_count++;
    5589             :                                         break;
    5590             :                         }
    5591             :                 }
    5592         147 :                 p++;
    5593             :         }
    5594             : 
    5595          20 :         if (!type) {
    5596           5 :                 RETURN_LONG(word_count);
    5597             :         }
    5598             : }
    5599             : 
    5600             : /* }}} */
    5601             : 
    5602             : #if HAVE_STRFMON
    5603             : /* {{{ proto string money_format(string format , float value)
    5604             :    Convert monetary value(s) to string */
    5605          71 : PHP_FUNCTION(money_format)
    5606             : {
    5607          71 :         size_t format_len = 0;
    5608             :         char *format, *p, *e;
    5609             :         double value;
    5610          71 :         zend_bool check = 0;
    5611             :         zend_string *str;
    5612             :         ssize_t res_len;
    5613             : 
    5614          71 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "sd", &format, &format_len, &value) == FAILURE) {
    5615          17 :                 return;
    5616             :         }
    5617             : 
    5618          54 :         p = format;
    5619          54 :         e = p + format_len;
    5620         141 :         while ((p = memchr(p, '%', (e - p)))) {
    5621          34 :                 if (*(p + 1) == '%') {
    5622           0 :                         p += 2;
    5623          34 :                 } else if (!check) {
    5624          33 :                         check = 1;
    5625          33 :                         p++;
    5626             :                 } else {
    5627           1 :                         php_error_docref(NULL, E_WARNING, "Only a single %%i or %%n token can be used");
    5628           1 :                         RETURN_FALSE;
    5629             :                 }
    5630             :         }
    5631             : 
    5632         106 :         str = zend_string_safe_alloc(format_len, 1, 1024, 0);
    5633          53 :         if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) {
    5634             :                 zend_string_free(str);
    5635           0 :                 RETURN_FALSE;
    5636             :         }
    5637          53 :         ZSTR_LEN(str) = (size_t)res_len;
    5638          53 :         ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
    5639             : 
    5640         106 :         RETURN_NEW_STR(zend_string_truncate(str, ZSTR_LEN(str), 0));
    5641             : }
    5642             : /* }}} */
    5643             : #endif
    5644             : 
    5645             : /* {{{ proto array str_split(string str [, int split_length])
    5646             :    Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
    5647         202 : PHP_FUNCTION(str_split)
    5648             : {
    5649             :         zend_string *str;
    5650         202 :         zend_long split_length = 1;
    5651             :         char *p;
    5652             :         size_t n_reg_segments;
    5653             : 
    5654         202 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &str, &split_length) == FAILURE) {
    5655          19 :                 return;
    5656             :         }
    5657             : 
    5658         183 :         if (split_length <= 0) {
    5659          15 :                 php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
    5660          15 :                 RETURN_FALSE;
    5661             :         }
    5662             : 
    5663             : 
    5664         168 :         if (0 == ZSTR_LEN(str) || (size_t)split_length >= ZSTR_LEN(str)) {
    5665          29 :                 array_init_size(return_value, 1);
    5666          29 :                 add_next_index_stringl(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
    5667          29 :                 return;
    5668             :         }
    5669             : 
    5670         139 :         array_init_size(return_value, (uint32_t)(((ZSTR_LEN(str) - 1) / split_length) + 1));
    5671             : 
    5672         139 :         n_reg_segments = ZSTR_LEN(str) / split_length;
    5673         139 :         p = ZSTR_VAL(str);
    5674             : 
    5675       25239 :         while (n_reg_segments-- > 0) {
    5676       24961 :                 add_next_index_stringl(return_value, p, split_length);
    5677       24961 :                 p += split_length;
    5678             :         }
    5679             : 
    5680         139 :         if (p != (ZSTR_VAL(str) + ZSTR_LEN(str))) {
    5681          31 :                 add_next_index_stringl(return_value, p, (ZSTR_VAL(str) + ZSTR_LEN(str) - p));
    5682             :         }
    5683             : }
    5684             : /* }}} */
    5685             : 
    5686             : /* {{{ proto array strpbrk(string haystack, string char_list)
    5687             :    Search a string for any of a set of characters */
    5688          20 : PHP_FUNCTION(strpbrk)
    5689             : {
    5690             :         zend_string *haystack, *char_list;
    5691             :         char *haystack_ptr, *cl_ptr;
    5692             : 
    5693          20 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &haystack, &char_list) == FAILURE) {
    5694           4 :                 RETURN_FALSE;
    5695             :         }
    5696             : 
    5697          16 :         if (!ZSTR_LEN(char_list)) {
    5698           1 :                 php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
    5699           1 :                 RETURN_FALSE;
    5700             :         }
    5701             : 
    5702          96 :         for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
    5703         228 :                 for (cl_ptr = ZSTR_VAL(char_list); cl_ptr < (ZSTR_VAL(char_list) + ZSTR_LEN(char_list)); ++cl_ptr) {
    5704         147 :                         if (*cl_ptr == *haystack_ptr) {
    5705          20 :                                 RETURN_STRINGL(haystack_ptr, (ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - haystack_ptr));
    5706             :                         }
    5707             :                 }
    5708             :         }
    5709             : 
    5710           5 :         RETURN_FALSE;
    5711             : }
    5712             : /* }}} */
    5713             : 
    5714             : /* {{{ proto int substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]])
    5715             :    Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters */
    5716          50 : PHP_FUNCTION(substr_compare)
    5717             : {
    5718             :         zend_string *s1, *s2;
    5719          50 :         zend_long offset, len=0;
    5720          50 :         zend_bool cs=0;
    5721             :         size_t cmp_len;
    5722             : 
    5723          50 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl|lb", &s1, &s2, &offset, &len, &cs) == FAILURE) {
    5724           2 :                 RETURN_FALSE;
    5725             :         }
    5726             : 
    5727          48 :         if (ZEND_NUM_ARGS() >= 4 && len <= 0) {
    5728           4 :                 if (len == 0) {
    5729           2 :                         RETURN_LONG(0L);
    5730             :                 } else {
    5731           2 :                         php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
    5732           2 :                         RETURN_FALSE;
    5733             :                 }
    5734             :         }
    5735             : 
    5736          44 :         if (offset < 0) {
    5737           2 :                 offset = ZSTR_LEN(s1) + offset;
    5738           2 :                 offset = (offset < 0) ? 0 : offset;
    5739             :         }
    5740             : 
    5741          44 :         if ((size_t)offset >= ZSTR_LEN(s1)) {
    5742           2 :                 php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
    5743           2 :                 RETURN_FALSE;
    5744             :         }
    5745             : 
    5746          42 :         cmp_len = len ? (size_t)len : MAX(ZSTR_LEN(s2), (ZSTR_LEN(s1) - offset));
    5747             : 
    5748          42 :         if (!cs) {
    5749          41 :                 RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
    5750             :         } else {
    5751           1 :                 RETURN_LONG(zend_binary_strncasecmp_l(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
    5752             :         }
    5753             : }
    5754             : /* }}} */
    5755             : 
    5756             : /*
    5757             :  * Local variables:
    5758             :  * tab-width: 4
    5759             :  * c-basic-offset: 4
    5760             :  * End:
    5761             :  * vim600: noet sw=4 ts=4 fdm=marker
    5762             :  * vim<600: noet sw=4 ts=4
    5763             :  */

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:29 +0000 (5 days ago)

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