1999-04-17 00:37:12 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2009-03-10 23:40:06 +00:00
| PHP Version 6 |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2008-12-31 11:12:40 +00:00
| Copyright ( c ) 1997 - 2009 The PHP Group |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 13:10:10 +00:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 13:13:16 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 13:10:10 +00:00
| http : //www.php.net/license/3_01.txt |
1999-07-16 13:13:16 +00:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2000-05-23 20:16:14 +00:00
| Authors : Rasmus Lerdorf < rasmus @ php . net > |
2003-03-18 12:06:09 +00:00
| Stig S <EFBFBD> ther Bakken < ssb @ php . net > |
1999-07-16 13:13:16 +00:00
| Zeev Suraski < zeev @ zend . com > |
1999-04-17 00:37:12 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
1999-04-23 20:06:01 +00:00
1999-12-18 04:01:20 +00:00
/* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
1999-04-17 00:37:12 +00:00
# include <stdio.h>
# include "php.h"
2002-09-26 19:18:35 +00:00
# include "php_rand.h"
1999-12-04 19:19:57 +00:00
# include "php_string.h"
2000-01-28 17:24:53 +00:00
# include "php_variables.h"
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
# ifdef HAVE_LOCALE_H
# include <locale.h>
1999-04-17 00:37:12 +00:00
# endif
2001-07-04 10:10:30 +00:00
# ifdef HAVE_LANGINFO_H
# include <langinfo.h>
# endif
2002-08-21 13:14:57 +00:00
# ifdef HAVE_MONETARY_H
# include <monetary.h>
# endif
2003-05-27 00:42:39 +00:00
# ifdef HAVE_LIBINTL
# include <libintl.h> /* For LC_MESSAGES */
# endif
2003-02-07 21:36:18 +00:00
2000-06-06 18:58:15 +00:00
# include "scanf.h"
# include "zend_API.h"
1999-06-15 21:51:00 +00:00
# include "zend_execute.h"
# include "php_globals.h"
1999-12-28 18:47:59 +00:00
# include "basic_functions.h"
2000-10-12 01:26:26 +00:00
# include "php_smart_str.h"
2001-01-14 16:36:30 +00:00
# ifdef ZTS
# include "TSRM.h"
# endif
1999-04-17 00:37:12 +00:00
2005-08-11 23:36:07 +00:00
# include "unicode/uchar.h"
2006-03-22 10:20:20 +00:00
# include "unicode/ubrk.h"
2005-08-11 23:36:07 +00:00
2006-12-05 04:52:44 +00:00
/* For str_getcsv() support */
# include "ext/standard/file.h"
2000-09-11 13:52:22 +00:00
# define STR_PAD_LEFT 0
# define STR_PAD_RIGHT 1
# define STR_PAD_BOTH 2
2002-01-22 03:35:23 +00:00
# define PHP_PATHINFO_DIRNAME 1
# define PHP_PATHINFO_BASENAME 2
# define PHP_PATHINFO_EXTENSION 4
2006-07-16 10:34:32 +00:00
# define PHP_PATHINFO_FILENAME 8
# define PHP_PATHINFO_ALL (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION | PHP_PATHINFO_FILENAME)
2000-07-08 20:38:23 +00:00
2002-09-25 19:06:29 +00:00
# define STR_STRSPN 0
# define STR_STRCSPN 1
2001-06-06 13:06:12 +00:00
/* {{{ register_string_constants
*/
2000-07-08 20:38:23 +00:00
void register_string_constants ( INIT_FUNC_ARGS )
{
2000-09-10 05:59:16 +00:00
REGISTER_LONG_CONSTANT ( " STR_PAD_LEFT " , STR_PAD_LEFT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STR_PAD_RIGHT " , STR_PAD_RIGHT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STR_PAD_BOTH " , STR_PAD_BOTH , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " PATHINFO_DIRNAME " , PHP_PATHINFO_DIRNAME , CONST_CS | CONST_PERSISTENT ) ;
2000-09-11 13:52:22 +00:00
REGISTER_LONG_CONSTANT ( " PATHINFO_BASENAME " , PHP_PATHINFO_BASENAME , CONST_CS | CONST_PERSISTENT ) ;
2000-09-10 05:59:16 +00:00
REGISTER_LONG_CONSTANT ( " PATHINFO_EXTENSION " , PHP_PATHINFO_EXTENSION , CONST_CS | CONST_PERSISTENT ) ;
2006-07-16 15:56:00 +00:00
REGISTER_LONG_CONSTANT ( " PATHINFO_FILENAME " , PHP_PATHINFO_FILENAME , CONST_CS | CONST_PERSISTENT ) ;
2000-12-10 15:55:34 +00:00
2001-01-14 16:36:30 +00:00
# ifdef HAVE_LOCALECONV
2006-07-16 15:56:00 +00:00
/* If last members of struct lconv equal CHAR_MAX, no grouping is done */
2001-01-14 16:36:30 +00:00
/* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */
# ifndef HAVE_LIMITS_H
# define CHAR_MAX 127
# endif
REGISTER_LONG_CONSTANT ( " CHAR_MAX " , CHAR_MAX , CONST_CS | CONST_PERSISTENT ) ;
# endif
2000-12-10 15:55:34 +00:00
# ifdef HAVE_LOCALE_H
REGISTER_LONG_CONSTANT ( " LC_CTYPE " , LC_CTYPE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " LC_NUMERIC " , LC_NUMERIC , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " LC_TIME " , LC_TIME , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " LC_COLLATE " , LC_COLLATE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " LC_MONETARY " , LC_MONETARY , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " LC_ALL " , LC_ALL , CONST_CS | CONST_PERSISTENT ) ;
2000-12-14 15:58:14 +00:00
# ifdef LC_MESSAGES
2000-12-11 16:27:48 +00:00
REGISTER_LONG_CONSTANT ( " LC_MESSAGES " , LC_MESSAGES , CONST_CS | CONST_PERSISTENT ) ;
# endif
2000-12-10 15:55:34 +00:00
# endif
2006-07-16 15:56:00 +00:00
2000-07-08 20:38:23 +00:00
}
2001-06-06 13:06:12 +00:00
/* }}} */
2000-07-08 20:38:23 +00:00
1999-12-05 14:16:37 +00:00
int php_tag_find ( char * tag , int len , char * set ) ;
2006-10-04 17:38:09 +00:00
static void php_ucwords ( char * str , int str_len ) ;
2006-03-26 02:15:47 +00:00
static UChar * php_u_strtr_array ( UChar * str , int slen , HashTable * hash , int minlen , int maxlen , int * outlen TSRMLS_DC ) ;
1999-12-05 14:16:37 +00:00
1999-11-28 00:31:02 +00:00
/* this is read-only, so it's ok */
1999-05-16 11:12:23 +00:00
static char hexconvtab [ ] = " 0123456789abcdef " ;
2001-01-14 16:36:30 +00:00
/* localeconv mutex */
# ifdef ZTS
static MUTEX_T locale_mutex = NULL ;
# endif
2001-06-06 13:06:12 +00:00
/* {{{ php_bin2hex
*/
1999-05-16 11:32:51 +00:00
static char * php_bin2hex ( const unsigned char * old , const size_t oldlen , size_t * newlen )
1999-05-16 11:12:23 +00:00
{
2001-09-04 06:18:11 +00:00
register unsigned char * result = NULL ;
1999-08-12 10:53:29 +00:00
size_t i , j ;
1999-05-16 11:12:23 +00:00
2006-03-02 13:12:45 +00:00
result = ( unsigned char * ) safe_emalloc ( oldlen * 2 , sizeof ( char ) , 1 ) ;
2006-07-16 15:56:00 +00:00
2002-10-02 17:56:04 +00:00
for ( i = j = 0 ; i < oldlen ; i + + ) {
2000-03-26 17:06:19 +00:00
result [ j + + ] = hexconvtab [ old [ i ] > > 4 ] ;
result [ j + + ] = hexconvtab [ old [ i ] & 15 ] ;
1999-05-16 11:12:23 +00:00
}
2001-02-22 10:36:40 +00:00
result [ j ] = ' \0 ' ;
1999-05-16 11:12:23 +00:00
2006-07-16 15:56:00 +00:00
if ( newlen )
2001-09-04 06:18:11 +00:00
* newlen = oldlen * 2 * sizeof ( char ) ;
1999-05-16 11:12:23 +00:00
2006-03-02 13:12:45 +00:00
return ( char * ) result ;
1999-05-16 11:12:23 +00:00
}
2001-06-06 13:06:12 +00:00
/* }}} */
1999-05-16 11:12:23 +00:00
2001-01-14 16:36:30 +00:00
# ifdef HAVE_LOCALECONV
2001-06-05 13:12:10 +00:00
/* {{{ localeconv_r
* glibc ' s localeconv is not reentrant , so lets make it so . . . sorta */
2004-11-03 23:36:51 +00:00
PHPAPI struct lconv * localeconv_r ( struct lconv * out )
2001-01-14 16:36:30 +00:00
{
struct lconv * res ;
# ifdef ZTS
tsrm_mutex_lock ( locale_mutex ) ;
# endif
/* localeconv doesn't return an error condition */
res = localeconv ( ) ;
* out = * res ;
# ifdef ZTS
tsrm_mutex_unlock ( locale_mutex ) ;
# endif
return out ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
2001-01-14 16:36:30 +00:00
# ifdef ZTS
2001-06-05 13:12:10 +00:00
/* {{{ PHP_MINIT_FUNCTION
*/
2001-01-14 16:36:30 +00:00
PHP_MINIT_FUNCTION ( localeconv )
{
locale_mutex = tsrm_mutex_alloc ( ) ;
return SUCCESS ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
2001-01-14 16:36:30 +00:00
2001-06-05 13:12:10 +00:00
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
2001-01-14 16:36:30 +00:00
PHP_MSHUTDOWN_FUNCTION ( localeconv )
{
tsrm_mutex_free ( locale_mutex ) ;
locale_mutex = NULL ;
return SUCCESS ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
2001-01-14 16:36:30 +00:00
# endif
# endif
2006-03-02 20:37:07 +00:00
/* {{{ proto string bin2hex(string data) U
2000-02-24 10:11:42 +00:00
Converts the binary representation of data to hex */
1999-05-16 11:12:23 +00:00
PHP_FUNCTION ( bin2hex )
{
2005-08-17 17:39:04 +00:00
unsigned char * data ;
int data_len ;
2000-03-26 17:06:19 +00:00
char * result ;
1999-05-16 11:12:23 +00:00
size_t newlen ;
2006-08-02 20:38:39 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S " , & data , & data_len ) = = FAILURE ) {
2005-08-17 17:39:04 +00:00
return ;
1999-05-16 11:12:23 +00:00
}
2005-08-17 17:39:04 +00:00
result = php_bin2hex ( data , data_len , & newlen ) ;
2006-07-16 15:56:00 +00:00
2001-09-04 06:18:11 +00:00
if ( ! result ) {
1999-05-16 11:12:23 +00:00
RETURN_FALSE ;
}
2006-08-02 21:53:43 +00:00
RETVAL_ASCII_STRINGL ( result , newlen , ZSTR_AUTOFREE ) ;
1999-05-16 11:12:23 +00:00
}
2000-02-24 10:11:42 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2007-06-05 13:37:05 +00:00
static void php_spn_common_handler ( INTERNAL_FUNCTION_PARAMETERS , int behavior ) /* { { { */
1999-04-17 00:37:12 +00:00
{
2005-10-19 19:10:13 +00:00
void * s1 , * s2 ;
2005-12-09 13:41:06 +00:00
int len1 , len2 ;
2005-10-19 19:10:13 +00:00
zend_uchar type1 , type2 ;
2008-10-21 22:06:49 +00:00
long start = 0 , len = 0 ; /* For UNICODE, these are codepoint units */
2006-07-16 15:56:00 +00:00
2005-10-19 19:10:13 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT|ll " ,
& s1 , & len1 , & type1 , & s2 , & len2 , & type2 ,
& start , & len ) = = FAILURE ) {
2002-09-25 19:06:29 +00:00
return ;
}
2006-07-16 15:56:00 +00:00
2002-09-25 19:06:29 +00:00
if ( ZEND_NUM_ARGS ( ) < 4 ) {
len = len1 ;
}
2006-07-16 15:56:00 +00:00
2002-09-25 19:06:29 +00:00
/* look at substr() function for more information */
2006-07-16 15:56:00 +00:00
2002-09-25 19:06:29 +00:00
if ( start < 0 ) {
start + = len1 ;
if ( start < 0 ) {
start = 0 ;
}
} else if ( start > len1 ) {
RETURN_FALSE ;
}
2006-07-16 15:56:00 +00:00
2002-09-25 19:06:29 +00:00
if ( len < 0 ) {
len + = ( len1 - start ) ;
if ( len < 0 ) {
len = 0 ;
}
}
2006-07-16 15:56:00 +00:00
2007-06-06 20:06:43 +00:00
if ( len > len1 - start ) {
2002-09-25 19:06:29 +00:00
len = len1 - start ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
2007-06-06 20:06:43 +00:00
if ( len = = 0 ) {
RETURN_LONG ( 0 ) ;
}
2005-10-19 19:10:13 +00:00
if ( type1 = = IS_UNICODE ) {
UChar * u_start , * u_end ;
int32_t i = 0 ;
U16_FWD_N ( ( UChar * ) s1 , i , len1 , start ) ;
u_start = ( UChar * ) s1 + i ;
U16_FWD_N ( ( UChar * ) s1 , i , len1 , len ) ;
u_end = ( UChar * ) s1 + i ;
if ( behavior = = STR_STRSPN ) {
RETURN_LONG ( php_u_strspn ( u_start /*str1_start*/ ,
( UChar * ) s2 /*str2_start*/ ,
u_end /*str1_end*/ ,
( UChar * ) s2 + len2 /*str2_end*/ ) ) ;
} else if ( behavior = = STR_STRCSPN ) {
RETURN_LONG ( php_u_strcspn ( u_start /*str1_start*/ ,
( UChar * ) s2 /*str2_start*/ ,
u_end /*str1_end*/ ,
( UChar * ) s2 + len2 /*str2_end*/ ) ) ;
}
} else {
if ( behavior = = STR_STRSPN ) {
RETURN_LONG ( php_strspn ( ( char * ) s1 + start /*str1_start*/ ,
( char * ) s2 /*str2_start*/ ,
( char * ) s1 + start + len /*str1_end*/ ,
( char * ) s2 + len2 /*str2_end*/ ) ) ;
} else if ( behavior = = STR_STRCSPN ) {
RETURN_LONG ( php_strcspn ( ( char * ) s1 + start /*str1_start*/ ,
( char * ) s2 /*str2_start*/ ,
( char * ) s1 + start + len /*str1_end*/ ,
( char * ) s2 + len2 /*str2_end*/ ) ) ;
}
2002-09-25 19:06:29 +00:00
}
2005-10-19 19:10:13 +00:00
2002-09-25 19:06:29 +00:00
}
2007-06-05 13:37:05 +00:00
/* }}} */
2002-09-25 19:06:29 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto int strspn(string str, string mask [, start [, len]]) U
2002-09-25 19:06:29 +00:00
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 ) */
PHP_FUNCTION ( strspn )
{
php_spn_common_handler ( INTERNAL_FUNCTION_PARAM_PASSTHRU , STR_STRSPN ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto int strcspn(string str, string mask [, start [, len]]) U
2002-09-25 19:06:29 +00:00
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 ) */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strcspn )
1999-04-17 00:37:12 +00:00
{
2002-09-25 19:06:29 +00:00
php_spn_common_handler ( INTERNAL_FUNCTION_PARAM_PASSTHRU , STR_STRCSPN ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2001-07-05 10:49:58 +00:00
/* {{{ PHP_MINIT_FUNCTION(nl_langinfo) */
2001-07-04 10:10:30 +00:00
# if HAVE_NL_LANGINFO
PHP_MINIT_FUNCTION ( nl_langinfo )
{
# define REGISTER_NL_LANGINFO_CONSTANT(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
2001-08-10 18:02:59 +00:00
# ifdef ABDAY_1
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_1 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_2 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_3 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_4 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_5 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_6 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABDAY_7 ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef DAY_1
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( DAY_1 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_2 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_3 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_4 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_5 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_6 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( DAY_7 ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef ABMON_1
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_1 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_2 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_3 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_4 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_5 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_6 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_7 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_8 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_9 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_10 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_11 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( ABMON_12 ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef MON_1
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( MON_1 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_2 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_3 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_4 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_5 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_6 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_7 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_8 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_9 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_10 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_11 ) ;
REGISTER_NL_LANGINFO_CONSTANT ( MON_12 ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef AM_STR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( AM_STR ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef PM_STR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( PM_STR ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef D_T_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( D_T_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef D_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( D_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef T_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( T_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef T_FMT_AMPM
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( T_FMT_AMPM ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef ERA
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ERA ) ;
2001-08-10 18:02:59 +00:00
# endif
2001-07-05 10:49:58 +00:00
# ifdef ERA_YEAR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ERA_YEAR ) ;
2001-07-05 10:49:58 +00:00
# endif
2001-08-10 18:02:59 +00:00
# ifdef ERA_D_T_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ERA_D_T_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef ERA_D_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ERA_D_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef ERA_T_FMT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ERA_T_FMT ) ;
2001-08-10 18:02:59 +00:00
# endif
# ifdef ALT_DIGITS
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( ALT_DIGITS ) ;
2001-08-10 18:02:59 +00:00
# endif
2001-07-05 10:49:58 +00:00
# ifdef INT_CURR_SYMBOL
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( INT_CURR_SYMBOL ) ;
2001-07-05 10:49:58 +00:00
# endif
2001-07-04 10:10:30 +00:00
# ifdef CURRENCY_SYMBOL
REGISTER_NL_LANGINFO_CONSTANT ( CURRENCY_SYMBOL ) ;
# endif
# ifdef CRNCYSTR
REGISTER_NL_LANGINFO_CONSTANT ( CRNCYSTR ) ;
# endif
2001-07-05 10:49:58 +00:00
# ifdef MON_DECIMAL_POINT
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( MON_DECIMAL_POINT ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef MON_THOUSANDS_SEP
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( MON_THOUSANDS_SEP ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef MON_GROUPING
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( MON_GROUPING ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef POSITIVE_SIGN
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( POSITIVE_SIGN ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef NEGATIVE_SIGN
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( NEGATIVE_SIGN ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef INT_FRAC_DIGITS
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( INT_FRAC_DIGITS ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef FRAC_DIGITS
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( FRAC_DIGITS ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef P_CS_PRECEDES
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( P_CS_PRECEDES ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef P_SEP_BY_SPACE
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( P_SEP_BY_SPACE ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef N_CS_PRECEDES
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( N_CS_PRECEDES ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef N_SEP_BY_SPACE
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( N_SEP_BY_SPACE ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef P_SIGN_POSN
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( P_SIGN_POSN ) ;
2001-07-05 10:49:58 +00:00
# endif
# ifdef N_SIGN_POSN
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( N_SIGN_POSN ) ;
2001-07-05 10:49:58 +00:00
# endif
2001-07-04 10:10:30 +00:00
# ifdef DECIMAL_POINT
REGISTER_NL_LANGINFO_CONSTANT ( DECIMAL_POINT ) ;
# endif
# ifdef RADIXCHAR
REGISTER_NL_LANGINFO_CONSTANT ( RADIXCHAR ) ;
# endif
# ifdef THOUSANDS_SEP
REGISTER_NL_LANGINFO_CONSTANT ( THOUSANDS_SEP ) ;
# endif
# ifdef THOUSEP
REGISTER_NL_LANGINFO_CONSTANT ( THOUSEP ) ;
# endif
2001-07-05 10:53:15 +00:00
# ifdef GROUPING
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( GROUPING ) ;
2001-07-05 10:53:15 +00:00
# endif
# ifdef YESEXPR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( YESEXPR ) ;
2001-07-05 10:53:15 +00:00
# endif
# ifdef NOEXPR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( NOEXPR ) ;
2001-07-05 10:53:15 +00:00
# endif
# ifdef YESSTR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( YESSTR ) ;
2001-07-05 10:53:15 +00:00
# endif
# ifdef NOSTR
2001-07-04 10:10:30 +00:00
REGISTER_NL_LANGINFO_CONSTANT ( NOSTR ) ;
2001-07-05 10:53:15 +00:00
# endif
2001-07-04 10:10:30 +00:00
# ifdef CODESET
REGISTER_NL_LANGINFO_CONSTANT ( CODESET ) ;
# endif
# undef REGISTER_NL_LANGINFO_CONSTANT
return SUCCESS ;
}
2001-07-05 10:49:58 +00:00
/* }}} */
2006-09-22 18:24:12 +00:00
/* {{{ proto string nl_langinfo(int item) U
2001-12-06 19:02:27 +00:00
Query language and locale information */
2001-07-04 10:10:30 +00:00
PHP_FUNCTION ( nl_langinfo )
{
2006-09-22 18:24:12 +00:00
long item ;
2001-09-04 06:18:11 +00:00
char * value ;
2006-07-16 15:56:00 +00:00
2006-09-22 18:24:12 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & item ) = = FAILURE ) {
return ;
2001-07-04 10:10:30 +00:00
}
2001-09-04 06:18:11 +00:00
2009-03-26 20:02:53 +00:00
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " deprecated in Unicode mode, please use ICU locale functions " ) ;
2006-09-22 18:24:12 +00:00
2007-12-13 22:29:15 +00:00
switch ( item ) { /* {{{ */
# ifdef ABDAY_1
case ABDAY_1 :
case ABDAY_2 :
case ABDAY_3 :
case ABDAY_4 :
case ABDAY_5 :
case ABDAY_6 :
case ABDAY_7 :
# endif
# ifdef DAY_1
case DAY_1 :
case DAY_2 :
case DAY_3 :
case DAY_4 :
case DAY_5 :
case DAY_6 :
case DAY_7 :
# endif
# ifdef ABMON_1
case ABMON_1 :
case ABMON_2 :
case ABMON_3 :
case ABMON_4 :
case ABMON_5 :
case ABMON_6 :
case ABMON_7 :
case ABMON_8 :
case ABMON_9 :
case ABMON_10 :
case ABMON_11 :
case ABMON_12 :
# endif
# ifdef MON_1
case MON_1 :
case MON_2 :
case MON_3 :
case MON_4 :
case MON_5 :
case MON_6 :
case MON_7 :
case MON_8 :
case MON_9 :
case MON_10 :
case MON_11 :
case MON_12 :
# endif
# ifdef AM_STR
case AM_STR :
# endif
# ifdef PM_STR
case PM_STR :
# endif
# ifdef D_T_FMT
case D_T_FMT :
# endif
# ifdef D_FMT
case D_FMT :
# endif
# ifdef T_FMT
case T_FMT :
# endif
# ifdef T_FMT_AMPM
case T_FMT_AMPM :
# endif
# ifdef ERA
case ERA :
# endif
# ifdef ERA_YEAR
case ERA_YEAR :
# endif
# ifdef ERA_D_T_FMT
case ERA_D_T_FMT :
# endif
# ifdef ERA_D_FMT
case ERA_D_FMT :
# endif
# ifdef ERA_T_FMT
case ERA_T_FMT :
# endif
# ifdef ALT_DIGITS
case ALT_DIGITS :
# endif
# ifdef INT_CURR_SYMBOL
case INT_CURR_SYMBOL :
# endif
# ifdef CURRENCY_SYMBOL
case CURRENCY_SYMBOL :
# endif
# ifdef CRNCYSTR
case CRNCYSTR :
# endif
# ifdef MON_DECIMAL_POINT
case MON_DECIMAL_POINT :
# endif
# ifdef MON_THOUSANDS_SEP
case MON_THOUSANDS_SEP :
# endif
# ifdef MON_GROUPING
case MON_GROUPING :
# endif
# ifdef POSITIVE_SIGN
case POSITIVE_SIGN :
# endif
# ifdef NEGATIVE_SIGN
case NEGATIVE_SIGN :
# endif
# ifdef INT_FRAC_DIGITS
case INT_FRAC_DIGITS :
# endif
# ifdef FRAC_DIGITS
case FRAC_DIGITS :
# endif
# ifdef P_CS_PRECEDES
case P_CS_PRECEDES :
# endif
# ifdef P_SEP_BY_SPACE
case P_SEP_BY_SPACE :
# endif
# ifdef N_CS_PRECEDES
case N_CS_PRECEDES :
# endif
# ifdef N_SEP_BY_SPACE
case N_SEP_BY_SPACE :
# endif
# ifdef P_SIGN_POSN
case P_SIGN_POSN :
# endif
# ifdef N_SIGN_POSN
case N_SIGN_POSN :
# endif
# ifdef DECIMAL_POINT
case DECIMAL_POINT :
2008-05-09 12:58:50 +00:00
# elif defined(RADIXCHAR)
2007-12-13 22:29:15 +00:00
case RADIXCHAR :
# endif
# ifdef THOUSANDS_SEP
case THOUSANDS_SEP :
2008-05-09 12:58:50 +00:00
# elif defined(THOUSEP)
2007-12-13 22:29:15 +00:00
case THOUSEP :
# endif
# ifdef GROUPING
case GROUPING :
# endif
# ifdef YESEXPR
case YESEXPR :
# endif
# ifdef NOEXPR
case NOEXPR :
# endif
# ifdef YESSTR
case YESSTR :
# endif
# ifdef NOSTR
case NOSTR :
# endif
# ifdef CODESET
case CODESET :
# endif
break ;
default :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Item '%ld' is not valid " , item ) ;
RETURN_FALSE ;
}
2008-08-14 10:10:56 +00:00
/* }}} */
2007-12-13 22:29:15 +00:00
2006-09-22 18:24:12 +00:00
value = nl_langinfo ( item ) ;
2002-10-02 18:13:56 +00:00
if ( value = = NULL ) {
2001-07-04 10:10:30 +00:00
RETURN_FALSE ;
2002-10-02 18:13:56 +00:00
} else {
2001-07-04 10:10:30 +00:00
RETURN_STRING ( value , 1 ) ;
}
}
# endif
2002-05-16 14:41:15 +00:00
/* }}} */
2001-07-04 10:10:30 +00:00
2006-08-14 22:00:46 +00:00
/* {{{ proto int strcoll(string str1, string str2) U
2001-09-04 10:44:28 +00:00
Compares two strings using the current locale */
2001-01-17 01:10:50 +00:00
PHP_FUNCTION ( strcoll )
{
2006-08-14 22:00:46 +00:00
zstr s1 , s2 ;
int s1_len , s2_len ;
zend_uchar str_type ;
2001-01-17 01:10:50 +00:00
2006-08-14 22:00:46 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT " , & s1 , & s1_len ,
& str_type , & s2 , & s2_len , & str_type ) = = FAILURE ) {
return ;
}
if ( str_type = = IS_UNICODE ) {
RETURN_LONG ( ZEND_COLL_RESULT ( ucol_strcoll ( UG ( default_collator ) - > coll , s1 . u , s1_len , s2 . u , s2_len ) ) ) ;
} else {
# ifdef HAVE_STRCOLL
RETURN_LONG ( strcoll ( ( const char * ) s1 . s ,
( const char * ) s2 . s ) ) ;
# else
RETURN_FALSE ;
# endif
2001-01-17 01:10:50 +00:00
}
}
2001-06-05 13:12:10 +00:00
/* }}} */
2001-01-17 01:10:50 +00:00
2001-08-03 23:09:05 +00:00
/* {{{ php_charmask
* Fills a 256 - byte bytemask with input . You can specify a range like ' a . . z ' ,
2006-07-16 15:56:00 +00:00
* it needs to be incrementing .
2006-01-05 20:49:28 +00:00
* Returns : FAILURE / SUCCESS whether the input was correct ( i . e . no range errors )
2001-08-03 23:09:05 +00:00
*/
2002-07-13 04:13:43 +00:00
static inline int php_charmask ( unsigned char * input , int len , char * mask TSRMLS_DC )
2001-08-03 23:09:05 +00:00
{
unsigned char * end ;
unsigned char c ;
2001-08-05 19:38:49 +00:00
int result = SUCCESS ;
2001-08-03 23:09:05 +00:00
memset ( mask , 0 , 256 ) ;
2002-10-02 17:56:04 +00:00
for ( end = input + len ; input < end ; input + + ) {
2006-07-16 15:56:00 +00:00
c = * input ;
if ( ( input + 3 < end ) & & input [ 1 ] = = ' . ' & & input [ 2 ] = = ' . '
2001-08-05 19:38:49 +00:00
& & input [ 3 ] > = c ) {
memset ( mask + c , 1 , input [ 3 ] - c + 1 ) ;
2001-08-03 23:09:05 +00:00
input + = 3 ;
2002-10-02 17:56:04 +00:00
} else if ( ( input + 1 < end ) & & input [ 0 ] = = ' . ' & & input [ 1 ] = = ' . ' ) {
2001-08-05 19:38:49 +00:00
/* Error, try to be as helpful as possible:
( a range ending / starting with ' . ' won ' t be captured here ) */
2002-10-02 17:56:04 +00:00
if ( end - len > = input ) { /* there was no 'left' char */
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, no character to the left of '..' " ) ;
2001-08-05 19:38:49 +00:00
result = FAILURE ;
continue ;
}
2002-10-02 17:56:04 +00:00
if ( input + 2 > = end ) { /* there is no 'right' char */
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, no character to the right of '..' " ) ;
2001-08-05 19:38:49 +00:00
result = FAILURE ;
continue ;
}
if ( input [ - 1 ] > input [ 2 ] ) { /* wrong order */
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, '..'-range needs to be incrementing " ) ;
2001-08-05 19:38:49 +00:00
result = FAILURE ;
continue ;
2006-07-16 15:56:00 +00:00
}
2001-08-05 19:38:49 +00:00
/* FIXME: better error (a..b..c is the only left possibility?) */
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range " ) ;
2001-08-05 19:38:49 +00:00
result = FAILURE ;
continue ;
} else {
2001-08-03 23:09:05 +00:00
mask [ c ] = 1 ;
2001-08-05 19:38:49 +00:00
}
2001-08-03 23:09:05 +00:00
}
2001-08-05 19:38:49 +00:00
return result ;
2001-08-03 23:09:05 +00:00
}
/* }}} */
2002-07-13 04:13:43 +00:00
/* {{{ php_trim()
* mode 1 : trim left
* mode 2 : trim right
* mode 3 : trim left and right
* what indicates which chars are to be trimmed . NULL - > default ( ' \ t \ n \ r \ v \ 0 ' )
2001-06-05 13:12:10 +00:00
*/
2006-08-15 20:38:12 +00:00
PHPAPI char * php_trim ( char * c , int len , char * what , int what_len , zval * return_value , int mode TSRMLS_DC )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
{
register int i ;
int trimmed = 0 ;
2001-08-03 23:09:05 +00:00
char mask [ 256 ] ;
if ( what ) {
2006-03-02 13:12:45 +00:00
php_charmask ( ( unsigned char * ) what , what_len , mask TSRMLS_CC ) ;
2001-08-03 23:09:05 +00:00
} else {
2006-03-02 13:12:45 +00:00
php_charmask ( ( unsigned char * ) " \n \r \t \v \0 " , 6 , mask TSRMLS_CC ) ;
2001-08-03 23:09:05 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( mode & 1 ) {
for ( i = 0 ; i < len ; i + + ) {
2001-08-03 23:09:05 +00:00
if ( mask [ ( unsigned char ) c [ i ] ] ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
trimmed + + ;
} else {
break ;
}
}
len - = trimmed ;
c + = trimmed ;
}
if ( mode & 2 ) {
for ( i = len - 1 ; i > = 0 ; i - - ) {
2001-08-03 23:09:05 +00:00
if ( mask [ ( unsigned char ) c [ i ] ] ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
len - - ;
} else {
break ;
}
}
}
2002-07-13 04:13:43 +00:00
if ( return_value ) {
2006-01-17 12:18:53 +00:00
RETVAL_STRINGL ( c , len , 1 ) ;
2002-07-13 04:13:43 +00:00
} else {
return estrndup ( c , len ) ;
}
return " " ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
/* }}} */
2006-08-18 18:01:58 +00:00
/* {{{ php_expand_uchar_range()
2005-08-11 23:36:07 +00:00
* Expands possible ranges of the form ' a . . b ' in input charlist ,
* where a < b in code - point order
*/
2006-08-18 18:01:58 +00:00
static int php_expand_uchar_range ( UChar * * range , int * range_len TSRMLS_DC )
2005-08-11 23:36:07 +00:00
{
UChar32 * codepts , * tmp , * input , * end , c ;
int32_t len , tmp_len , idx ;
UErrorCode err ;
int expanded = 0 ;
int result = SUCCESS ;
/* First, convert UTF-16 to UTF-32 */
len = * range_len ;
codepts = ( UChar32 * ) emalloc ( ( len + 1 ) * sizeof ( UChar32 ) ) ;
err = U_ZERO_ERROR ;
u_strToUTF32 ( ( UChar32 * ) codepts , len + 1 , & len , * range , len , & err ) ;
/* Expand ranges, if any - taken from php_charmask() */
tmp_len = len ;
tmp = ( UChar32 * ) emalloc ( ( tmp_len + 1 ) * sizeof ( UChar32 ) ) ;
input = codepts ;
for ( idx = 0 , end = input + len ; input < end ; input + + ) {
c = input [ 0 ] ;
if ( ( input + 3 < end ) & & input [ 1 ] = = ' . ' & & input [ 2 ] = = ' . ' & & input [ 3 ] > = c ) {
2006-03-15 12:20:49 +00:00
tmp_len + = ( input [ 3 ] - c + 1 - 4 ) ;
tmp = ( UChar32 * ) erealloc ( tmp , ( tmp_len + 1 ) * sizeof ( UChar32 ) ) ;
2005-08-11 23:36:07 +00:00
for ( ; c < = input [ 3 ] ; c + + ) {
if ( U_IS_UNICODE_CHAR ( c ) ) tmp [ idx + + ] = c ;
}
input + = 3 ;
expanded + + ;
} else if ( ( input + 1 < end ) & & input [ 0 ] = = ' . ' & & input [ 1 ] = = ' . ' ) {
/* Error, try to be as helpful as possible:
( a range ending / starting with ' . ' won ' t be captured here ) */
if ( end - len > = input ) { /* There is no 'left' char */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, no character to the left of '..' " ) ;
result = FAILURE ;
continue ;
}
if ( input + 2 > = end ) { /* There is no 'right' char */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, no character to the right of '..' " ) ;
result = FAILURE ;
continue ;
}
if ( input [ - 1 ] > input [ 2 ] ) { /* Wrong order */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range, '..'-range needs to be incrementing " ) ;
result = FAILURE ;
continue ;
}
/* FIXME: Better error (a..b..c is the only left possibility?) */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid '..'-range " ) ;
result = FAILURE ;
continue ;
} else {
tmp [ idx + + ] = c ;
}
}
/* If any ranges were expanded, convert the expanded results back to UTF-16 */
if ( expanded > 0 ) {
len = tmp_len ;
* range = ( UChar * ) erealloc ( * range , ( len + 1 ) * sizeof ( UChar ) ) ;
err = U_ZERO_ERROR ;
u_strFromUTF32 ( * range , len + 1 , & len , tmp , tmp_len , & err ) ;
2006-03-27 23:05:38 +00:00
if ( err = = U_BUFFER_OVERFLOW_ERROR ) {
2005-08-11 23:36:07 +00:00
err = U_ZERO_ERROR ;
* range = ( UChar * ) erealloc ( * range , ( len + 1 ) * sizeof ( UChar ) ) ;
u_strFromUTF32 ( * range , len + 1 , NULL , tmp , tmp_len , & err ) ;
if ( U_FAILURE ( err ) ) { /* Internal ICU error */
result = FAILURE ;
}
}
* range_len = len ;
}
efree ( tmp ) ;
efree ( codepts ) ;
return result ;
}
/* }}} */
/* {{{ php_u_trim()
* Unicode capable version of php_trim ( )
*/
2006-03-02 13:12:45 +00:00
static UChar * php_u_trim ( UChar * c , int len , UChar * what , int what_len , zval * return_value , int mode TSRMLS_DC )
2005-08-11 23:36:07 +00:00
{
2006-08-18 18:01:58 +00:00
int32_t i , k ;
UChar ch = 0 ;
2005-08-11 23:36:07 +00:00
int32_t start = 0 , end = len ;
if ( what ) {
2006-03-15 12:20:49 +00:00
what = eustrndup ( what , what_len ) ;
2006-08-18 18:01:58 +00:00
php_expand_uchar_range ( & what , & what_len TSRMLS_CC ) ;
2007-04-22 19:22:19 +00:00
} else {
what = USTR_MAKE ( " \n \r \t \v \0 " ) ;
what_len = sizeof ( " \n \r \t \v \0 " ) - 1 ;
2005-08-11 23:36:07 +00:00
}
if ( mode & 1 ) {
2006-08-15 20:38:12 +00:00
for ( i = k = 0 ; i < end ; ) {
U16_NEXT ( c , k , end , ch ) ;
2005-08-11 23:36:07 +00:00
if ( what ) {
2006-08-16 18:07:22 +00:00
if ( u_memchr32 ( what , ch , what_len ) = = NULL ) {
break ;
2005-08-11 23:36:07 +00:00
}
} else {
2006-04-18 05:18:12 +00:00
if ( u_isWhitespace ( ch ) = = FALSE ) {
break ;
}
2005-08-11 23:36:07 +00:00
}
2006-08-15 20:38:12 +00:00
i = k ;
2005-08-11 23:36:07 +00:00
}
start = i ;
}
if ( mode & 2 ) {
2006-08-15 20:38:12 +00:00
for ( i = k = end ; i > start ; ) {
U16_PREV ( c , 0 , k , ch ) ;
2005-08-11 23:36:07 +00:00
if ( what ) {
2006-08-16 18:07:22 +00:00
if ( u_memchr32 ( what , ch , what_len ) = = NULL ) {
break ;
2005-08-11 23:36:07 +00:00
}
} else {
2006-04-18 05:18:12 +00:00
if ( u_isWhitespace ( ch ) = = FALSE ) {
break ;
}
2005-08-11 23:36:07 +00:00
}
2006-08-15 20:38:12 +00:00
i = k ;
2005-08-11 23:36:07 +00:00
}
end = i ;
}
2006-03-15 12:20:49 +00:00
if ( what )
{
efree ( what ) ;
}
2005-08-11 23:36:07 +00:00
if ( start < len ) {
if ( return_value ) {
2006-04-18 05:18:12 +00:00
RETVAL_UNICODEL ( c + start , end - start , 1 ) ;
2005-08-15 08:11:35 +00:00
return NULL ;
2005-08-11 23:36:07 +00:00
} else {
2006-04-18 05:18:12 +00:00
return eustrndup ( c + start , end - start ) ;
2005-08-11 23:36:07 +00:00
}
} else { /* Trimmed the whole string */
if ( return_value ) {
2005-08-12 16:46:38 +00:00
RETVAL_EMPTY_UNICODE ( ) ;
2005-08-15 08:11:35 +00:00
return NULL ;
2005-08-11 23:36:07 +00:00
} else {
return ( USTR_MAKE ( " " ) ) ;
}
}
}
/* }}} */
2002-07-13 04:13:43 +00:00
/* {{{ php_do_trim
* Base for trim ( ) , rtrim ( ) and ltrim ( ) functions .
*/
static void php_do_trim ( INTERNAL_FUNCTION_PARAMETERS , int mode )
1999-04-17 00:37:12 +00:00
{
2006-08-15 20:38:12 +00:00
zstr str , what = NULL_ZSTR ;
int str_len , what_len ;
zend_uchar str_type ;
2005-08-17 11:36:32 +00:00
2006-08-15 20:38:12 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|T " , & str , & str_len ,
& str_type , & what , & what_len , & str_type ) = = FAILURE ) {
return ;
2001-09-04 06:18:11 +00:00
}
2002-07-13 04:13:43 +00:00
2006-08-15 20:38:12 +00:00
if ( ZEND_NUM_ARGS ( ) > 1 ) {
if ( str_type = = IS_UNICODE ) {
php_u_trim ( str . u , str_len , what . u , what_len , return_value , mode TSRMLS_CC ) ;
2005-08-11 23:36:07 +00:00
} else {
2006-08-15 20:38:12 +00:00
php_trim ( str . s , str_len , what . s , what_len , return_value , mode TSRMLS_CC ) ;
2005-08-11 23:36:07 +00:00
}
2002-07-13 04:13:43 +00:00
} else {
2006-08-15 20:38:12 +00:00
if ( str_type = = IS_UNICODE ) {
php_u_trim ( str . u , str_len , NULL , 0 , return_value , mode TSRMLS_CC ) ;
2005-08-11 23:36:07 +00:00
} else {
2006-08-15 20:38:12 +00:00
php_trim ( str . s , str_len , NULL , 0 , return_value , mode TSRMLS_CC ) ;
2005-08-11 23:36:07 +00:00
}
2001-09-04 06:18:11 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string trim(string str [, string character_mask]) U
2001-09-04 10:44:28 +00:00
Strips whitespace from the beginning and end of a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( trim )
1999-04-17 00:37:12 +00:00
{
2002-07-13 04:13:43 +00:00
php_do_trim ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 3 ) ;
}
/* }}} */
1999-04-17 00:37:12 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto string rtrim(string str [, string character_mask]) U
2002-07-13 04:13:43 +00:00
Removes trailing whitespace */
PHP_FUNCTION ( rtrim )
{
php_do_trim ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 2 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string ltrim(string str [, string character_mask]) U
2001-09-04 10:44:28 +00:00
Strips whitespace from the beginning of a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( ltrim )
1999-04-17 00:37:12 +00:00
{
2002-07-13 04:13:43 +00:00
php_do_trim ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2003-03-09 00:05:48 +00:00
/* {{{ proto string wordwrap(string str [, int width [, string break [, boolean cut]]])
2001-09-04 10:44:28 +00:00
Wraps buffer to selected number of characters using string break char */
2000-07-22 01:12:24 +00:00
PHP_FUNCTION ( wordwrap )
{
2002-01-05 20:46:43 +00:00
const char * text , * breakchar = " \n " ;
char * newtext ;
2006-08-10 19:02:32 +00:00
int textlen , breakcharlen = 1 , newtextlen , chk ;
size_t alloced ;
2002-01-05 20:46:43 +00:00
long current = 0 , laststart = 0 , lastspace = 0 ;
long linelength = 75 ;
2002-01-04 19:48:08 +00:00
zend_bool docut = 0 ;
2000-07-22 01:12:24 +00:00
2002-01-04 19:48:08 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|lsb " , & text , & textlen , & linelength , & breakchar , & breakcharlen , & docut ) = = FAILURE ) {
return ;
2000-07-22 01:12:24 +00:00
}
2004-07-06 22:16:42 +00:00
if ( textlen = = 0 ) {
RETURN_EMPTY_STRING ( ) ;
}
2000-07-22 01:12:24 +00:00
2007-07-23 11:47:44 +00:00
if ( breakcharlen = = 0 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Break string cannot be empty " ) ;
RETURN_FALSE ;
}
2002-01-04 19:48:08 +00:00
if ( linelength = = 0 & & docut ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Can't force cut when width is zero " ) ;
2002-01-04 19:48:08 +00:00
RETURN_FALSE ;
2000-09-11 20:06:24 +00:00
}
2000-07-22 01:12:24 +00:00
/* Special case for a single-character break as it needs no
additional storage space */
2002-01-04 19:48:08 +00:00
if ( breakcharlen = = 1 & & ! docut ) {
newtext = estrndup ( text , textlen ) ;
2001-09-04 06:18:11 +00:00
2002-01-05 20:46:43 +00:00
laststart = lastspace = 0 ;
for ( current = 0 ; current < textlen ; current + + ) {
if ( text [ current ] = = breakchar [ 0 ] ) {
laststart = lastspace = current ;
2002-10-10 18:41:24 +00:00
} else if ( text [ current ] = = ' ' ) {
2002-01-05 20:46:43 +00:00
if ( current - laststart > = linelength ) {
newtext [ current ] = breakchar [ 0 ] ;
2004-05-13 17:44:23 +00:00
laststart = current + 1 ;
2000-07-22 01:12:24 +00:00
}
2002-01-05 20:46:43 +00:00
lastspace = current ;
2002-10-10 18:41:24 +00:00
} else if ( current - laststart > = linelength & & laststart ! = lastspace ) {
2002-01-05 20:46:43 +00:00
newtext [ lastspace ] = breakchar [ 0 ] ;
2006-07-28 12:21:34 +00:00
laststart = lastspace + 1 ;
2000-07-22 01:12:24 +00:00
}
}
2001-09-04 06:18:11 +00:00
2002-01-04 19:48:08 +00:00
RETURN_STRINGL ( newtext , textlen , 0 ) ;
2002-10-10 18:41:24 +00:00
} else {
2002-01-05 20:46:43 +00:00
/* Multiple character line break or forced cut */
if ( linelength > 0 ) {
2002-12-12 13:38:19 +00:00
chk = ( int ) ( textlen / linelength + 1 ) ;
2006-03-13 14:37:32 +00:00
newtext = safe_emalloc ( chk , breakcharlen , textlen + 1 ) ;
2002-12-12 13:38:19 +00:00
alloced = textlen + chk * breakcharlen + 1 ;
2002-10-10 18:41:24 +00:00
} else {
2002-12-12 13:38:19 +00:00
chk = textlen ;
alloced = textlen * ( breakcharlen + 1 ) + 1 ;
2006-03-13 14:37:32 +00:00
newtext = safe_emalloc ( textlen , ( breakcharlen + 1 ) , 1 ) ;
2002-01-05 20:46:43 +00:00
}
2002-12-12 13:38:19 +00:00
2002-01-05 20:46:43 +00:00
/* now keep track of the actual new text length */
newtextlen = 0 ;
laststart = lastspace = 0 ;
for ( current = 0 ; current < textlen ; current + + ) {
2002-12-12 13:38:19 +00:00
if ( chk < = 0 ) {
alloced + = ( int ) ( ( ( textlen - current + 1 ) / linelength + 1 ) * breakcharlen ) + 1 ;
newtext = erealloc ( newtext , alloced ) ;
chk = ( int ) ( ( textlen - current ) / linelength ) + 1 ;
}
2002-01-05 20:46:43 +00:00
/* when we hit an existing break, copy to new buffer, and
* fix up laststart and lastspace */
if ( text [ current ] = = breakchar [ 0 ]
& & current + breakcharlen < textlen
& & ! strncmp ( text + current , breakchar , breakcharlen ) ) {
memcpy ( newtext + newtextlen , text + laststart , current - laststart + breakcharlen ) ;
newtextlen + = current - laststart + breakcharlen ;
current + = breakcharlen - 1 ;
laststart = lastspace = current + 1 ;
2002-12-12 13:38:19 +00:00
chk - - ;
2000-07-22 01:12:24 +00:00
}
2002-01-05 20:46:43 +00:00
/* if it is a space, check if it is at the line boundary,
* copy and insert a break , or just keep track of it */
else if ( text [ current ] = = ' ' ) {
if ( current - laststart > = linelength ) {
memcpy ( newtext + newtextlen , text + laststart , current - laststart ) ;
newtextlen + = current - laststart ;
memcpy ( newtext + newtextlen , breakchar , breakcharlen ) ;
newtextlen + = breakcharlen ;
laststart = current + 1 ;
2002-12-12 13:38:19 +00:00
chk - - ;
2000-07-22 01:12:24 +00:00
}
2002-01-05 20:46:43 +00:00
lastspace = current ;
2000-07-22 01:12:24 +00:00
}
2002-01-05 20:46:43 +00:00
/* if we are cutting, and we've accumulated enough
2002-01-05 23:49:58 +00:00
* characters , and we haven ' t see a space for this line ,
* copy and insert a break . */
else if ( current - laststart > = linelength
& & docut & & laststart > = lastspace ) {
2002-01-05 20:46:43 +00:00
memcpy ( newtext + newtextlen , text + laststart , current - laststart ) ;
newtextlen + = current - laststart ;
memcpy ( newtext + newtextlen , breakchar , breakcharlen ) ;
newtextlen + = breakcharlen ;
laststart = lastspace = current ;
2002-12-12 13:38:19 +00:00
chk - - ;
2002-01-05 20:46:43 +00:00
}
/* if the current word puts us over the linelength, copy
* back up until the last space , insert a break , and move
* up the laststart */
else if ( current - laststart > = linelength
& & laststart < lastspace ) {
memcpy ( newtext + newtextlen , text + laststart , lastspace - laststart ) ;
newtextlen + = lastspace - laststart ;
memcpy ( newtext + newtextlen , breakchar , breakcharlen ) ;
newtextlen + = breakcharlen ;
laststart = lastspace = lastspace + 1 ;
2002-12-12 13:38:19 +00:00
chk - - ;
2000-07-22 01:12:24 +00:00
}
}
2002-01-05 20:46:43 +00:00
/* copy over any stragglers */
if ( laststart ! = current ) {
memcpy ( newtext + newtextlen , text + laststart , current - laststart ) ;
newtextlen + = current - laststart ;
2000-07-22 01:12:24 +00:00
}
2002-01-05 20:46:43 +00:00
newtext [ newtextlen ] = ' \0 ' ;
2002-09-05 14:00:28 +00:00
/* free unused memory */
newtext = erealloc ( newtext , newtextlen + 1 ) ;
2002-01-05 20:46:43 +00:00
RETURN_STRINGL ( newtext , newtextlen , 0 ) ;
2000-07-22 01:12:24 +00:00
}
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_explode
*/
2009-04-01 17:04:17 +00:00
PHPAPI void php_explode ( char * delim , uint delim_len , char * str , uint str_len , zend_uchar str_type , zval * return_value , long limit )
1999-04-17 00:37:12 +00:00
{
1999-12-06 18:29:22 +00:00
char * p1 , * p2 , * endp ;
1999-04-17 00:37:12 +00:00
2005-08-11 23:36:07 +00:00
endp = str + str_len ;
p1 = str ;
p2 = php_memnstr ( str , delim , delim_len , endp ) ;
1999-12-06 18:29:22 +00:00
2005-08-11 23:36:07 +00:00
if ( p2 = = NULL ) {
2006-01-17 12:18:53 +00:00
add_next_index_stringl ( return_value , p1 , str_len , 1 ) ;
1999-12-07 08:14:00 +00:00
} else {
do {
2006-01-17 12:18:53 +00:00
add_next_index_stringl ( return_value , p1 , p2 - p1 , 1 ) ;
2005-08-11 23:36:07 +00:00
p1 = p2 + delim_len ;
} while ( ( p2 = php_memnstr ( p1 , delim , delim_len , endp ) ) ! = NULL & &
2009-04-01 17:04:17 +00:00
- - limit > 1 ) ;
1999-12-07 08:14:00 +00:00
2005-08-11 23:36:07 +00:00
if ( p1 < = endp ) {
2006-01-17 12:18:53 +00:00
add_next_index_stringl ( return_value , p1 , endp - p1 , 1 ) ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
}
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2004-07-18 11:34:28 +00:00
/* {{{ php_explode_negative_limit
*/
2009-04-01 17:04:17 +00:00
PHPAPI void php_explode_negative_limit ( char * delim , uint delim_len , char * str , uint str_len , zend_uchar str_type , zval * return_value , long limit )
2004-07-18 11:34:28 +00:00
{
2009-04-01 17:04:17 +00:00
# define EXPLODE_ALLOC_STEP 64
2004-07-18 11:34:28 +00:00
char * p1 , * p2 , * endp ;
2005-08-11 23:36:07 +00:00
endp = str + str_len ;
p1 = str ;
p2 = php_memnstr ( str , delim , delim_len , endp ) ;
2004-07-18 11:34:28 +00:00
2005-08-11 23:36:07 +00:00
if ( p2 = = NULL ) {
2004-07-18 11:34:28 +00:00
/*
do nothing since limit < = - 1 , thus if only one chunk - 1 + ( limit ) < = 0
by doing nothing we return empty array
*/
} else {
2009-04-01 17:04:17 +00:00
int allocated = EXPLODE_ALLOC_STEP , found = 0 ;
long i , to_return ;
char * * positions = emalloc ( allocated * sizeof ( char * ) ) ;
2004-07-18 11:34:28 +00:00
positions [ found + + ] = p1 ;
do {
2005-08-11 23:36:07 +00:00
if ( found > = allocated ) {
2004-07-18 11:34:28 +00:00
allocated = found + EXPLODE_ALLOC_STEP ; /* make sure we have enough memory */
positions = erealloc ( positions , allocated * sizeof ( char * ) ) ;
}
2005-08-11 23:36:07 +00:00
positions [ found + + ] = p1 = p2 + delim_len ;
} while ( ( p2 = php_memnstr ( p1 , delim , delim_len , endp ) ) ! = NULL ) ;
2006-07-16 15:56:00 +00:00
2004-07-18 11:34:28 +00:00
to_return = limit + found ;
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
2005-08-11 23:36:07 +00:00
for ( i = 0 ; i < to_return ; i + + ) { /* this checks also for to_return > 0 */
2006-01-17 12:18:53 +00:00
add_next_index_stringl ( return_value , positions [ i ] ,
2005-08-11 23:36:07 +00:00
( positions [ i + 1 ] - delim_len ) - positions [ i ] , 1 ) ;
2004-07-18 11:34:28 +00:00
}
2009-04-01 17:04:17 +00:00
efree ( positions ) ;
2004-07-18 11:34:28 +00:00
}
# undef EXPLODE_ALLOC_STEP
}
/* }}} */
2005-08-11 23:36:07 +00:00
/* {{{ php_u_explode
* Unicode capable version of php_explode ( )
*/
2009-04-01 17:04:17 +00:00
static void php_u_explode ( UChar * delim , uint delim_len , UChar * str , uint str_len , zval * return_value , long limit )
2005-08-11 23:36:07 +00:00
{
UChar * p1 , * p2 , * endp ;
endp = str + str_len ;
p1 = str ;
p2 = zend_u_memnstr ( str , delim , delim_len , endp ) ;
if ( p2 = = NULL ) {
add_next_index_unicodel ( return_value , p1 , str_len , 1 ) ;
} else {
do {
add_next_index_unicodel ( return_value , p1 , p2 - p1 , 1 ) ;
p1 = ( UChar * ) p2 + delim_len ;
} while ( ( p2 = zend_u_memnstr ( p1 , delim , delim_len , endp ) ) ! = NULL & &
2009-04-01 17:04:17 +00:00
- - limit > 1 ) ;
2005-08-11 23:36:07 +00:00
if ( p1 < = endp ) {
add_next_index_unicodel ( return_value , p1 , endp - p1 , 1 ) ;
}
}
}
/* }}} */
/* {{{ php_u_explode_negative_limit
* Unicode capable version of php_explode_negative_limit ( )
*/
2009-04-01 17:04:17 +00:00
static void php_u_explode_negative_limit ( UChar * delim , uint delim_len , UChar * str , uint str_len , zval * return_value , long limit )
2005-08-11 23:36:07 +00:00
{
2009-04-01 17:04:17 +00:00
# define EXPLODE_ALLOC_STEP 64
2005-08-11 23:36:07 +00:00
UChar * p1 , * p2 , * endp ;
endp = str + str_len ;
p1 = str ;
p2 = zend_u_memnstr ( str , delim , delim_len , endp ) ;
if ( p2 = = NULL ) {
/*
do nothing since limit < = - 1 , thus if only one chunk - 1 + ( limit ) < = 0
by doing nothing we return empty array
*/
} else {
2009-04-01 17:04:17 +00:00
int allocated = EXPLODE_ALLOC_STEP , found = 0 ;
long i , to_return ;
UChar * * positions = emalloc ( allocated * sizeof ( UChar * ) ) ;
2005-08-11 23:36:07 +00:00
positions [ found + + ] = p1 ;
do {
if ( found > = allocated ) {
allocated = found + EXPLODE_ALLOC_STEP ; /* make sure we have enough memory */
positions = erealloc ( positions , allocated * sizeof ( UChar * ) ) ;
}
positions [ found + + ] = p1 = p2 + delim_len ;
} while ( ( p2 = zend_u_memnstr ( p1 , delim , delim_len , endp ) ) ! = NULL ) ;
2006-07-16 15:56:00 +00:00
2005-08-11 23:36:07 +00:00
to_return = limit + found ;
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
for ( i = 0 ; i < to_return ; i + + ) { /* this checks also for to_return > 0 */
add_next_index_unicodel ( return_value , positions [ i ] ,
( positions [ i + 1 ] - delim_len ) - positions [ i ] , 1 ) ;
}
2009-04-01 17:04:17 +00:00
efree ( positions ) ;
2005-08-11 23:36:07 +00:00
}
# undef EXPLODE_ALLOC_STEP
}
/* }}} */
2004-07-18 11:34:28 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto array explode(string separator, string str [, int limit]) U
2004-07-18 11:34:28 +00:00
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 . */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
PHP_FUNCTION ( explode )
1999-04-17 00:37:12 +00:00
{
2005-08-11 23:36:07 +00:00
void * str , * delim ;
2005-12-09 13:41:06 +00:00
int str_len , delim_len ;
2005-08-11 23:36:07 +00:00
zend_uchar str_type , delim_type ;
2009-04-01 17:04:17 +00:00
long limit = LONG_MAX ; /* No limit */
2000-05-23 05:04:28 +00:00
2009-04-01 17:04:17 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT|l " , & delim , & delim_len , & delim_type ,
2006-08-02 21:53:43 +00:00
& str , & str_len , & str_type , & limit ) = = FAILURE ) {
2005-08-11 23:36:07 +00:00
return ;
2001-09-04 06:18:11 +00:00
}
2005-08-11 23:36:07 +00:00
if ( delim_len = = 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Empty delimiter " ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
RETURN_FALSE ;
}
1999-12-06 18:29:22 +00:00
2002-12-05 22:28:02 +00:00
array_init ( return_value ) ;
1999-12-06 18:29:22 +00:00
2005-08-11 23:36:07 +00:00
if ( str_len = = 0 ) {
2009-04-01 17:04:17 +00:00
if ( limit > = 0 ) {
2008-12-27 05:13:30 +00:00
if ( str_type = = IS_UNICODE ) {
add_next_index_unicodel ( return_value , USTR_MAKE ( " " ) , sizeof ( " " ) - 1 , 0 ) ;
} else {
add_next_index_stringl ( return_value , " " , sizeof ( " " ) - 1 , 1 ) ;
}
2005-08-11 23:36:07 +00:00
}
2004-07-18 11:34:28 +00:00
return ;
}
2009-04-01 17:04:17 +00:00
if ( limit > 1 ) {
2005-08-11 23:36:07 +00:00
if ( str_type = = IS_UNICODE ) {
2009-04-01 17:04:17 +00:00
php_u_explode ( ( UChar * ) delim , delim_len , ( UChar * ) str , str_len , return_value , limit ) ;
2005-08-11 23:36:07 +00:00
} else {
2009-04-01 17:04:17 +00:00
php_explode ( ( char * ) delim , delim_len , ( char * ) str , str_len , str_type , return_value , limit ) ;
2005-08-11 23:36:07 +00:00
}
2009-04-01 17:04:17 +00:00
} else if ( limit < 0 ) {
2005-08-11 23:36:07 +00:00
if ( str_type = = IS_UNICODE ) {
php_u_explode_negative_limit ( ( UChar * ) delim , delim_len , ( UChar * ) str , str_len , return_value , limit ) ;
} else {
php_explode_negative_limit ( ( char * ) delim , delim_len , ( char * ) str , str_len , str_type , return_value , limit ) ;
}
2000-05-23 05:04:28 +00:00
} else {
2005-08-11 23:36:07 +00:00
if ( str_type = = IS_UNICODE ) {
2009-04-01 17:04:17 +00:00
add_index_unicodel ( return_value , 0 , ( UChar * ) str , str_len , 1 ) ;
2005-08-11 23:36:07 +00:00
} else {
2009-04-01 17:04:17 +00:00
add_index_stringl ( return_value , 0 , ( char * ) str , str_len , 1 ) ;
2005-08-11 23:36:07 +00:00
}
2000-05-23 05:04:28 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
/* }}} */
2006-08-02 21:53:43 +00:00
/* {{{ proto string join([string glue,] array pieces) U
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
An alias for implode */
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_implode
*/
2006-08-30 18:40:26 +00:00
PHPAPI void php_implode ( zval * delim , zval * arr , zval * retval TSRMLS_DC )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
{
2005-08-16 12:04:13 +00:00
zend_uchar return_type ;
2005-08-17 07:14:12 +00:00
int numelems , i = 0 ;
2005-08-16 12:04:13 +00:00
HashPosition pos ;
zval * * tmp ;
Z_TYPE_P ( retval ) = return_type = Z_TYPE_P ( delim ) ; /* ... to start off */
2002-10-04 20:44:19 +00:00
2005-08-16 12:04:13 +00:00
/* Setup return value */
if ( return_type = = IS_UNICODE ) {
ZVAL_EMPTY_UNICODE ( retval ) ;
} else {
ZVAL_EMPTY_STRING ( retval ) ;
}
1999-04-17 00:37:12 +00:00
2005-08-16 12:04:13 +00:00
numelems = zend_hash_num_elements ( Z_ARRVAL_P ( arr ) ) ;
2003-02-08 15:26:17 +00:00
if ( numelems = = 0 ) {
2005-08-16 12:04:13 +00:00
return ;
2002-10-06 11:28:11 +00:00
}
2001-09-04 06:18:11 +00:00
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_P ( arr ) , & pos ) ;
2005-08-17 07:14:12 +00:00
while ( zend_hash_get_current_data_ex ( Z_ARRVAL_P ( arr ) , ( void * * ) & tmp , & pos ) = = SUCCESS ) {
2005-08-16 12:04:13 +00:00
if ( Z_TYPE_PP ( tmp ) ! = return_type ) {
if ( return_type = = IS_UNICODE ) {
2006-11-10 12:01:50 +00:00
if ( Z_TYPE_PP ( tmp ) ! = IS_UNICODE ) {
2005-08-16 12:04:13 +00:00
SEPARATE_ZVAL ( tmp ) ;
convert_to_unicode_ex ( tmp ) ;
}
2006-01-17 12:18:53 +00:00
} else if ( return_type = = IS_STRING ) {
2006-11-10 12:01:50 +00:00
if ( Z_TYPE_PP ( tmp ) ! = IS_STRING ) {
2005-08-16 12:04:13 +00:00
SEPARATE_ZVAL ( tmp ) ;
2006-01-17 12:18:53 +00:00
convert_to_string_ex ( tmp ) ;
2005-08-16 12:04:13 +00:00
}
} else {
if ( Z_TYPE_PP ( tmp ) = = IS_UNICODE ) {
/* Convert IS_STRING up to IS_UNICODE */
convert_to_unicode_ex ( & retval ) ;
convert_to_unicode_ex ( & delim ) ;
Z_TYPE_P ( retval ) = return_type = IS_UNICODE ;
} else {
SEPARATE_ZVAL ( tmp ) ;
convert_to_string_ex ( tmp ) ;
}
}
}
/* Append elem */
if ( return_type = = IS_UNICODE ) {
Z_USTRVAL_P ( retval ) = eurealloc ( Z_USTRVAL_P ( retval ) ,
2006-01-24 23:09:43 +00:00
Z_USTRLEN_P ( retval ) + Z_USTRLEN_PP ( tmp ) + 1 ) ;
2005-08-17 07:59:31 +00:00
memcpy ( Z_USTRVAL_P ( retval ) + Z_USTRLEN_P ( retval ) , Z_USTRVAL_PP ( tmp ) , UBYTES ( Z_USTRLEN_PP ( tmp ) + 1 ) ) ;
2005-08-16 12:04:13 +00:00
Z_USTRLEN_P ( retval ) + = Z_USTRLEN_PP ( tmp ) ;
2005-08-17 07:14:12 +00:00
if ( + + i < numelems ) { /* Append delim */
2005-08-16 12:04:13 +00:00
Z_USTRVAL_P ( retval ) = eurealloc ( Z_USTRVAL_P ( retval ) ,
2006-01-24 23:09:43 +00:00
Z_USTRLEN_P ( retval ) + Z_USTRLEN_P ( delim ) + 1 ) ;
2005-08-17 07:59:31 +00:00
memcpy ( Z_USTRVAL_P ( retval ) + Z_USTRLEN_P ( retval ) , Z_USTRVAL_P ( delim ) , UBYTES ( Z_USTRLEN_P ( delim ) + 1 ) ) ;
2005-08-16 12:04:13 +00:00
Z_USTRLEN_P ( retval ) + = Z_USTRLEN_P ( delim ) ;
}
} else {
Z_STRVAL_P ( retval ) = ( char * ) erealloc ( Z_STRVAL_P ( retval ) ,
2005-08-17 07:59:31 +00:00
Z_STRLEN_P ( retval ) + Z_STRLEN_PP ( tmp ) + 1 ) ;
memcpy ( Z_STRVAL_P ( retval ) + Z_STRLEN_P ( retval ) , Z_STRVAL_PP ( tmp ) , Z_STRLEN_PP ( tmp ) + 1 ) ;
2005-08-16 12:04:13 +00:00
Z_STRLEN_P ( retval ) + = Z_STRLEN_PP ( tmp ) ;
2005-08-17 07:14:12 +00:00
if ( + + i < numelems ) { /* Append delim */
2005-08-16 12:04:13 +00:00
Z_STRVAL_P ( retval ) = ( char * ) erealloc ( Z_STRVAL_P ( retval ) ,
2005-08-17 07:59:31 +00:00
Z_STRLEN_P ( retval ) + Z_STRLEN_P ( delim ) + 1 ) ;
memcpy ( Z_STRVAL_P ( retval ) + Z_STRLEN_P ( retval ) , Z_STRVAL_P ( delim ) , Z_STRLEN_P ( delim ) + 1 ) ;
2005-08-16 12:04:13 +00:00
Z_STRLEN_P ( retval ) + = Z_STRLEN_P ( delim ) ;
}
}
2005-08-17 07:14:12 +00:00
zend_hash_move_forward_ex ( Z_ARRVAL_P ( arr ) , & pos ) ;
1999-04-17 00:37:12 +00:00
}
2002-10-04 20:44:19 +00:00
2005-08-16 12:04:13 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto string implode([string glue,] array pieces) U
2001-09-04 10:44:28 +00:00
Joins array elements placing glue string between items and return one string */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
PHP_FUNCTION ( implode )
{
2008-08-16 21:16:25 +00:00
zval * * arg1 = NULL , * * arg2 = NULL , * delim , * arr ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Z|Z " , & arg1 , & arg2 ) = = FAILURE ) {
2005-08-16 12:04:13 +00:00
return ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2008-08-16 21:16:25 +00:00
if ( ZEND_NUM_ARGS ( ) = = 1 ) {
2002-10-04 16:53:14 +00:00
if ( Z_TYPE_PP ( arg1 ) ! = IS_ARRAY ) {
2007-10-01 12:04:09 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Argument must be an array " ) ;
return ;
2005-08-16 12:04:13 +00:00
} else {
SEPARATE_ZVAL ( arg1 ) ;
2008-08-16 21:16:25 +00:00
arr = * arg1 ;
2005-08-17 07:14:12 +00:00
MAKE_STD_ZVAL ( delim ) ;
2009-03-26 20:02:53 +00:00
ZVAL_UNICODEL ( delim , EMPTY_STR , sizeof ( " " ) - 1 , 0 ) ;
2002-10-04 16:53:14 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
} else {
2002-10-04 16:53:14 +00:00
if ( Z_TYPE_PP ( arg1 ) = = IS_ARRAY ) {
SEPARATE_ZVAL ( arg1 ) ;
arr = * arg1 ;
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_PP ( arg2 ) ! = IS_UNICODE & & Z_TYPE_PP ( arg2 ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( arg2 ) ;
2005-08-17 07:59:31 +00:00
}
2002-10-04 16:53:14 +00:00
delim = * arg2 ;
} else if ( Z_TYPE_PP ( arg2 ) = = IS_ARRAY ) {
SEPARATE_ZVAL ( arg2 ) ;
arr = * arg2 ;
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_PP ( arg1 ) ! = IS_UNICODE & & Z_TYPE_PP ( arg1 ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( arg1 ) ;
2005-08-17 07:59:31 +00:00
}
2002-10-04 16:53:14 +00:00
delim = * arg1 ;
} else {
2007-10-01 12:04:09 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid arguments passed " ) ;
return ;
2002-10-04 16:53:14 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2001-09-04 06:18:11 +00:00
2006-08-30 20:24:32 +00:00
php_implode ( delim , arr , return_value TSRMLS_CC ) ;
2002-11-05 13:52:11 +00:00
2008-08-16 21:16:25 +00:00
if ( ZEND_NUM_ARGS ( ) = = 1 ) {
2002-11-05 13:52:11 +00:00
FREE_ZVAL ( delim ) ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
1999-04-17 00:37:12 +00:00
/* }}} */
2006-07-16 15:56:00 +00:00
# define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
2001-08-03 23:09:05 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto string strtok([string str,] string token) U
1999-04-17 00:37:12 +00:00
Tokenize a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strtok )
1999-04-17 00:37:12 +00:00
{
2005-09-29 11:05:30 +00:00
void * tok , * str ;
2005-12-09 13:41:06 +00:00
int tok_len , str_len ;
2005-09-29 11:05:30 +00:00
zend_uchar tok_type , str_type ;
zval * zv ;
char * token , * token_end , * p , * pe ;
UChar * u_token , * u_p , * u_pe ;
UChar32 ch , th ;
2006-07-13 17:55:50 +00:00
int32_t start = 0 , end , i , j , rem_len ;
2005-09-29 11:05:30 +00:00
int delim_found , token_present ;
2001-11-02 19:19:24 +00:00
int skipped = 0 ;
2005-09-29 11:05:30 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|T " ,
& str , & str_len , & str_type ,
& tok , & tok_len , & tok_type ) = = FAILURE ) {
return ;
}
2003-02-08 15:26:17 +00:00
switch ( ZEND_NUM_ARGS ( ) ) {
case 1 :
2005-09-29 11:05:30 +00:00
tok = str ;
tok_len = str_len ;
tok_type = str_type ;
2003-02-08 15:26:17 +00:00
break ;
default :
case 2 :
if ( BG ( strtok_zval ) ) {
zval_ptr_dtor ( & BG ( strtok_zval ) ) ;
}
2005-09-29 11:05:30 +00:00
MAKE_STD_ZVAL ( zv ) ;
if ( str_type = = IS_UNICODE ) {
ZVAL_UNICODEL ( zv , ( UChar * ) str , str_len , 1 ) ;
BG ( strtok_last ) = BG ( strtok_string ) = Z_USTRVAL_P ( zv ) ;
} else {
2008-08-16 21:16:25 +00:00
ZVAL_STRINGL ( zv , ( char * ) str , str_len , 1 ) ;
2005-09-29 11:05:30 +00:00
BG ( strtok_last ) = BG ( strtok_string ) = Z_STRVAL_P ( zv ) ;
}
2008-08-16 21:16:25 +00:00
BG ( strtok_zval ) = zv ;
2005-09-29 11:05:30 +00:00
BG ( strtok_len ) = str_len ;
2003-02-08 15:26:17 +00:00
break ;
2001-08-03 08:49:19 +00:00
}
2005-09-29 11:05:30 +00:00
if ( BG ( strtok_zval ) & & tok_type ! = Z_TYPE_P ( BG ( strtok_zval ) ) ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Delimiter type must match string type " ) ;
2001-08-03 23:09:05 +00:00
RETURN_FALSE ;
2003-02-08 15:26:17 +00:00
}
2001-08-03 23:09:05 +00:00
2005-09-29 11:05:30 +00:00
if ( tok_type = = IS_UNICODE ) {
u_p = ( UChar * ) BG ( strtok_last ) ; /* Where we start to search */
u_pe = ( UChar * ) BG ( strtok_string ) + BG ( strtok_len ) ;
u_token = ( UChar * ) tok ;
if ( ! u_p | | u_p > = u_pe ) {
RETURN_FALSE ;
}
rem_len = u_pe - u_p ;
/* Skip leading delimiters */
token_present = 0 ;
for ( i = 0 ; ( u_p + i ) < u_pe ; ) {
delim_found = 0 ;
U16_NEXT ( u_p , i , rem_len , ch ) ;
for ( j = 0 ; j < tok_len ; ) {
U16_NEXT ( u_token , j , tok_len , th ) ;
if ( ch = = th ) {
delim_found = 1 ;
break ;
}
}
if ( delim_found = = 0 ) {
U16_BACK_1 ( u_p , 0 , i ) ; /* U16_NEXT() post-incrs 'i' */
start = i ;
token_present = 1 ;
break ;
}
}
if ( token_present = = 0 ) {
BG ( strtok_last ) = NULL ;
RETURN_FALSE ;
}
2001-08-03 23:09:05 +00:00
2005-09-29 11:05:30 +00:00
/* Seek to next delimiter */
delim_found = 0 ;
for ( i = start ; ( u_p + i ) < u_pe ; ) {
U16_NEXT ( u_p , i , rem_len , ch ) ;
for ( j = 0 ; j < tok_len ; ) {
U16_NEXT ( u_token , j , tok_len , th ) ;
if ( ch = = th ) {
delim_found = 1 ;
break ;
}
}
if ( delim_found ) {
U16_BACK_1 ( u_p , 0 , i ) ; /* 'i' was beyond delimiter */
break ;
}
}
end = i ;
if ( end - start ) {
2008-11-24 19:21:20 +00:00
RETVAL_UNICODEL ( u_p + start , end - start , 1 ) ;
/* skip matched token */
U16_FWD_1 ( u_p , end , rem_len ) ;
2005-09-29 11:05:30 +00:00
BG ( strtok_last ) = u_p + end ;
2008-11-24 19:21:20 +00:00
return ;
2005-09-29 11:05:30 +00:00
} else {
2001-08-03 23:09:05 +00:00
BG ( strtok_last ) = NULL ;
2005-09-29 11:05:30 +00:00
RETURN_FALSE ;
2001-08-03 22:42:02 +00:00
}
2005-09-29 11:05:30 +00:00
} else {
p = ( char * ) BG ( strtok_last ) ; /* Where we start to search */
pe = ( char * ) BG ( strtok_string ) + BG ( strtok_len ) ;
if ( ! p | | p > = pe ) {
RETURN_FALSE ;
2003-02-08 15:26:17 +00:00
}
2005-09-29 11:05:30 +00:00
token = ( char * ) tok ;
token_end = token + tok_len ;
while ( token < token_end ) {
STRTOK_TABLE ( token + + ) = 1 ;
}
/* Skip leading delimiters */
while ( STRTOK_TABLE ( p ) ) {
if ( + + p > = pe ) {
/* no other chars left */
BG ( strtok_last ) = NULL ;
RETVAL_FALSE ;
goto restore ;
}
skipped + + ;
}
2006-07-16 15:56:00 +00:00
/* We know at this place that *p is no delimiter, so skip it */
2005-09-29 11:05:30 +00:00
while ( + + p < pe ) {
if ( STRTOK_TABLE ( p ) ) {
2006-07-16 15:56:00 +00:00
goto return_token ;
2005-09-29 11:05:30 +00:00
}
}
if ( p - ( char * ) BG ( strtok_last ) ) {
2001-08-03 23:09:05 +00:00
return_token :
2006-01-17 12:18:53 +00:00
RETVAL_STRINGL ( ( char * ) BG ( strtok_last ) + skipped , ( p - ( char * ) BG ( strtok_last ) ) - skipped , 1 ) ;
2005-09-29 11:05:30 +00:00
BG ( strtok_last ) = p + 1 ;
} else {
RETVAL_FALSE ;
BG ( strtok_last ) = NULL ;
}
2001-08-03 23:09:05 +00:00
2005-09-29 11:05:30 +00:00
/* Restore table -- usually faster then memset'ing the table on every invocation */
2001-08-03 23:09:05 +00:00
restore :
2005-09-29 11:05:30 +00:00
token = ( char * ) tok ;
while ( token < token_end ) {
STRTOK_TABLE ( token + + ) = 0 ;
}
2003-02-08 15:26:17 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strtoupper
*/
1999-12-09 23:45:30 +00:00
PHPAPI char * php_strtoupper ( char * s , size_t len )
1999-04-17 00:37:12 +00:00
{
2002-10-25 20:09:53 +00:00
unsigned char * c , * e ;
2006-07-16 15:56:00 +00:00
2006-03-02 13:12:45 +00:00
c = ( unsigned char * ) s ;
2002-08-25 19:08:07 +00:00
e = c + len ;
2002-10-02 17:56:04 +00:00
while ( c < e ) {
2002-08-25 19:08:07 +00:00
* c = toupper ( * c ) ;
c + + ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
return s ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2005-08-11 23:36:07 +00:00
/* {{{ php_u_strtoupper
*/
2006-08-03 23:09:29 +00:00
PHPAPI UChar * php_u_strtoupper ( UChar * s , int * len , const char * locale )
2005-08-11 23:36:07 +00:00
{
UChar * dest = NULL ;
2006-03-02 13:12:45 +00:00
int dest_len ;
2005-08-11 23:36:07 +00:00
UErrorCode status ;
2006-07-16 15:56:00 +00:00
2005-08-11 23:36:07 +00:00
dest_len = * len ;
while ( 1 ) {
status = U_ZERO_ERROR ;
dest = eurealloc ( dest , dest_len + 1 ) ;
2006-08-03 23:09:29 +00:00
dest_len = u_strToUpper ( dest , dest_len , s , * len , locale , & status ) ;
2005-08-11 23:36:07 +00:00
if ( status ! = U_BUFFER_OVERFLOW_ERROR ) {
break ;
}
}
if ( U_SUCCESS ( status ) ) {
dest [ dest_len ] = 0 ;
* len = dest_len ;
2006-08-03 23:09:29 +00:00
return dest ;
2005-08-11 23:36:07 +00:00
} else {
efree ( dest ) ;
2006-08-03 23:09:29 +00:00
return NULL ;
2005-08-11 23:36:07 +00:00
}
}
/* }}} */
2006-08-02 21:53:43 +00:00
/* {{{ proto string strtoupper(string str) U
2001-09-04 10:44:28 +00:00
Makes a string uppercase */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strtoupper )
1999-04-17 00:37:12 +00:00
{
2006-08-03 23:09:29 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2006-08-03 23:09:29 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE ) {
UChar * result ;
if ( ( result = php_u_strtoupper ( str . u , & str_len , UG ( default_locale ) ) ) ) {
RETURN_UNICODEL ( result , str_len , 0 ) ;
} else {
RETURN_EMPTY_UNICODE ( ) ;
}
2005-08-11 23:36:07 +00:00
} else {
2006-08-03 23:09:29 +00:00
RETVAL_STRINGL ( str . s , str_len , 1 ) ;
2005-08-11 23:36:07 +00:00
php_strtoupper ( Z_STRVAL_P ( return_value ) , Z_STRLEN_P ( return_value ) ) ;
}
}
/* }}} */
/* {{{ php_u_strtolower
*/
2006-08-03 23:09:29 +00:00
PHPAPI UChar * php_u_strtolower ( UChar * s , int * len , const char * locale )
2005-08-11 23:36:07 +00:00
{
UChar * dest = NULL ;
2006-03-02 13:12:45 +00:00
int dest_len ;
2005-08-11 23:36:07 +00:00
UErrorCode status = U_ZERO_ERROR ;
dest_len = * len ;
while ( 1 ) {
status = U_ZERO_ERROR ;
dest = eurealloc ( dest , dest_len + 1 ) ;
2006-08-03 23:09:29 +00:00
dest_len = u_strToLower ( dest , dest_len , s , * len , locale , & status ) ;
2005-08-11 23:36:07 +00:00
if ( status ! = U_BUFFER_OVERFLOW_ERROR ) {
break ;
}
}
if ( U_SUCCESS ( status ) ) {
dest [ dest_len ] = 0 ;
* len = dest_len ;
2006-08-03 23:09:29 +00:00
return dest ;
2005-08-11 23:36:07 +00:00
} else {
efree ( dest ) ;
2006-08-03 23:09:29 +00:00
return NULL ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strtolower
*/
1999-12-09 23:45:30 +00:00
PHPAPI char * php_strtolower ( char * s , size_t len )
1999-04-17 00:37:12 +00:00
{
2002-10-25 20:09:53 +00:00
unsigned char * c , * e ;
2006-07-16 15:56:00 +00:00
2006-03-02 13:12:45 +00:00
c = ( unsigned char * ) s ;
2002-08-25 19:08:07 +00:00
e = c + len ;
2002-10-02 17:56:04 +00:00
while ( c < e ) {
2002-08-25 19:08:07 +00:00
* c = tolower ( * c ) ;
c + + ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
return s ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-08-02 21:53:43 +00:00
/* {{{ proto string strtolower(string str) U
2001-09-04 10:44:28 +00:00
Makes a string lowercase */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strtolower )
1999-04-17 00:37:12 +00:00
{
2006-08-03 23:09:29 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2006-08-03 23:09:29 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE ) {
UChar * result ;
if ( ( result = php_u_strtolower ( str . u , & str_len , UG ( default_locale ) ) ) ) {
RETURN_UNICODEL ( result , str_len , 0 ) ;
} else {
RETURN_EMPTY_UNICODE ( ) ;
}
2005-08-11 23:36:07 +00:00
} else {
2006-08-03 23:09:29 +00:00
RETVAL_STRINGL ( str . s , str_len , 1 ) ;
2005-08-11 23:36:07 +00:00
php_strtolower ( Z_STRVAL_P ( return_value ) , Z_STRLEN_P ( return_value ) ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-22 10:20:20 +00:00
/* {{{ php_strtotitle
*/
PHPAPI char * php_strtotitle ( char * s , size_t len )
{
s [ 0 ] = toupper ( s [ 0 ] ) ;
return s ;
}
/* }}} */
/* {{{ php_u_strtotitle
*/
2006-08-03 23:09:29 +00:00
PHPAPI UChar * php_u_strtotitle ( UChar * s , int32_t * len , const char * locale )
2006-03-22 10:20:20 +00:00
{
UChar * dest = NULL ;
int32_t dest_len ;
UErrorCode status = U_ZERO_ERROR ;
UBreakIterator * brkiter ;
2006-07-16 15:56:00 +00:00
2006-03-22 10:20:20 +00:00
dest_len = * len ;
2006-08-03 23:09:29 +00:00
brkiter = ubrk_open ( UBRK_WORD , locale , s , * len , & status ) ;
2006-03-22 10:20:20 +00:00
while ( 1 ) {
status = U_ZERO_ERROR ;
dest = eurealloc ( dest , dest_len + 1 ) ;
2006-08-03 23:09:29 +00:00
dest_len = u_strToTitle ( dest , dest_len , s , * len , NULL , locale , & status ) ;
2006-03-22 10:20:20 +00:00
if ( status ! = U_BUFFER_OVERFLOW_ERROR ) {
break ;
}
}
ubrk_close ( brkiter ) ;
if ( U_SUCCESS ( status ) ) {
dest [ dest_len ] = 0 ;
* len = dest_len ;
2006-08-03 23:09:29 +00:00
return dest ;
2006-03-22 10:20:20 +00:00
} else {
efree ( dest ) ;
2006-08-03 23:09:29 +00:00
return NULL ;
2006-03-22 10:20:20 +00:00
}
}
/* }}} */
2006-08-02 21:53:43 +00:00
/* {{{ proto string strtotitle(string str) U
2006-03-22 10:20:20 +00:00
Makes a string titlecase */
PHP_FUNCTION ( strtotitle )
{
2006-08-03 23:09:29 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2006-08-03 23:09:29 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2006-03-22 10:20:20 +00:00
}
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE & & str_len = = 0 ) {
2006-03-22 10:20:20 +00:00
RETURN_EMPTY_UNICODE ( ) ;
2006-08-03 23:09:29 +00:00
} else if ( str_len = = 0 ) {
2006-03-22 10:20:20 +00:00
RETURN_EMPTY_STRING ( ) ;
}
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE ) {
UChar * result ;
if ( ( result = php_u_strtotitle ( str . u , & str_len , UG ( default_locale ) ) ) ) {
RETURN_UNICODEL ( result , str_len , 0 ) ;
} else {
RETURN_EMPTY_UNICODE ( ) ;
}
2006-03-22 10:20:20 +00:00
} else {
2006-08-03 23:09:29 +00:00
RETVAL_STRINGL ( str . s , str_len , 1 ) ;
2006-10-04 17:38:09 +00:00
php_ucwords ( Z_STRVAL_P ( return_value ) , str_len ) ;
2006-03-22 10:20:20 +00:00
}
}
/* }}} */
2006-08-03 23:45:27 +00:00
/* {{{ php_u_basename
*/
2009-01-09 18:23:45 +00:00
PHPAPI void php_u_basename ( UChar * s , size_t len , UChar * suffix , size_t sufflen , UChar * * p_ret , size_t * p_len TSRMLS_DC )
2006-08-03 23:45:27 +00:00
{
2006-12-20 23:30:11 +00:00
UChar * end , * c , * comp , * cend ;
2006-08-03 23:45:27 +00:00
int state ;
c = comp = cend = s ;
end = s + len ;
state = 0 ;
while ( c < end ) {
# if defined(PHP_WIN32) || defined(NETWARE)
if ( * c = = ( UChar ) 0x2f /*'/'*/ | | * c = = ( UChar ) 0x5c /*'\\'*/ ) {
# else
if ( * c = = ( UChar ) 0x2f /*'/'*/ ) {
# endif
if ( state = = 1 ) {
state = 0 ;
cend = c ;
}
} else {
if ( state = = 0 ) {
comp = c ;
state = 1 ;
}
}
c + + ;
}
if ( state = = 1 ) {
cend = c ;
}
if ( suffix ! = NULL & & sufflen < ( cend - comp ) & &
u_memcmp ( cend - sufflen , suffix , sufflen ) = = 0 ) {
cend - = sufflen ;
}
len = cend - comp ;
if ( p_ret ) {
2006-12-20 23:30:11 +00:00
* p_ret = eustrndup ( comp , len ) ;
2006-08-03 23:45:27 +00:00
}
if ( p_len ) {
* p_len = len ;
}
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_basename
*/
2009-01-09 18:23:45 +00:00
PHPAPI void php_basename ( char * s , size_t len , char * suffix , size_t sufflen , char * * p_ret , size_t * p_len TSRMLS_DC )
1999-04-17 00:37:12 +00:00
{
2003-12-10 07:15:28 +00:00
char * ret = NULL , * c , * comp , * cend ;
size_t inc_len , cnt ;
int state ;
c = comp = cend = s ;
cnt = len ;
state = 0 ;
while ( cnt > 0 ) {
inc_len = ( * c = = ' \0 ' ? 1 : php_mblen ( c , cnt ) ) ;
switch ( inc_len ) {
case - 2 :
case - 1 :
inc_len = 1 ;
php_mblen ( NULL , 0 ) ;
break ;
case 0 :
goto quit_loop ;
case 1 :
2005-03-01 14:59:37 +00:00
# if defined(PHP_WIN32) || defined(NETWARE)
2003-12-10 07:15:28 +00:00
if ( * c = = ' / ' | | * c = = ' \\ ' ) {
# else
if ( * c = = ' / ' ) {
1999-04-17 00:37:12 +00:00
# endif
2003-12-10 07:15:28 +00:00
if ( state = = 1 ) {
state = 0 ;
cend = c ;
}
} else {
if ( state = = 0 ) {
comp = c ;
state = 1 ;
}
}
2006-07-17 20:43:07 +00:00
break ;
2003-12-10 07:15:28 +00:00
default :
2006-07-17 20:43:07 +00:00
if ( state = = 0 ) {
comp = c ;
state = 1 ;
}
2003-12-10 07:15:28 +00:00
break ;
}
c + = inc_len ;
cnt - = inc_len ;
2003-02-08 15:26:17 +00:00
}
2003-12-10 07:15:28 +00:00
quit_loop :
if ( state = = 1 ) {
cend = c ;
2003-02-08 15:26:17 +00:00
}
2003-12-10 07:15:28 +00:00
if ( suffix ! = NULL & & sufflen < ( cend - comp ) & &
memcmp ( cend - sufflen , suffix , sufflen ) = = 0 ) {
cend - = sufflen ;
2003-02-08 15:26:17 +00:00
}
2003-05-05 13:46:14 +00:00
2003-12-10 07:15:28 +00:00
len = cend - comp ;
if ( p_ret ) {
2006-12-20 23:30:11 +00:00
ret = emalloc ( len + 1 ) ;
memcpy ( ret , comp , len ) ;
ret [ len ] = ' \0 ' ;
2003-12-10 07:15:28 +00:00
* p_ret = ret ;
}
if ( p_len ) {
* p_len = len ;
}
2000-05-23 20:16:14 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
2000-05-23 20:16:14 +00:00
2006-08-03 23:45:27 +00:00
/* {{{ proto string basename(string path [, string suffix]) U
2001-09-04 10:44:28 +00:00
Returns the filename component of the path */
2000-05-23 20:16:14 +00:00
PHP_FUNCTION ( basename )
{
2006-08-03 23:45:27 +00:00
zstr string , suffix = NULL_ZSTR , ret ;
int string_len , suffix_len = 0 ;
zend_uchar string_type , suffix_type ;
2009-01-09 18:23:45 +00:00
size_t ret_len ;
2000-05-23 20:16:14 +00:00
2006-08-03 23:45:27 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|T " , & string , & string_len , & string_type , & suffix , & suffix_len , & suffix_type ) = = FAILURE ) {
2001-12-01 15:45:55 +00:00
return ;
2000-05-23 20:16:14 +00:00
}
2001-06-23 00:51:03 +00:00
2006-08-03 23:45:27 +00:00
if ( string_type = = IS_UNICODE ) {
php_u_basename ( string . u , string_len , suffix . u , suffix_len , & ret . u , & ret_len TSRMLS_CC ) ;
2009-01-09 18:23:45 +00:00
RETURN_UNICODEL ( ret . u , ( int ) ret_len , 0 ) ;
2006-08-03 23:45:27 +00:00
} else {
php_basename ( string . s , string_len , suffix . s , suffix_len , & ret . s , & ret_len TSRMLS_CC ) ;
2009-01-09 18:23:45 +00:00
RETURN_STRINGL ( ret . s , ( int ) ret_len , 0 ) ;
2006-08-03 23:45:27 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-08-04 18:09:46 +00:00
/* {{{ php_u_dirname
Returns directory name component of path */
2009-01-09 18:23:45 +00:00
PHPAPI size_t php_u_dirname ( UChar * path , size_t len )
2006-08-04 18:09:46 +00:00
{
2008-02-12 01:04:08 +00:00
return zend_u_dirname ( path , len ) ;
2006-08-04 18:09:46 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_dirname
2002-05-16 16:04:45 +00:00
Returns directory name component of path */
2009-01-09 18:23:45 +00:00
PHPAPI size_t php_dirname ( char * path , size_t len )
2000-10-03 14:43:04 +00:00
{
2008-02-12 01:04:08 +00:00
return zend_dirname ( path , len ) ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-08-04 18:09:46 +00:00
/* {{{ proto string dirname(string path) U
2001-09-04 10:44:28 +00:00
Returns the directory name component of the path */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( dirname )
1999-04-17 00:37:12 +00:00
{
2006-08-04 18:09:46 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
zstr ret ;
2009-01-09 18:23:45 +00:00
size_t ret_len ;
2003-04-12 21:53:46 +00:00
2006-08-04 18:09:46 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len ,
& str_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-04 18:09:46 +00:00
if ( str_type = = IS_UNICODE ) {
ret . u = eustrndup ( str . u , str_len ) ;
ret_len = php_u_dirname ( ret . u , str_len ) ;
} else {
ret . s = estrndup ( str . s , str_len ) ;
ret_len = php_dirname ( ret . s , str_len ) ;
2006-01-17 12:18:53 +00:00
}
2006-08-04 18:09:46 +00:00
2009-01-09 18:23:45 +00:00
RETURN_ZSTRL ( str_type , ret , ( int ) ret_len , 0 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-08-04 21:06:11 +00:00
/* {{{ proto array pathinfo(string path[, int options]) U
2001-09-04 10:44:28 +00:00
Returns information about a certain string */
2000-09-10 05:59:16 +00:00
PHP_FUNCTION ( pathinfo )
{
2006-08-04 21:06:11 +00:00
zstr path , ret = NULL_ZSTR ;
int path_len , have_basename , have_ext , have_filename ;
zend_uchar path_type ;
2009-01-09 18:23:45 +00:00
size_t ret_len ;
2002-01-22 03:35:23 +00:00
zval * tmp ;
2003-03-06 23:07:28 +00:00
long opt = PHP_PATHINFO_ALL ;
2002-01-22 03:35:23 +00:00
2006-08-04 21:06:11 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t|l " , & path , & path_len , & path_type , & opt ) = = FAILURE ) {
2002-01-22 03:35:23 +00:00
return ;
2000-09-10 05:59:16 +00:00
}
2001-09-04 06:18:11 +00:00
2006-07-17 06:44:45 +00:00
have_basename = ( ( opt & PHP_PATHINFO_BASENAME ) = = PHP_PATHINFO_BASENAME ) ;
2006-08-04 21:06:11 +00:00
have_filename = ( ( opt & PHP_PATHINFO_FILENAME ) = = PHP_PATHINFO_FILENAME ) ;
have_ext = ( ( opt & PHP_PATHINFO_EXTENSION ) = = PHP_PATHINFO_EXTENSION ) ;
2000-09-10 05:59:16 +00:00
MAKE_STD_ZVAL ( tmp ) ;
array_init ( tmp ) ;
2006-07-16 15:56:00 +00:00
2002-01-22 03:35:23 +00:00
if ( ( opt & PHP_PATHINFO_DIRNAME ) = = PHP_PATHINFO_DIRNAME ) {
2006-08-04 21:06:11 +00:00
if ( path_type = = IS_UNICODE ) {
ret . u = eustrndup ( path . u , path_len ) ;
ret_len = php_u_dirname ( ret . u , path_len ) ;
} else {
ret . s = estrndup ( path . s , path_len ) ;
ret_len = php_dirname ( ret . s , path_len ) ;
2003-02-08 15:26:17 +00:00
}
2006-08-04 21:06:11 +00:00
if ( ret_len > 0 ) {
2006-09-19 10:38:31 +00:00
add_ascii_assoc_zstrl ( tmp , " dirname " , path_type , ret , ret_len , 1 ) ;
2006-08-04 21:06:11 +00:00
}
efree ( ret . v ) ;
ret = NULL_ZSTR ;
2000-09-10 05:59:16 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-04 21:06:11 +00:00
if ( have_basename | | have_ext | | have_filename ) {
if ( path_type = = IS_UNICODE ) {
php_u_basename ( path . u , path_len , NULL , 0 , & ret . u , & ret_len TSRMLS_CC ) ;
} else {
php_basename ( path . s , path_len , NULL , 0 , & ret . s , & ret_len TSRMLS_CC ) ;
}
}
2006-07-17 06:44:45 +00:00
if ( have_basename ) {
2006-09-19 10:38:31 +00:00
add_ascii_assoc_zstrl ( tmp , " basename " , path_type , ret , ret_len , 0 ) ;
2006-07-16 15:56:00 +00:00
}
2006-08-04 21:06:11 +00:00
if ( have_ext ) {
zstr ext ;
2006-08-10 09:31:24 +00:00
int ext_len = 0 ;
2002-01-22 03:35:23 +00:00
2006-08-04 21:06:11 +00:00
if ( path_type = = IS_UNICODE ) {
2006-08-08 09:48:08 +00:00
ext . u = u_memrchr32 ( ret . u , ( UChar ) 0x2e /*'.'*/ , ret_len ) ;
2006-08-04 21:06:11 +00:00
if ( ext . u ) {
ext . u + + ;
ext_len = ret_len - ( ext . u - ret . u ) ;
}
} else {
2006-08-08 09:48:08 +00:00
ext . s = zend_memrchr ( ret . s , ' . ' , ret_len ) ;
2006-08-04 21:06:11 +00:00
if ( ext . s ) {
ext . s + + ;
ext_len = ret_len - ( ext . s - ret . s ) ;
}
2002-01-22 03:35:23 +00:00
}
2006-08-04 21:06:11 +00:00
if ( ext . v ) {
2006-09-19 10:38:31 +00:00
add_ascii_assoc_zstrl ( tmp , " extension " , path_type , ext , ext_len , 1 ) ;
2002-01-22 03:35:23 +00:00
}
2000-09-10 05:59:16 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-04 21:06:11 +00:00
if ( have_filename ) {
zstr p ;
2006-07-16 10:34:32 +00:00
int idx ;
2006-08-04 21:06:11 +00:00
if ( path_type = = IS_UNICODE ) {
2006-08-08 09:48:08 +00:00
p . u = u_memrchr32 ( ret . u , ( UChar ) 0x2e /*'.'*/ , ret_len ) ;
2006-08-04 21:06:11 +00:00
idx = p . u ? ( p . u - ret . u ) : ret_len ;
} else {
2006-08-08 09:48:08 +00:00
p . s = zend_memrchr ( ret . s , ' . ' , ret_len ) ;
2006-08-04 21:06:11 +00:00
idx = p . s ? ( p . s - ret . s ) : ret_len ;
2006-07-16 10:34:32 +00:00
}
2006-09-19 10:38:31 +00:00
add_ascii_assoc_zstrl ( tmp , " filename " , path_type , ret , idx , 1 ) ;
2006-07-17 06:44:45 +00:00
}
2006-07-16 10:34:32 +00:00
2006-08-04 21:06:11 +00:00
if ( ! have_basename & & ret . v ) {
efree ( ret . v ) ;
2006-07-16 10:34:32 +00:00
}
2001-09-04 06:18:11 +00:00
2002-01-22 03:35:23 +00:00
if ( opt = = PHP_PATHINFO_ALL ) {
2005-03-10 23:52:43 +00:00
RETURN_ZVAL ( tmp , 0 , 1 ) ;
2002-01-22 03:35:23 +00:00
} else {
zval * * element ;
if ( zend_hash_get_current_data ( Z_ARRVAL_P ( tmp ) , ( void * * ) & element ) = = SUCCESS ) {
2005-03-10 23:42:15 +00:00
RETVAL_ZVAL ( * element , 1 , 0 ) ;
2002-01-22 03:35:23 +00:00
} else {
2008-12-28 20:16:48 +00:00
ZVAL_EMPTY_UNICODE ( return_value ) ;
2002-01-22 03:35:23 +00:00
}
2000-09-10 05:59:16 +00:00
}
2005-03-10 23:42:15 +00:00
zval_ptr_dtor ( & tmp ) ;
2000-09-10 05:59:16 +00:00
}
/* }}} */
1999-04-17 00:37:12 +00:00
2005-10-20 19:25:54 +00:00
/* {{{ php_u_stristr
Unicode version of case insensitve strstr */
2006-10-03 18:13:36 +00:00
PHPAPI UChar * php_u_stristr ( UChar * str , UChar * pat , int str_len , int pat_len , zend_bool find_first TSRMLS_DC )
2006-09-29 21:00:07 +00:00
{
UChar * str_fold , * pat_fold ;
int str_fold_len , pat_fold_len ;
UChar * result , * found ;
int offset ;
UErrorCode status = U_ZERO_ERROR ;
zend_case_fold_string ( & str_fold , & str_fold_len , str , str_len , U_FOLD_CASE_DEFAULT , & status ) ;
if ( str_fold_len = = str_len ) {
zend_case_fold_string ( & pat_fold , & pat_fold_len , pat , pat_len , U_FOLD_CASE_DEFAULT , & status ) ;
2006-10-03 18:13:36 +00:00
if ( find_first ) {
found = u_strFindFirst ( str_fold , str_fold_len , pat_fold , pat_fold_len ) ;
} else {
found = u_strFindLast ( str_fold , str_fold_len , pat_fold , pat_fold_len ) ;
}
2006-09-29 21:00:07 +00:00
if ( found ) {
result = str + ( found - str_fold ) ;
} else {
result = NULL ;
}
efree ( pat_fold ) ;
} else {
usearch_setText ( UG ( root_search ) , str , str_len , & status ) ;
usearch_setPattern ( UG ( root_search ) , pat , pat_len , & status ) ;
usearch_setOffset ( UG ( root_search ) , 0 , & status ) ;
2006-10-03 18:13:36 +00:00
if ( find_first ) {
offset = usearch_first ( UG ( root_search ) , & status ) ;
} else {
offset = usearch_last ( UG ( root_search ) , & status ) ;
}
2006-09-29 21:00:07 +00:00
if ( offset ! = USEARCH_DONE ) {
result = str + offset ;
} else {
result = NULL ;
}
}
efree ( str_fold ) ;
return result ;
}
#if 0
2006-10-02 01:11:04 +00:00
PHPAPI UChar * php_u_stristr ( UChar * s , UChar * t , int s_len , int t_len TSRMLS_DC )
2005-10-20 19:25:54 +00:00
{
int32_t i , j , last ;
UChar32 ch1 , ch2 ;
/* Have to do this by hand since lower-casing can change lengths
by changing codepoints , and an offset within the lower - case &
2005-10-22 05:52:53 +00:00
upper - case strings might be different codepoints .
2005-10-22 13:32:51 +00:00
Find an occurrence of the first codepoint of ' t ' in ' s ' , and
starting from this point , match the rest of the codepoints of
' t ' with those in ' s ' . Comparisons are performed against
lower - case equivalents of the codepoints being matched .
2005-10-22 05:52:53 +00:00
2005-10-22 13:32:51 +00:00
' i ' & ' j ' are indices used for extracting codepoints ' ch1 ' &
2005-10-22 05:52:53 +00:00
' ch2 ' . ' last ' is offset in ' s ' where the search for ' t '
started , and indicates beginning of ' t ' in ' s ' for a successful
match .
2005-10-20 19:25:54 +00:00
*/
2005-10-22 05:52:53 +00:00
2005-10-20 19:25:54 +00:00
i = 0 ;
while ( i < = ( s_len - t_len ) ) {
last = i ;
U16_NEXT ( s , i , s_len , ch1 ) ;
2005-10-22 05:52:53 +00:00
j = 0 ;
U16_NEXT ( t , j , t_len , ch2 ) ;
2005-10-20 19:25:54 +00:00
if ( u_tolower ( ch1 ) = = u_tolower ( ch2 ) ) {
while ( j < t_len ) {
U16_NEXT ( s , i , s_len , ch1 ) ;
U16_NEXT ( t , j , t_len , ch2 ) ;
if ( u_tolower ( ch1 ) ! = u_tolower ( ch2 ) ) {
2005-10-22 05:52:53 +00:00
/* U16_NEXT() incr 'i' beyond 'ch1', re-adjust to
restart compare
*/
2005-10-20 19:25:54 +00:00
U16_BACK_1 ( s , 0 , i ) ;
break ;
}
}
if ( u_tolower ( ch1 ) = = u_tolower ( ch2 ) ) {
return s + last ;
}
}
}
return NULL ;
}
2006-09-29 21:00:07 +00:00
# endif
2005-10-20 19:25:54 +00:00
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_stristr
2002-09-11 14:40:52 +00:00
case insensitve strstr */
2006-03-02 13:12:45 +00:00
PHPAPI char * php_stristr ( char * s , char * t , size_t s_len , size_t t_len )
1999-04-17 00:37:12 +00:00
{
1999-12-11 19:50:01 +00:00
php_strtolower ( s , s_len ) ;
php_strtolower ( t , t_len ) ;
return php_memnstr ( s , t , t_len , s + s_len ) ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2005-10-19 19:10:13 +00:00
/* {{{ php_u_strspn
*/
2006-03-02 13:12:45 +00:00
PHPAPI int php_u_strspn ( UChar * s1 , UChar * s2 , UChar * s1_end , UChar * s2_end )
2005-10-19 19:10:13 +00:00
{
int32_t len1 = s1_end - s1 ;
int32_t len2 = s2_end - s2 ;
2006-03-02 13:12:45 +00:00
int32_t i ;
int codepts ;
2005-10-19 19:10:13 +00:00
UChar32 ch ;
for ( i = 0 , codepts = 0 ; i < len1 ; codepts + + ) {
U16_NEXT ( s1 , i , len1 , ch ) ;
if ( u_memchr32 ( s2 , ch , len2 ) = = NULL ) {
break ;
}
}
return codepts ;
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strspn
*/
1999-12-13 23:40:36 +00:00
PHPAPI size_t php_strspn ( char * s1 , char * s2 , char * s1_end , char * s2_end )
{
register const char * p = s1 , * spanp ;
register char c = * p ;
cont :
2003-02-08 15:26:17 +00:00
for ( spanp = s2 ; p ! = s1_end & & spanp ! = s2_end ; ) {
1999-12-13 23:40:36 +00:00
if ( * spanp + + = = c ) {
c = * ( + + p ) ;
goto cont ;
}
2003-02-08 15:26:17 +00:00
}
1999-12-13 23:40:36 +00:00
return ( p - s1 ) ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-12-13 23:40:36 +00:00
2005-10-19 19:10:13 +00:00
/* {{{ php_u_strcspn
*/
2006-03-02 13:12:45 +00:00
PHPAPI int php_u_strcspn ( UChar * s1 , UChar * s2 , UChar * s1_end , UChar * s2_end )
2005-10-19 19:10:13 +00:00
{
int32_t len1 = s1_end - s1 ;
int32_t len2 = s2_end - s2 ;
2006-03-02 13:12:45 +00:00
int32_t i ;
int codepts ;
2005-10-19 19:10:13 +00:00
UChar32 ch ;
2006-10-04 11:12:21 +00:00
for ( i = 0 , codepts = 0 ; i < len1 ; ) {
2005-10-19 19:10:13 +00:00
U16_NEXT ( s1 , i , len1 , ch ) ;
2007-10-02 11:35:26 +00:00
if ( len2 ) {
if ( u_memchr32 ( s2 , ch , len2 ) ) {
break ;
}
} else if ( ch = = ( UChar32 ) 0x00 ) {
2005-10-19 19:10:13 +00:00
break ;
}
2006-10-04 11:12:21 +00:00
codepts + + ;
2005-10-19 19:10:13 +00:00
}
return codepts ;
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strcspn
*/
1999-12-13 23:40:36 +00:00
PHPAPI size_t php_strcspn ( char * s1 , char * s2 , char * s1_end , char * s2_end )
{
register const char * p , * spanp ;
register char c = * s1 ;
for ( p = s1 ; ; ) {
spanp = s2 ;
do {
2003-02-08 15:26:17 +00:00
if ( * spanp = = c | | p = = s1_end ) {
2001-09-04 06:18:11 +00:00
return p - s1 ;
2003-02-08 15:26:17 +00:00
}
2006-10-04 11:12:21 +00:00
} while ( spanp + + < ( s2_end - 1 ) ) ;
2001-09-04 06:18:11 +00:00
c = * + + p ;
1999-12-13 23:40:36 +00:00
}
/* NOTREACHED */
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-12-13 23:40:36 +00:00
2006-10-04 17:38:09 +00:00
/* {{{ proto string stristr(string haystack, string needle[, bool part]) U
2001-09-04 10:44:28 +00:00
Finds first occurrence of a string within another , case insensitive */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( stristr )
1999-04-17 00:37:12 +00:00
{
2006-08-31 14:19:33 +00:00
zval * * haystack , * * needle ;
2005-08-09 20:49:19 +00:00
zend_bool part = 0 ;
2005-10-20 19:25:54 +00:00
zend_uchar str_type ;
1999-12-11 19:50:01 +00:00
char needle_char [ 2 ] ;
2005-10-20 19:25:54 +00:00
UChar u_needle_char [ 3 ] ;
2006-03-02 13:12:45 +00:00
int needle_len ;
2006-07-13 17:55:50 +00:00
char * haystack_copy = NULL ;
2006-02-21 20:12:43 +00:00
zstr target ;
2005-10-20 19:25:54 +00:00
void * found = NULL ;
int found_offset ;
void * start , * end ;
2006-08-31 14:19:33 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ZZ|b " , & haystack , & needle , & part ) = = FAILURE ) {
2005-08-09 20:49:19 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2005-12-09 22:26:39 +00:00
2008-01-10 14:31:11 +00:00
SEPARATE_ZVAL ( haystack ) ;
SEPARATE_ZVAL ( needle ) ;
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) ! = IS_UNICODE & & Z_TYPE_PP ( haystack ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( haystack ) ;
2005-10-20 19:25:54 +00:00
}
1999-04-17 00:37:12 +00:00
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( needle ) = = IS_UNICODE | | Z_TYPE_PP ( needle ) = = IS_STRING ) {
if ( ! Z_UNILEN_PP ( needle ) ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Empty delimiter " ) ;
1999-12-11 19:50:01 +00:00
RETURN_FALSE ;
}
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) ! = Z_TYPE_PP ( needle ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_PP ( haystack ) , Z_TYPE_PP ( needle ) ) ;
convert_to_explicit_type_ex ( haystack , str_type ) ;
convert_to_explicit_type_ex ( needle , str_type ) ;
2005-10-20 19:25:54 +00:00
}
2006-08-31 14:19:33 +00:00
target = Z_UNIVAL_PP ( needle ) ;
needle_len = Z_UNILEN_PP ( needle ) ;
2002-09-11 14:40:52 +00:00
} else {
2006-08-31 14:19:33 +00:00
convert_to_long_ex ( needle ) ;
2005-10-20 19:25:54 +00:00
needle_len = 0 ;
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
if ( Z_LVAL_PP ( needle ) < 0 | | Z_LVAL_PP ( needle ) > 0x10FFFF ) {
2005-10-20 19:25:54 +00:00
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
2006-10-02 19:18:14 +00:00
needle_len = zend_codepoint_to_uchar ( ( UChar32 ) Z_LVAL_PP ( needle ) , u_needle_char ) ;
u_needle_char [ needle_len ] = 0 ;
2006-02-21 20:12:43 +00:00
target . u = u_needle_char ;
2005-10-20 19:25:54 +00:00
} else {
2006-08-31 14:19:33 +00:00
needle_char [ needle_len + + ] = ( char ) Z_LVAL_PP ( needle ) ;
2005-10-20 19:25:54 +00:00
needle_char [ needle_len ] = 0 ;
2006-02-21 20:12:43 +00:00
target . s = needle_char ;
2005-10-20 19:25:54 +00:00
}
}
2006-08-31 14:19:33 +00:00
if ( needle_len > Z_UNILEN_PP ( haystack ) ) {
2005-10-20 19:25:54 +00:00
RETURN_FALSE ;
}
2000-03-22 08:14:00 +00:00
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
found = php_u_stristr ( Z_USTRVAL_PP ( haystack ) , target . u ,
2006-10-03 18:13:36 +00:00
Z_USTRLEN_PP ( haystack ) , needle_len , 1 TSRMLS_CC ) ;
2005-10-20 19:25:54 +00:00
} else {
2006-08-31 14:19:33 +00:00
haystack_copy = estrndup ( Z_STRVAL_PP ( haystack ) , Z_STRLEN_PP ( haystack ) ) ;
found = php_stristr ( Z_STRVAL_PP ( haystack ) , target . s ,
Z_STRLEN_PP ( haystack ) , needle_len ) ;
1999-04-17 00:37:12 +00:00
}
2002-09-11 14:40:52 +00:00
1999-04-17 00:37:12 +00:00
if ( found ) {
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
start = part ? Z_USTRVAL_PP ( haystack ) : found ;
end = part ? found : ( Z_USTRVAL_PP ( haystack ) + Z_USTRLEN_PP ( haystack ) ) ;
2005-10-20 19:25:54 +00:00
RETVAL_UNICODEL ( ( UChar * ) start , ( UChar * ) end - ( UChar * ) start , 1 ) ;
2005-08-09 20:49:19 +00:00
} else {
2006-08-31 14:19:33 +00:00
found_offset = ( char * ) found - Z_STRVAL_PP ( haystack ) ;
2005-10-20 19:25:54 +00:00
start = part ? haystack_copy : haystack_copy + found_offset ;
2006-08-31 14:19:33 +00:00
end = part ? haystack_copy + found_offset : ( haystack_copy + Z_STRLEN_PP ( haystack ) ) ;
2006-01-17 12:18:53 +00:00
RETVAL_STRINGL ( ( char * ) start , ( char * ) end - ( char * ) start , 1 ) ;
2005-08-09 20:49:19 +00:00
}
1999-04-17 00:37:12 +00:00
} else {
2001-09-27 00:21:21 +00:00
RETVAL_FALSE ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) ! = IS_UNICODE ) {
2005-10-20 19:25:54 +00:00
efree ( haystack_copy ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string strstr(string haystack, string needle[, bool part]) U
2001-09-04 10:44:28 +00:00
Finds first occurrence of a string within another */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strstr )
1999-04-17 00:37:12 +00:00
{
2006-10-02 19:18:14 +00:00
zstr haystack ;
2005-12-09 13:41:06 +00:00
int haystack_len ;
2005-08-11 23:36:07 +00:00
zend_uchar haystack_type ;
zval * * needle ;
void * found = NULL ;
char needle_char [ 2 ] ;
UChar u_needle_char [ 3 ] ;
2006-03-02 13:12:45 +00:00
int n_len = 0 ;
2005-08-11 23:36:07 +00:00
size_t found_offset ;
2005-08-09 20:49:19 +00:00
zend_bool part = 0 ;
2003-02-08 15:26:17 +00:00
2005-08-11 23:36:07 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " tZ|b " , & haystack , & haystack_len , & haystack_type , & needle , & part ) = = FAILURE ) {
2005-08-09 20:49:19 +00:00
return ;
}
1999-04-17 00:37:12 +00:00
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_PP ( needle ) = = IS_STRING | | Z_TYPE_PP ( needle ) = = IS_UNICODE ) {
2005-08-11 23:36:07 +00:00
if ( ! Z_STRLEN_PP ( needle ) ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Empty delimiter " ) ;
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
2001-09-04 06:18:11 +00:00
2005-08-11 23:36:07 +00:00
/* haystack type determines the needle type */
if ( haystack_type = = IS_UNICODE ) {
convert_to_unicode_ex ( needle ) ;
2006-10-02 19:18:14 +00:00
found = zend_u_memnstr ( haystack . u ,
2005-08-11 23:36:07 +00:00
Z_USTRVAL_PP ( needle ) ,
Z_USTRLEN_PP ( needle ) ,
2006-10-02 19:18:14 +00:00
haystack . u + haystack_len ) ;
2005-08-11 23:36:07 +00:00
} else {
convert_to_string_ex ( needle ) ;
2006-10-02 19:18:14 +00:00
found = php_memnstr ( haystack . s ,
2005-08-11 23:36:07 +00:00
Z_STRVAL_PP ( needle ) ,
Z_STRLEN_PP ( needle ) ,
2006-10-02 19:18:14 +00:00
haystack . s + haystack_len ) ;
2005-08-11 23:36:07 +00:00
}
2002-09-11 14:40:52 +00:00
} else {
2005-08-11 23:36:07 +00:00
convert_to_long_ex ( needle ) ;
if ( haystack_type = = IS_UNICODE ) {
if ( Z_LVAL_PP ( needle ) < 0 | | Z_LVAL_PP ( needle ) > 0x10FFFF ) {
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
1999-04-17 00:37:12 +00:00
2006-10-02 19:18:14 +00:00
n_len = zend_codepoint_to_uchar ( ( UChar32 ) Z_LVAL_PP ( needle ) , u_needle_char ) ;
u_needle_char [ n_len ] = 0 ;
found = zend_u_memnstr ( haystack . u ,
2005-08-11 23:36:07 +00:00
u_needle_char ,
n_len ,
2006-10-02 19:18:14 +00:00
haystack . u + haystack_len ) ;
2005-08-11 23:36:07 +00:00
} else {
needle_char [ 0 ] = ( char ) Z_LVAL_PP ( needle ) ;
needle_char [ 1 ] = 0 ;
2006-10-02 19:18:14 +00:00
found = php_memnstr ( haystack . s ,
2005-08-11 23:36:07 +00:00
needle_char ,
1 ,
2006-10-02 19:18:14 +00:00
haystack . s + haystack_len ) ;
2005-08-11 23:36:07 +00:00
}
2001-09-04 06:18:11 +00:00
}
1999-04-17 00:37:12 +00:00
if ( found ) {
2005-08-11 23:36:07 +00:00
switch ( haystack_type ) {
case IS_UNICODE :
2006-10-02 19:18:14 +00:00
found_offset = ( UChar * ) found - haystack . u ;
2005-08-11 23:36:07 +00:00
if ( part ) {
2005-08-12 16:46:38 +00:00
UChar * ret ;
2005-08-11 23:36:07 +00:00
ret = eumalloc ( found_offset + 1 ) ;
2006-10-02 19:18:14 +00:00
u_strncpy ( ret , haystack . u , found_offset ) ;
2005-08-11 23:36:07 +00:00
ret [ found_offset ] = ' \0 ' ;
RETURN_UNICODEL ( ret , found_offset , 0 ) ;
} else {
RETURN_UNICODEL ( found , haystack_len - found_offset , 1 ) ;
}
break ;
case IS_STRING :
2006-10-02 19:18:14 +00:00
found_offset = ( char * ) found - haystack . s ;
2005-08-11 23:36:07 +00:00
if ( part ) {
char * ret ;
ret = emalloc ( found_offset + 1 ) ;
2006-10-02 19:18:14 +00:00
strncpy ( ret , haystack . s , found_offset ) ;
2005-08-11 23:36:07 +00:00
ret [ found_offset ] = ' \0 ' ;
RETURN_STRINGL ( ret , found_offset , 0 ) ;
} else {
RETURN_STRINGL ( found , haystack_len - found_offset , 1 ) ;
}
break ;
2005-08-09 20:49:19 +00:00
}
1999-04-17 00:37:12 +00:00
} else {
2001-09-04 06:18:11 +00:00
RETURN_FALSE ;
1999-04-17 00:37:12 +00:00
}
}
/* }}} */
2006-08-02 21:53:43 +00:00
/* {{{ proto string strchr(string haystack, string needle[, bool part]) U
1999-08-09 20:52:58 +00:00
An alias for strstr */
/* }}} */
2006-03-06 21:49:21 +00:00
/* {{{ proto int strpos(string haystack, mixed needle [, int offset]) U
2001-09-04 10:44:28 +00:00
Finds position of first occurrence of a string within another */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strpos )
1999-04-17 00:37:12 +00:00
{
2006-10-02 19:18:14 +00:00
zstr haystack ;
2005-12-09 13:41:06 +00:00
int haystack_len ;
2005-08-11 23:36:07 +00:00
zend_uchar haystack_type ;
zval * * needle ;
2006-03-01 11:19:35 +00:00
long offset = 0 ;
2005-08-11 23:36:07 +00:00
void * found = NULL ;
char needle_char [ 2 ] ;
UChar u_needle_char [ 3 ] ;
2006-03-02 13:12:45 +00:00
int n_len = 0 ;
2006-10-02 19:18:14 +00:00
int32_t cu_offset = 0 ;
1999-12-06 17:37:59 +00:00
2005-08-11 23:36:07 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " tZ|l " , & haystack ,
& haystack_len , & haystack_type , & needle , & offset ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2005-08-11 23:36:07 +00:00
/*
2006-10-02 19:18:14 +00:00
* Unicode note : it ' s okay to not convert offset to code unit offset here .
2005-08-11 23:36:07 +00:00
* We ' ll just do a rough check that the offset does not exceed length in
* code units , and leave the rest to zend_u_memnstr ( ) .
*/
if ( offset < 0 | | offset > haystack_len ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset not contained in string " ) ;
2001-09-04 06:18:11 +00:00
RETURN_FALSE ;
}
1999-12-06 17:37:59 +00:00
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_PP ( needle ) = = IS_STRING | | Z_TYPE_PP ( needle ) = = IS_UNICODE ) {
2001-09-04 06:18:11 +00:00
if ( ! Z_STRLEN_PP ( needle ) ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Empty delimiter " ) ;
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
1999-12-06 17:37:59 +00:00
2005-08-11 23:36:07 +00:00
/* haystack type determines the needle type */
if ( haystack_type = = IS_UNICODE ) {
convert_to_unicode_ex ( needle ) ;
2006-10-02 19:18:14 +00:00
/* calculate code unit offset */
U16_FWD_N ( haystack . u , cu_offset , haystack_len , offset ) ;
found = zend_u_memnstr ( haystack . u + cu_offset ,
2005-08-11 23:36:07 +00:00
Z_USTRVAL_PP ( needle ) ,
Z_USTRLEN_PP ( needle ) ,
2006-10-02 19:18:14 +00:00
haystack . u + haystack_len ) ;
2005-08-11 23:36:07 +00:00
} else {
convert_to_string_ex ( needle ) ;
2006-10-02 19:18:14 +00:00
found = php_memnstr ( haystack . s + offset ,
2005-08-11 23:36:07 +00:00
Z_STRVAL_PP ( needle ) ,
Z_STRLEN_PP ( needle ) ,
2006-10-02 19:18:14 +00:00
haystack . s + haystack_len ) ;
2005-08-11 23:36:07 +00:00
}
2002-09-11 14:40:52 +00:00
} else {
1999-09-25 11:55:42 +00:00
convert_to_long_ex ( needle ) ;
2005-08-11 23:36:07 +00:00
if ( haystack_type = = IS_UNICODE ) {
if ( Z_LVAL_PP ( needle ) < 0 | | Z_LVAL_PP ( needle ) > 0x10FFFF ) {
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
2006-01-25 00:02:23 +00:00
n_len + = zend_codepoint_to_uchar ( Z_LVAL_PP ( needle ) , u_needle_char ) ;
u_needle_char [ n_len ] = 0 ;
1999-12-06 17:37:59 +00:00
2006-10-02 19:18:14 +00:00
/* calculate code unit offset */
U16_FWD_N ( haystack . u , cu_offset , haystack_len , offset ) ;
found = zend_u_memnstr ( haystack . u + cu_offset ,
2005-08-11 23:36:07 +00:00
u_needle_char ,
n_len ,
2006-10-02 19:18:14 +00:00
haystack . u + haystack_len ) ;
2005-08-11 23:36:07 +00:00
} else {
needle_char [ 0 ] = ( char ) Z_LVAL_PP ( needle ) ;
needle_char [ 1 ] = 0 ;
2006-10-02 19:18:14 +00:00
found = php_memnstr ( haystack . s + offset ,
2005-08-11 23:36:07 +00:00
needle_char ,
1 ,
2006-10-02 19:18:14 +00:00
haystack . s + haystack_len ) ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
}
if ( found ) {
2005-08-11 23:36:07 +00:00
if ( haystack_type = = IS_UNICODE ) {
2006-10-02 19:18:14 +00:00
/* Simple subtraction will not suffice, since there may be
supplementary codepoints . We count how many codepoints there are
between the starting offset and the found location and add them
to the starting codepoint offset . */
RETURN_LONG ( offset + u_countChar32 ( haystack . u + cu_offset ,
( UChar * ) found - ( haystack . u + cu_offset ) ) ) ;
2005-08-11 23:36:07 +00:00
} else {
2006-10-02 19:18:14 +00:00
RETURN_LONG ( ( char * ) found - haystack . s ) ;
2005-08-11 23:36:07 +00:00
}
1999-04-17 00:37:12 +00:00
} else {
2001-09-04 06:18:11 +00:00
RETURN_FALSE ;
1999-04-17 00:37:12 +00:00
}
}
/* }}} */
2006-10-02 16:52:22 +00:00
/* {{{ proto int stripos(string haystack, string needle [, int offset]) U
2003-01-11 17:52:38 +00:00
Finds position of first occurrence of a string within another , case insensitive */
PHP_FUNCTION ( stripos )
{
2006-08-31 14:19:33 +00:00
zval * * haystack , * * needle ;
2003-01-11 17:52:38 +00:00
long offset = 0 ;
2006-03-02 13:12:45 +00:00
int haystack_len , needle_len = 0 ;
2005-10-17 19:50:13 +00:00
zend_uchar str_type ;
2006-10-02 16:52:22 +00:00
void * haystack_dup = NULL , * needle_dup = NULL ;
2003-01-11 17:52:38 +00:00
char needle_char [ 2 ] ;
2006-07-13 17:55:50 +00:00
char c = 0 ;
2006-10-02 19:18:14 +00:00
UChar u_needle_char [ 3 ] ;
2005-10-17 19:50:13 +00:00
void * found = NULL ;
2006-10-02 16:52:22 +00:00
int cu_offset = 0 ;
2003-01-11 17:52:38 +00:00
2006-08-31 14:19:33 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ZZ|l " , & haystack , & needle , & offset ) = = FAILURE ) {
2003-01-11 17:52:38 +00:00
return ;
}
2003-02-08 15:26:17 +00:00
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) ! = IS_UNICODE & & Z_TYPE_PP ( haystack ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( haystack ) ;
2005-10-17 19:50:13 +00:00
}
2006-10-02 19:18:14 +00:00
/*
* Unicode note : it ' s okay to not convert offset to code unit offset here .
* We ' ll just do a rough check that the offset does not exceed length in
* code units , and leave the rest to zend_u_memnstr ( ) .
*/
2006-08-31 14:19:33 +00:00
if ( offset < 0 | | offset > Z_UNILEN_PP ( haystack ) ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset not contained in string " ) ;
2003-01-11 17:52:38 +00:00
RETURN_FALSE ;
}
2006-08-31 14:19:33 +00:00
haystack_len = Z_UNILEN_PP ( haystack ) ;
2006-07-12 12:33:04 +00:00
if ( haystack_len = = 0 ) {
RETURN_FALSE ;
}
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( needle ) = = IS_UNICODE | | Z_TYPE_PP ( needle ) = = IS_STRING ) {
if ( ! Z_UNILEN_PP ( needle ) | | Z_UNILEN_PP ( needle ) > haystack_len ) {
2005-10-17 19:50:13 +00:00
RETURN_FALSE ;
}
2006-10-02 16:52:22 +00:00
/* convert both strings to the same type */
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) ! = Z_TYPE_PP ( needle ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_PP ( haystack ) , Z_TYPE_PP ( needle ) ) ;
convert_to_explicit_type_ex ( haystack , str_type ) ;
convert_to_explicit_type_ex ( needle , str_type ) ;
2005-10-17 19:50:13 +00:00
}
2006-08-31 14:19:33 +00:00
needle_len = Z_UNILEN_PP ( needle ) ;
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
2006-10-02 19:18:14 +00:00
/* calculate code unit offset */
2006-10-02 16:52:22 +00:00
U16_FWD_N ( Z_USTRVAL_PP ( haystack ) , cu_offset , haystack_len , offset ) ;
2008-09-14 14:56:34 +00:00
found = php_u_stristr ( Z_USTRVAL_PP ( haystack ) + cu_offset , Z_USTRVAL_PP ( needle ) , haystack_len - cu_offset , needle_len , 1 TSRMLS_CC ) ;
2005-10-17 19:50:13 +00:00
} else {
2006-08-31 14:19:33 +00:00
haystack_dup = estrndup ( Z_STRVAL_PP ( haystack ) , haystack_len ) ;
2005-10-17 19:50:13 +00:00
php_strtolower ( ( char * ) haystack_dup , haystack_len ) ;
2006-08-31 14:19:33 +00:00
needle_dup = estrndup ( Z_STRVAL_PP ( needle ) , needle_len ) ;
php_strtolower ( ( char * ) needle_dup , Z_STRLEN_PP ( needle ) ) ;
2005-10-17 19:50:13 +00:00
found = php_memnstr ( ( char * ) haystack_dup + offset ,
( char * ) needle_dup , needle_len ,
( char * ) haystack_dup + haystack_len ) ;
}
2003-01-11 17:52:38 +00:00
} else {
2006-10-02 19:18:14 +00:00
convert_to_long_ex ( needle ) ;
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
2006-10-02 19:18:14 +00:00
if ( Z_LVAL_PP ( needle ) < 0 | | Z_LVAL_PP ( needle ) > 0x10FFFF ) {
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
needle_len = zend_codepoint_to_uchar ( ( UChar32 ) Z_LVAL_PP ( needle ) , u_needle_char ) ;
2006-10-02 16:52:22 +00:00
u_needle_char [ needle_len ] = 0 ;
2006-10-02 19:18:14 +00:00
/* calculate code unit offset */
U16_FWD_N ( Z_USTRVAL_PP ( haystack ) , cu_offset , haystack_len , offset ) ;
2006-10-02 16:52:22 +00:00
found = php_u_stristr ( Z_USTRVAL_PP ( haystack ) + cu_offset ,
2008-09-14 14:56:34 +00:00
u_needle_char , haystack_len - cu_offset , needle_len , 1 TSRMLS_CC ) ;
2005-10-17 19:50:13 +00:00
} else {
2006-10-02 19:18:14 +00:00
c = tolower ( ( char ) Z_LVAL_PP ( needle ) ) ;
2005-10-17 19:50:13 +00:00
needle_char [ 0 ] = c ;
needle_char [ 1 ] = ' \0 ' ;
2006-08-31 14:19:33 +00:00
haystack_dup = estrndup ( Z_STRVAL_PP ( haystack ) , haystack_len ) ;
2005-10-17 19:50:13 +00:00
php_strtolower ( ( char * ) haystack_dup , haystack_len ) ;
2006-07-16 15:56:00 +00:00
found = php_memnstr ( ( char * ) haystack_dup + offset ,
( char * ) needle_char ,
sizeof ( needle_char ) - 1 ,
2005-10-17 19:50:13 +00:00
( char * ) haystack_dup + haystack_len ) ;
}
2003-01-11 17:52:38 +00:00
}
2006-10-02 16:52:22 +00:00
if ( haystack_dup ) {
efree ( haystack_dup ) ;
}
2003-01-11 17:52:38 +00:00
if ( needle_dup ) {
efree ( needle_dup ) ;
}
if ( found ) {
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( haystack ) = = IS_UNICODE ) {
2006-10-02 16:52:22 +00:00
/* Simple subtraction will not suffice, since there may be
supplementary codepoints . We count how many codepoints there are
between the starting offset and the found location and add them
to the starting codepoint offset . */
RETURN_LONG ( offset + u_countChar32 ( Z_USTRVAL_PP ( haystack ) + cu_offset ,
( UChar * ) found - ( Z_USTRVAL_PP ( haystack ) + cu_offset ) ) ) ;
2005-10-17 19:50:13 +00:00
} else {
RETURN_LONG ( ( char * ) found - ( char * ) haystack_dup ) ;
}
2003-01-11 17:52:38 +00:00
} else {
RETURN_FALSE ;
}
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto int strrpos(string haystack, string needle [, int offset]) U
2003-04-12 07:36:22 +00:00
Finds position of last occurrence of a string within another string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strrpos )
1999-04-17 00:37:12 +00:00
{
2006-08-31 14:19:33 +00:00
zval * * zhaystack , * * zneedle ;
2006-02-21 20:12:43 +00:00
zstr haystack , needle ;
2006-03-02 13:12:45 +00:00
int haystack_len , needle_len = 0 ;
2005-10-17 17:07:44 +00:00
zend_uchar str_type ;
2004-06-15 22:38:18 +00:00
long offset = 0 ;
2003-12-03 01:11:36 +00:00
char * p , * e , ord_needle [ 2 ] ;
2005-10-17 17:07:44 +00:00
UChar * pos , * u_p , * u_e , u_ord_needle [ 3 ] ;
2006-10-02 19:18:14 +00:00
int cu_offset = 0 ;
2003-01-11 17:52:38 +00:00
2006-08-31 14:19:33 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ZZ|l " ,
2005-10-17 17:07:44 +00:00
& zhaystack , & zneedle , & offset ) = = FAILURE ) {
2003-04-12 07:36:22 +00:00
RETURN_FALSE ;
2003-01-11 17:52:38 +00:00
}
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( zhaystack ) ! = IS_UNICODE & & Z_TYPE_PP ( zhaystack ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( zhaystack ) ;
2005-10-17 17:07:44 +00:00
}
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( zneedle ) = = IS_UNICODE | | Z_TYPE_PP ( zneedle ) = = IS_STRING ) {
if ( Z_TYPE_PP ( zneedle ) ! = Z_TYPE_PP ( zhaystack ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_PP ( zhaystack ) , Z_TYPE_PP ( zneedle ) ) ;
convert_to_explicit_type_ex ( zhaystack , str_type ) ;
convert_to_explicit_type_ex ( zneedle , str_type ) ;
2005-10-17 17:07:44 +00:00
}
2006-08-31 14:19:33 +00:00
needle = Z_UNIVAL_PP ( zneedle ) ;
needle_len = Z_UNILEN_PP ( zneedle ) ;
2003-12-03 01:11:36 +00:00
} else {
2006-10-03 18:13:36 +00:00
convert_to_long_ex ( zneedle ) ;
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( zhaystack ) = = IS_UNICODE ) {
if ( Z_LVAL_PP ( zneedle ) < 0 | | Z_LVAL_PP ( zneedle ) > 0x10FFFF ) {
2005-10-17 17:07:44 +00:00
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
2006-10-02 19:18:14 +00:00
needle_len = zend_codepoint_to_uchar ( ( UChar32 ) Z_LVAL_PP ( zneedle ) , u_ord_needle ) ;
u_ord_needle [ needle_len ] = 0 ;
2006-02-21 20:12:43 +00:00
needle . u = u_ord_needle ;
2005-10-17 17:07:44 +00:00
} else {
2006-08-31 14:19:33 +00:00
ord_needle [ 0 ] = ( char ) ( Z_LVAL_PP ( zneedle ) & 0xFF ) ;
2005-10-17 17:07:44 +00:00
ord_needle [ 1 ] = ' \0 ' ;
2006-02-21 20:12:43 +00:00
needle . s = ord_needle ;
2005-10-17 17:07:44 +00:00
needle_len = 1 ;
}
2003-12-03 01:11:36 +00:00
}
2006-08-31 14:19:33 +00:00
haystack = Z_UNIVAL_PP ( zhaystack ) ;
haystack_len = Z_UNILEN_PP ( zhaystack ) ;
2003-12-03 01:11:36 +00:00
2006-10-02 19:18:14 +00:00
if ( ( haystack_len = = 0 ) | | ( needle_len = = 0 ) | | needle_len > haystack_len ) {
2003-04-12 20:04:06 +00:00
RETURN_FALSE ;
}
2006-08-31 14:19:33 +00:00
if ( Z_TYPE_PP ( zhaystack ) = = IS_UNICODE ) {
2005-10-17 17:07:44 +00:00
if ( offset > = 0 ) {
2006-10-02 19:18:14 +00:00
U16_FWD_N ( haystack . u , cu_offset , haystack_len , offset ) ;
if ( cu_offset > haystack_len - needle_len ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-02 19:18:14 +00:00
RETURN_FALSE ;
}
u_p = haystack . u + cu_offset ;
2006-02-21 20:12:43 +00:00
u_e = haystack . u + haystack_len - needle_len ;
2005-10-17 17:07:44 +00:00
} else {
2006-02-21 20:12:43 +00:00
u_p = haystack . u ;
2008-07-22 01:05:55 +00:00
if ( - offset > haystack_len | | offset < - INT_MAX ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-02 19:18:14 +00:00
RETURN_FALSE ;
2005-10-17 17:07:44 +00:00
} else {
2006-10-02 19:18:14 +00:00
cu_offset = haystack_len ;
U16_BACK_N ( haystack . u , 0 , cu_offset , - offset ) ;
if ( cu_offset = = 0 ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-02 19:18:14 +00:00
RETURN_FALSE ;
}
if ( needle_len > haystack_len - cu_offset ) {
u_e = haystack . u + haystack_len - needle_len ;
} else {
u_e = haystack . u + cu_offset ;
}
2005-10-17 17:07:44 +00:00
}
}
2006-02-21 20:12:43 +00:00
pos = u_strFindLast ( u_p , u_e - u_p + needle_len , needle . u , needle_len ) ;
2005-10-17 17:07:44 +00:00
if ( pos ) {
2006-10-02 19:18:14 +00:00
if ( offset > 0 ) {
RETURN_LONG ( offset + u_countChar32 ( u_p , ( UChar * ) pos - u_p ) ) ;
} else {
RETURN_LONG ( u_countChar32 ( haystack . u , ( UChar * ) pos - haystack . u ) ) ;
}
2005-10-17 17:07:44 +00:00
} else {
RETURN_FALSE ;
}
2003-01-11 17:52:38 +00:00
} else {
2005-10-17 17:07:44 +00:00
if ( offset > = 0 ) {
2006-10-02 19:18:14 +00:00
if ( offset > haystack_len ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-02 19:18:14 +00:00
RETURN_FALSE ;
}
2006-02-21 20:12:43 +00:00
p = haystack . s + offset ;
e = haystack . s + haystack_len - needle_len ;
2003-04-12 07:36:22 +00:00
} else {
2008-07-22 01:05:55 +00:00
if ( - offset > haystack_len | | offset < - INT_MAX ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-02 19:18:14 +00:00
RETURN_FALSE ;
}
p = haystack . s ;
if ( needle_len > - offset ) {
2006-02-21 20:12:43 +00:00
e = haystack . s + haystack_len - needle_len ;
2005-10-17 17:07:44 +00:00
} else {
2006-02-21 20:12:43 +00:00
e = haystack . s + haystack_len + offset ;
2005-10-17 17:07:44 +00:00
}
}
if ( needle_len = = 1 ) {
/* Single character search can shortcut memcmps */
while ( e > = p ) {
2006-02-21 20:12:43 +00:00
if ( * e = = * needle . s ) {
2005-10-17 17:07:44 +00:00
RETURN_LONG ( e - p + ( offset > 0 ? offset : 0 ) ) ;
}
e - - ;
}
RETURN_FALSE ;
2003-04-12 07:36:22 +00:00
}
2003-01-11 17:52:38 +00:00
2003-12-03 01:31:56 +00:00
while ( e > = p ) {
2006-02-21 20:12:43 +00:00
if ( memcmp ( e , needle . s , needle_len ) = = 0 ) {
2003-12-03 01:31:56 +00:00
RETURN_LONG ( e - p + ( offset > 0 ? offset : 0 ) ) ;
}
e - - ;
}
2003-01-11 17:52:38 +00:00
}
2003-04-12 07:36:22 +00:00
RETURN_FALSE ;
2003-01-11 17:52:38 +00:00
}
/* }}} */
2006-10-03 18:13:36 +00:00
/* {{{ proto int strripos(string haystack, string needle [, int offset]) U
2003-04-12 07:36:22 +00:00
Finds position of last occurrence of a string within another string */
2003-01-11 17:52:38 +00:00
PHP_FUNCTION ( strripos )
{
2006-10-03 18:13:36 +00:00
zstr haystack , needle ;
2006-08-31 14:19:33 +00:00
zval * * zneedle ;
2004-02-25 20:16:27 +00:00
int needle_len , haystack_len ;
2006-10-03 18:13:36 +00:00
zend_uchar haystack_type ;
2004-02-25 20:16:27 +00:00
long offset = 0 ;
2006-10-03 18:13:36 +00:00
char * p , * e , needle_char [ 2 ] ;
UChar * u_p , * u_e , * pos ;
UChar u_needle_char [ 3 ] ;
2003-04-12 07:36:22 +00:00
char * needle_dup , * haystack_dup ;
2006-10-03 18:13:36 +00:00
int cu_offset = 0 ;
1999-04-17 00:37:12 +00:00
2006-10-03 18:13:36 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " tZ|l " , & haystack ,
& haystack_len , & haystack_type , & zneedle , & offset ) = = FAILURE ) {
2003-04-12 07:36:22 +00:00
RETURN_FALSE ;
2003-01-11 17:52:38 +00:00
}
2006-10-03 18:13:36 +00:00
if ( Z_TYPE_PP ( zneedle ) = = IS_STRING | | Z_TYPE_PP ( zneedle ) = = IS_UNICODE ) {
convert_to_explicit_type_ex ( zneedle , haystack_type ) ;
needle = Z_UNIVAL_PP ( zneedle ) ;
needle_len = Z_UNILEN_PP ( zneedle ) ;
2003-12-03 01:11:36 +00:00
} else {
2006-08-31 14:19:33 +00:00
convert_to_long_ex ( zneedle ) ;
2006-10-03 18:13:36 +00:00
if ( haystack_type = = IS_UNICODE ) {
if ( Z_LVAL_PP ( zneedle ) < 0 | | Z_LVAL_PP ( zneedle ) > 0x10FFFF ) {
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
needle_len = zend_codepoint_to_uchar ( ( UChar32 ) Z_LVAL_PP ( zneedle ) , u_needle_char ) ;
u_needle_char [ needle_len ] = 0 ;
needle . u = u_needle_char ;
} else {
needle_char [ 0 ] = ( char ) ( Z_LVAL_PP ( zneedle ) & 0xFF ) ;
needle_char [ 1 ] = ' \0 ' ;
needle . s = needle_char ;
needle_len = 1 ;
}
2003-12-03 01:11:36 +00:00
}
2006-10-03 18:13:36 +00:00
if ( ( haystack_len = = 0 ) | | ( needle_len = = 0 ) | | needle_len > haystack_len ) {
2003-04-12 20:04:06 +00:00
RETURN_FALSE ;
}
2006-10-03 18:13:36 +00:00
if ( haystack_type = = IS_UNICODE ) {
2003-12-03 01:31:56 +00:00
if ( offset > = 0 ) {
2006-10-03 18:13:36 +00:00
U16_FWD_N ( haystack . u , cu_offset , haystack_len , offset ) ;
2009-01-17 20:36:22 +00:00
if ( cu_offset > haystack_len ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
}
u_p = haystack . u + cu_offset ;
u_e = haystack . u + haystack_len - needle_len ;
2003-12-03 01:31:56 +00:00
} else {
2006-10-03 18:13:36 +00:00
u_p = haystack . u ;
2007-06-06 21:55:18 +00:00
if ( - offset > haystack_len | | offset < - INT_MAX ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
2004-05-06 16:11:50 +00:00
} else {
2006-10-03 18:13:36 +00:00
cu_offset = haystack_len ;
U16_BACK_N ( haystack . u , 0 , cu_offset , - offset ) ;
if ( cu_offset = = 0 ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
}
if ( needle_len > haystack_len - cu_offset ) {
u_e = haystack . u + haystack_len - needle_len ;
} else {
u_e = haystack . u + cu_offset ;
}
2004-05-06 16:11:50 +00:00
}
2003-12-03 01:31:56 +00:00
}
2006-10-03 18:13:36 +00:00
pos = php_u_stristr ( u_p , needle . u , u_e - u_p + needle_len , needle_len , 0 TSRMLS_CC ) ;
if ( pos ) {
if ( offset > 0 ) {
RETURN_LONG ( offset + u_countChar32 ( u_p , ( UChar * ) pos - u_p ) ) ;
} else {
RETURN_LONG ( u_countChar32 ( haystack . u , ( UChar * ) pos - haystack . u ) ) ;
2003-12-03 01:31:56 +00:00
}
2006-10-03 18:13:36 +00:00
} else {
RETURN_FALSE ;
}
} else {
if ( needle_len = = 1 ) {
/* Single character search can shortcut memcmps
Can also avoid tolower emallocs */
if ( offset > = 0 ) {
if ( offset > haystack_len ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
}
p = haystack . s + offset ;
e = haystack . s + haystack_len - 1 ;
} else {
p = haystack . s ;
2007-06-06 21:55:18 +00:00
if ( - offset > haystack_len | | offset < INT_MAX ) {
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
} else {
e = haystack . s + haystack_len + offset ;
}
}
/* Borrow that needle_char buffer to avoid repeatedly tolower()ing needle */
* needle_char = tolower ( * needle . s ) ;
while ( e > = p ) {
if ( tolower ( * e ) = = * needle_char ) {
RETURN_LONG ( e - p + ( offset > 0 ? offset : 0 ) ) ;
}
e - - ;
}
RETURN_FALSE ;
2003-12-03 01:31:56 +00:00
}
2006-10-03 18:13:36 +00:00
needle_dup = estrndup ( needle . s , needle_len ) ;
php_strtolower ( needle_dup , needle_len ) ;
haystack_dup = estrndup ( haystack . s , haystack_len ) ;
php_strtolower ( haystack_dup , haystack_len ) ;
2003-01-11 17:52:38 +00:00
2006-10-03 18:13:36 +00:00
if ( offset > = 0 ) {
if ( offset > haystack_len ) {
efree ( haystack_dup ) ;
efree ( needle_dup ) ;
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
}
p = haystack_dup + offset ;
2003-04-12 07:36:22 +00:00
e = haystack_dup + haystack_len - needle_len ;
} else {
2007-06-06 21:55:18 +00:00
if ( - offset > haystack_len | | offset < - INT_MAX ) {
2006-10-03 18:13:36 +00:00
efree ( haystack_dup ) ;
efree ( needle_dup ) ;
2009-02-14 06:59:36 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset is greater than the length of haystack string " ) ;
2006-10-03 18:13:36 +00:00
RETURN_FALSE ;
}
p = haystack_dup ;
if ( needle_len > - offset ) {
e = haystack_dup + haystack_len - needle_len ;
} else {
e = haystack_dup + haystack_len + offset ;
}
2003-04-12 07:36:22 +00:00
}
1999-04-17 00:37:12 +00:00
2006-10-03 18:13:36 +00:00
while ( e > = p ) {
if ( memcmp ( e , needle_dup , needle_len ) = = 0 ) {
efree ( haystack_dup ) ;
efree ( needle_dup ) ;
RETURN_LONG ( e - p + ( offset > 0 ? offset : 0 ) ) ;
}
e - - ;
2003-04-12 07:36:22 +00:00
}
2003-01-11 17:52:38 +00:00
2006-10-03 18:13:36 +00:00
efree ( haystack_dup ) ;
efree ( needle_dup ) ;
RETURN_FALSE ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string strrchr(string haystack, string needle) U
2001-09-04 10:44:28 +00:00
Finds the last occurrence of a character in a string within another */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strrchr )
1999-04-17 00:37:12 +00:00
{
2005-10-24 14:35:02 +00:00
zval * haystack , * needle ;
zend_uchar str_type ;
UChar32 ch ;
void * found = NULL ;
2006-03-02 13:12:45 +00:00
int found_offset ;
2005-10-24 14:35:02 +00:00
2006-08-04 23:20:04 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " z/z/ " , & haystack , & needle ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_P ( haystack ) ! = IS_UNICODE | | Z_TYPE_P ( haystack ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode ( haystack ) ;
2005-10-24 14:35:02 +00:00
}
1999-04-17 00:37:12 +00:00
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_P ( needle ) = = IS_UNICODE | | Z_TYPE_P ( needle ) = = IS_STRING ) {
2005-10-24 14:35:02 +00:00
if ( Z_TYPE_P ( needle ) ! = Z_TYPE_P ( haystack ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_P ( haystack ) , Z_TYPE_P ( needle ) ) ;
2006-01-17 12:18:53 +00:00
convert_to_explicit_type ( haystack , str_type ) ;
convert_to_explicit_type ( needle , str_type ) ;
2005-10-24 14:35:02 +00:00
}
2006-08-04 23:20:04 +00:00
if ( Z_USTRLEN_P ( needle ) = = 0 ) {
RETURN_FALSE ;
}
2005-10-24 14:35:02 +00:00
if ( Z_TYPE_P ( haystack ) = = IS_UNICODE ) {
2006-08-04 23:20:04 +00:00
ch = zend_get_codepoint_at ( Z_USTRVAL_P ( needle ) , Z_USTRLEN_P ( needle ) , 0 ) ;
found = u_memrchr32 ( Z_USTRVAL_P ( haystack ) , ch , Z_USTRLEN_P ( haystack ) ) ;
2005-10-24 14:35:02 +00:00
} else {
2006-08-08 09:48:08 +00:00
found = zend_memrchr ( Z_STRVAL_P ( haystack ) , * Z_STRVAL_P ( needle ) , Z_STRLEN_P ( haystack ) ) ;
2005-10-24 14:35:02 +00:00
}
2002-10-10 18:41:24 +00:00
} else {
2005-10-24 14:35:02 +00:00
convert_to_long ( needle ) ;
if ( Z_TYPE_P ( haystack ) = = IS_UNICODE ) {
2006-08-04 23:20:04 +00:00
UChar32 ch = ( UChar32 ) Z_LVAL_P ( needle ) ;
if ( ch < 0 | | ch > 0x10FFFF ) {
2005-10-24 14:35:02 +00:00
php_error ( E_WARNING , " Needle argument codepoint value out of range (0 - 0x10FFFF) " ) ;
RETURN_FALSE ;
}
2006-08-04 23:20:04 +00:00
found = u_memrchr32 ( Z_USTRVAL_P ( haystack ) , ch , Z_USTRLEN_P ( haystack ) ) ;
2005-10-24 14:35:02 +00:00
} else {
2006-08-08 09:48:08 +00:00
found = zend_memrchr ( Z_STRVAL_P ( haystack ) , ( char ) Z_LVAL_P ( needle ) , Z_STRLEN_P ( haystack ) ) ;
2005-10-24 14:35:02 +00:00
}
1999-04-17 00:37:12 +00:00
}
if ( found ) {
2005-10-24 14:35:02 +00:00
if ( Z_TYPE_P ( haystack ) = = IS_UNICODE ) {
found_offset = ( UChar * ) found - Z_USTRVAL_P ( haystack ) ;
RETURN_UNICODEL ( ( UChar * ) found , Z_USTRLEN_P ( haystack ) - found_offset , 1 ) ;
} else {
found_offset = ( char * ) found - Z_STRVAL_P ( haystack ) ;
2006-01-17 12:18:53 +00:00
RETURN_STRINGL ( ( char * ) found , Z_STRLEN_P ( haystack ) - found_offset , 1 ) ;
2005-10-24 14:35:02 +00:00
}
1999-04-17 00:37:12 +00:00
} else {
2001-09-04 06:18:11 +00:00
RETURN_FALSE ;
1999-04-17 00:37:12 +00:00
}
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_chunk_split
*/
2006-08-14 20:43:23 +00:00
static char * php_chunk_split ( char * src , int srclen , char * end , int endlen , int chunklen , int * destlen , zend_uchar str_type )
1999-04-17 00:37:12 +00:00
{
char * dest ;
char * p , * q ;
int chunks ; /* complete chunks! */
int restlen ;
2006-08-14 20:43:23 +00:00
int charsize = sizeof ( char ) ;
2007-06-06 20:06:43 +00:00
int out_len ;
2006-08-14 20:43:23 +00:00
if ( str_type = = IS_UNICODE ) {
charsize = sizeof ( UChar ) ;
}
1999-04-17 00:37:12 +00:00
chunks = srclen / chunklen ;
restlen = srclen - chunks * chunklen ; /* srclen % chunklen */
2007-06-06 20:06:43 +00:00
if ( chunks > INT_MAX - 1 ) {
return NULL ;
}
2007-06-03 18:53:51 +00:00
out_len = chunks + 1 ;
2007-06-06 20:06:43 +00:00
if ( endlen ! = 0 & & out_len > INT_MAX / endlen ) {
return NULL ;
}
2007-06-03 18:53:51 +00:00
out_len * = endlen ;
2007-06-06 20:06:43 +00:00
if ( out_len > INT_MAX - srclen - 1 ) {
return NULL ;
}
2007-06-03 18:53:51 +00:00
out_len + = srclen + 1 ;
2007-05-30 00:38:00 +00:00
2007-06-06 20:06:43 +00:00
if ( out_len > INT_MAX / charsize ) {
2007-05-30 00:38:00 +00:00
return NULL ;
}
2007-06-06 20:06:43 +00:00
dest = safe_emalloc ( out_len , charsize , 0 ) ;
1999-04-17 00:37:12 +00:00
2006-08-14 20:43:23 +00:00
for ( p = src , q = dest ; p < ( src + charsize * ( srclen - chunklen + 1 ) ) ; ) {
memcpy ( q , p , chunklen * charsize ) ;
q + = chunklen * charsize ;
memcpy ( q , end , endlen * charsize ) ;
q + = endlen * charsize ;
p + = chunklen * charsize ;
1999-04-17 00:37:12 +00:00
}
2002-10-02 17:56:04 +00:00
if ( restlen ) {
2006-08-14 20:43:23 +00:00
memcpy ( q , p , restlen * charsize ) ;
q + = restlen * charsize ;
memcpy ( q , end , endlen * charsize ) ;
q + = endlen * charsize ;
1999-04-17 00:37:12 +00:00
}
2006-08-14 20:43:23 +00:00
if ( str_type = = IS_UNICODE ) {
* ( UChar * ) q = 0 ;
} else {
* q = ' \0 ' ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( destlen ) {
2006-08-14 20:43:23 +00:00
* destlen = ( q - dest ) / charsize ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
1999-04-17 00:37:12 +00:00
2006-08-14 20:43:23 +00:00
return ( dest ) ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-08-14 20:43:23 +00:00
/* {{{ proto string chunk_split(string str [, int chunklen [, string ending]]) U
2001-09-04 10:44:28 +00:00
Returns split line */
2006-07-16 15:56:00 +00:00
PHP_FUNCTION ( chunk_split )
1999-04-17 00:37:12 +00:00
{
2006-08-14 20:43:23 +00:00
zstr str , ending = NULL_ZSTR ;
int str_len , ending_len ;
zstr result ;
1999-04-17 00:37:12 +00:00
char * end = " \r \n " ;
2006-08-14 20:43:23 +00:00
UChar u_end [ 3 ] = { 0x0d , 0x0a , 0x0 } ;
2007-12-24 18:10:20 +00:00
long chunklen = 76 ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
int result_len ;
2006-08-14 20:43:23 +00:00
zend_uchar str_type ;
2001-09-04 06:18:11 +00:00
2006-08-14 20:43:23 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|lT " , & str , & str_len ,
& str_type , & chunklen , & ending , & ending_len , & str_type ) = = FAILURE ) {
return ;
2001-09-04 06:18:11 +00:00
}
if ( chunklen < = 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Chunk length should be greater than zero " ) ;
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
2000-08-17 08:47:42 +00:00
2006-08-14 20:43:23 +00:00
if ( ! ending . v ) {
ending = ( str_type = = IS_UNICODE ) ? ZSTR ( u_end ) : ZSTR ( end ) ;
ending_len = 2 ;
}
if ( chunklen > str_len ) {
2005-04-03 18:08:40 +00:00
/* to maintain BC, we must return original string + ending */
2006-08-14 20:43:23 +00:00
result_len = ending_len + str_len ;
if ( str_type = = IS_UNICODE ) {
result . u = eumalloc ( result_len + 1 ) ;
u_memcpy ( result . u , str . u , str_len ) ;
u_memcpy ( result . u + str_len , ending . u , ending_len ) ;
result . u [ result_len ] = 0 ;
} else {
result . s = emalloc ( result_len + 1 ) ;
memcpy ( result . s , str . s , str_len ) ;
memcpy ( result . s + str_len , ending . s , ending_len ) ;
result . s [ result_len ] = ' \0 ' ;
}
2006-12-19 21:38:59 +00:00
RETURN_ZSTRL ( str_type , result , result_len , 0 ) ;
2005-01-18 15:47:57 +00:00
}
2006-08-14 20:43:23 +00:00
if ( ! str_len ) {
2009-05-25 14:32:15 +00:00
RETURN_EMPTY_UNICODE ( ) ;
2000-08-17 08:47:42 +00:00
}
2006-08-14 20:43:23 +00:00
result . v = php_chunk_split ( str . v , str_len , ending . v , ending_len , chunklen , & result_len , str_type ) ;
2003-02-08 15:26:17 +00:00
2006-08-14 20:43:23 +00:00
if ( result . v ) {
2006-12-19 21:38:59 +00:00
RETURN_ZSTRL ( str_type , result , result_len , 0 ) ;
1999-04-17 00:37:12 +00:00
} else {
RETURN_FALSE ;
}
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string substr(string str, int start [, int length]) U
2001-09-04 10:44:28 +00:00
Returns part of a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( substr )
1999-04-17 00:37:12 +00:00
{
2005-08-11 23:36:07 +00:00
void * str ;
2005-12-09 13:41:06 +00:00
int str_len ;
2006-03-02 13:12:45 +00:00
int cp_len ;
2005-08-11 23:36:07 +00:00
zend_uchar str_type ;
2006-03-01 11:19:35 +00:00
long l = - 1 ;
long f ;
1999-04-17 00:37:12 +00:00
2005-08-11 23:36:07 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " tl|l " , & str , & str_len , & str_type , & f , & l ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2003-02-08 15:26:17 +00:00
2005-08-11 23:36:07 +00:00
if ( str_type = = IS_UNICODE ) {
cp_len = u_countChar32 ( str , str_len ) ;
2002-10-03 18:15:18 +00:00
} else {
2005-08-11 23:36:07 +00:00
cp_len = str_len ;
2001-09-04 06:18:11 +00:00
}
1999-04-17 00:37:12 +00:00
2005-08-11 23:36:07 +00:00
if ( ZEND_NUM_ARGS ( ) = = 2 ) {
l = cp_len ;
}
2006-07-16 15:56:00 +00:00
1999-04-17 00:37:12 +00:00
/* if "from" position is negative, count start position from the end
* of the string
*/
if ( f < 0 ) {
2005-08-11 23:36:07 +00:00
f = cp_len + f ;
1999-04-17 00:37:12 +00:00
if ( f < 0 ) {
f = 0 ;
}
}
/* if "length" position is negative, set it to the length
* needed to stop that many chars from the end of the string
*/
if ( l < 0 ) {
2005-08-11 23:36:07 +00:00
l = ( cp_len - f ) + l ;
1999-04-17 00:37:12 +00:00
if ( l < 0 ) {
l = 0 ;
}
}
2005-08-11 23:36:07 +00:00
if ( f > = cp_len ) {
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
2005-08-11 23:36:07 +00:00
if ( ( ( unsigned ) f + ( unsigned ) l ) > cp_len ) {
l = cp_len - f ;
1999-04-17 00:37:12 +00:00
}
1999-06-15 21:51:00 +00:00
2005-08-11 23:36:07 +00:00
if ( str_type = = IS_UNICODE ) {
int32_t start = 0 , end = 0 ;
U16_FWD_N ( ( UChar * ) str , end , str_len , f ) ;
start = end ;
U16_FWD_N ( ( UChar * ) str , end , str_len , l ) ;
RETURN_UNICODEL ( ( UChar * ) str + start , end - start , 1 ) ;
} else {
RETURN_STRINGL ( ( char * ) str + f , l , 1 ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2005-09-08 05:05:36 +00:00
/* {{{ php_adjust_limits
*/
2007-07-10 14:16:40 +00:00
static int php_adjust_limits ( zval * * str , int * f , int * l )
2005-09-08 05:05:36 +00:00
{
2006-03-02 13:12:45 +00:00
int str_codepts ;
2007-07-10 14:16:40 +00:00
int ret = 1 ;
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( str ) = = IS_UNICODE ) {
2005-09-28 14:58:31 +00:00
str_codepts = u_countChar32 ( Z_USTRVAL_PP ( str ) , Z_USTRLEN_PP ( str ) ) ;
2005-09-08 05:05:36 +00:00
} else {
str_codepts = Z_STRLEN_PP ( str ) ;
}
/* If "from" position is negative, count start position from the end
* of the string */
if ( * f < 0 ) {
* f = str_codepts + * f ;
if ( * f < 0 ) {
* f = 0 ;
}
} else if ( * f > str_codepts ) {
* f = str_codepts ;
}
/* If "length" position is negative, set it to the length
* needed to stop that many codepts / chars from the end of the string */
if ( * l < 0 ) {
* l = str_codepts - * f + * l ;
if ( * l < 0 ) {
* l = 0 ;
}
}
2007-07-10 14:16:40 +00:00
if ( * f > str_codepts | | ( * f < 0 & & - ( * f ) > str_codepts ) ) {
ret = 0 ;
} else if ( * l > str_codepts | | ( * l < 0 & & - ( * l ) > str_codepts ) ) {
2007-10-01 13:41:57 +00:00
* l = str_codepts ;
2007-07-10 14:16:40 +00:00
}
2005-09-08 05:05:36 +00:00
if ( ( ( unsigned ) ( * f ) + ( unsigned ) ( * l ) ) > str_codepts ) {
* l = str_codepts - * f ;
}
2007-07-10 14:16:40 +00:00
return ret ;
2005-09-08 05:05:36 +00:00
}
/* }}} */
/* {{{ php_do_substr_replace
*/
2006-03-02 13:12:45 +00:00
PHPAPI int php_do_substr_replace ( void * * result , zval * * str , zval * * repl , int f , int l TSRMLS_DC )
2005-09-08 05:05:36 +00:00
{
void * buf ;
int32_t buf_len , idx ;
UChar ch ;
2005-09-08 12:40:01 +00:00
int repl_len ;
if ( repl ) {
repl_len = Z_UNILEN_PP ( repl ) ;
} else {
repl_len = 0 ;
}
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( str ) = = IS_UNICODE ) {
2006-01-24 23:09:43 +00:00
buf = eumalloc ( Z_USTRLEN_PP ( str ) - l + repl_len + 1 ) ;
2005-09-08 05:05:36 +00:00
/* buf_len is codept count here */
buf_len = 0 ; idx = 0 ;
while ( f - - > 0 ) {
U16_NEXT ( Z_USTRVAL_PP ( str ) , idx , Z_USTRLEN_PP ( str ) , ch ) ;
buf_len + = zend_codepoint_to_uchar ( ch , ( UChar * ) buf + buf_len ) ;
}
if ( repl ! = NULL ) {
2005-09-08 12:40:01 +00:00
u_memcpy ( ( UChar * ) buf + buf_len , Z_USTRVAL_PP ( repl ) , repl_len ) ;
buf_len + = repl_len ;
2005-09-08 05:05:36 +00:00
}
U16_FWD_N ( Z_USTRVAL_PP ( str ) , idx , Z_USTRLEN_PP ( str ) , l ) ;
u_memcpy ( ( UChar * ) buf + buf_len , Z_USTRVAL_PP ( str ) + idx , Z_USTRLEN_PP ( str ) - idx ) ;
buf_len + = ( Z_USTRLEN_PP ( str ) - idx ) ;
* ( ( UChar * ) buf + buf_len ) = 0 ;
2006-01-24 23:09:43 +00:00
buf = eurealloc ( buf , buf_len + 1 ) ;
2005-09-08 05:05:36 +00:00
} else {
/* buf_len is char count here */
2005-09-08 12:40:01 +00:00
buf_len = Z_STRLEN_PP ( str ) - l + repl_len ;
2005-09-08 05:05:36 +00:00
buf = emalloc ( buf_len + 1 ) ;
memcpy ( buf , Z_STRVAL_PP ( str ) , f ) ;
2005-09-08 12:40:01 +00:00
if ( repl ! = NULL ) {
memcpy ( ( char * ) buf + f , Z_STRVAL_PP ( repl ) , repl_len ) ;
2005-09-08 05:05:36 +00:00
}
2005-09-08 12:40:01 +00:00
memcpy ( ( char * ) buf + f + repl_len , Z_STRVAL_PP ( str ) + f + l , Z_STRLEN_PP ( str ) - f - l ) ;
2005-09-08 05:05:36 +00:00
* ( ( char * ) buf + buf_len ) = ' \0 ' ;
}
* result = buf ;
return buf_len ;
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto mixed substr_replace(mixed str, mixed repl, mixed start [, mixed length]) U
2001-09-04 10:44:28 +00:00
Replaces part of a string with another string */
1999-11-16 22:44:13 +00:00
PHP_FUNCTION ( substr_replace )
{
2002-09-11 14:40:52 +00:00
zval * * str ;
zval * * from ;
2003-05-02 10:02:40 +00:00
zval * * len = NULL ;
2002-09-11 14:40:52 +00:00
zval * * repl ;
2005-09-08 05:05:36 +00:00
void * result ;
2006-03-02 13:12:45 +00:00
int result_len ;
int l = 0 ;
int f ;
2002-09-11 14:40:52 +00:00
int argc = ZEND_NUM_ARGS ( ) ;
2003-05-02 10:02:40 +00:00
HashPosition pos_str , pos_from , pos_repl , pos_len ;
zval * * tmp_str = NULL , * * tmp_from = NULL , * * tmp_repl = NULL , * * tmp_len = NULL ;
2005-09-28 14:58:31 +00:00
zend_uchar str_type ;
2003-05-02 10:02:40 +00:00
2006-09-20 20:30:19 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ZZZ|Z " , & str , & repl , & from , & len ) = = FAILURE ) {
return ;
1999-11-16 22:44:13 +00:00
}
2006-07-16 15:56:00 +00:00
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( str ) ! = IS_ARRAY & & Z_TYPE_PP ( str ) ! = IS_UNICODE & &
2006-01-17 12:18:53 +00:00
Z_TYPE_PP ( str ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( str ) ;
2003-05-02 10:02:40 +00:00
}
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( repl ) ! = IS_ARRAY & & Z_TYPE_PP ( repl ) ! = IS_UNICODE & &
2006-01-17 12:18:53 +00:00
Z_TYPE_PP ( repl ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( repl ) ;
2003-05-02 10:02:40 +00:00
}
if ( Z_TYPE_PP ( from ) ! = IS_ARRAY ) {
convert_to_long_ex ( from ) ;
2005-09-08 05:05:36 +00:00
f = Z_LVAL_PP ( from ) ;
2003-05-02 10:02:40 +00:00
}
2001-09-04 06:18:11 +00:00
if ( argc > 3 ) {
2007-10-01 13:41:57 +00:00
SEPARATE_ZVAL ( len ) ;
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( len ) ! = IS_ARRAY ) {
convert_to_long_ex ( len ) ;
l = Z_LVAL_PP ( len ) ;
}
2002-10-10 18:41:24 +00:00
} else {
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( str ) ! = IS_ARRAY ) {
2005-09-08 12:40:01 +00:00
l = Z_UNILEN_PP ( str ) ;
2003-05-02 10:02:40 +00:00
}
1999-11-16 22:44:13 +00:00
}
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( str ) ! = IS_ARRAY ) {
2007-10-01 13:41:57 +00:00
if (
( argc = = 3 & & Z_TYPE_PP ( from ) = = IS_ARRAY ) | |
( argc = = 4 & & Z_TYPE_PP ( from ) ! = Z_TYPE_PP ( len ) )
) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " 'from' and 'len' should be of same type - numerical or array " ) ;
2005-09-08 05:05:36 +00:00
RETURN_ZVAL ( * str , 1 , 0 ) ;
2003-05-02 10:02:40 +00:00
}
if ( argc = = 4 & & Z_TYPE_PP ( from ) = = IS_ARRAY ) {
if ( zend_hash_num_elements ( Z_ARRVAL_PP ( from ) ) ! = zend_hash_num_elements ( Z_ARRVAL_PP ( len ) ) ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " 'from' and 'len' should have the same number of elements " ) ;
2005-09-08 05:05:36 +00:00
RETURN_ZVAL ( * str , 1 , 0 ) ;
2003-05-02 10:02:40 +00:00
}
1999-11-16 22:44:13 +00:00
}
2002-10-10 18:41:24 +00:00
}
2000-11-06 19:41:30 +00:00
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( str ) ! = IS_ARRAY ) {
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( from ) ! = IS_ARRAY ) {
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( repl ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_PP ( repl ) , & pos_repl ) ;
if ( SUCCESS = = zend_hash_get_current_data_ex ( Z_ARRVAL_PP ( repl ) , ( void * * ) & tmp_repl , & pos_repl ) ) {
2006-01-17 12:18:53 +00:00
if ( Z_TYPE_PP ( repl ) ! = IS_UNICODE & & Z_TYPE_PP ( repl ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( tmp_repl ) ;
2005-09-08 05:05:36 +00:00
}
} else {
tmp_repl = NULL ;
2003-05-02 10:02:40 +00:00
}
} else {
2005-09-08 05:05:36 +00:00
tmp_repl = repl ;
2003-12-01 23:17:22 +00:00
}
2003-05-02 10:02:40 +00:00
2005-09-28 14:58:31 +00:00
if ( tmp_repl & & Z_TYPE_PP ( str ) ! = Z_TYPE_PP ( tmp_repl ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_PP ( str ) , Z_TYPE_PP ( tmp_repl ) ) ;
2006-01-17 12:18:53 +00:00
convert_to_explicit_type_ex ( str , str_type ) ;
convert_to_explicit_type_ex ( tmp_repl , str_type ) ;
2005-09-28 14:58:31 +00:00
}
2007-07-10 14:16:40 +00:00
if ( ! php_adjust_limits ( str , & f , & l ) ) {
RETURN_FALSE ;
}
2005-09-08 05:05:36 +00:00
result_len = php_do_substr_replace ( & result , str , tmp_repl , f , l TSRMLS_CC ) ;
if ( Z_TYPE_PP ( str ) = = IS_UNICODE ) {
RETURN_UNICODEL ( ( UChar * ) result , result_len , 0 ) ;
} else {
RETURN_STRINGL ( ( char * ) result , result_len , 0 ) ;
2003-05-02 10:02:40 +00:00
}
} else {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Functionality of 'from' and 'len' as arrays is not implemented " ) ;
2006-07-16 15:56:00 +00:00
RETURN_ZVAL ( * str , 1 , 0 ) ;
1999-11-16 22:44:13 +00:00
}
2003-05-02 10:02:40 +00:00
} else { /* str is array of strings */
array_init ( return_value ) ;
1999-11-16 22:44:13 +00:00
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( from ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_PP ( from ) , & pos_from ) ;
}
if ( argc > 3 & & Z_TYPE_PP ( len ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_PP ( len ) , & pos_len ) ;
}
if ( Z_TYPE_PP ( repl ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_PP ( repl ) , & pos_repl ) ;
}
2003-12-01 23:17:22 +00:00
2003-05-02 10:02:40 +00:00
zend_hash_internal_pointer_reset_ex ( Z_ARRVAL_PP ( str ) , & pos_str ) ;
while ( zend_hash_get_current_data_ex ( Z_ARRVAL_PP ( str ) , ( void * * ) & tmp_str , & pos_str ) = = SUCCESS ) {
2006-09-20 20:30:19 +00:00
if ( Z_TYPE_PP ( tmp_str ) ! = IS_UNICODE & & Z_TYPE_PP ( tmp_str ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( tmp_str ) ;
2005-09-08 05:05:36 +00:00
}
2003-12-01 23:17:22 +00:00
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( from ) = = IS_ARRAY ) {
if ( SUCCESS = = zend_hash_get_current_data_ex ( Z_ARRVAL_PP ( from ) , ( void * * ) & tmp_from , & pos_from ) ) {
convert_to_long_ex ( tmp_from ) ;
f = Z_LVAL_PP ( tmp_from ) ;
zend_hash_move_forward_ex ( Z_ARRVAL_PP ( from ) , & pos_from ) ;
} else {
f = 0 ;
2003-12-01 23:17:22 +00:00
}
2003-05-02 10:02:40 +00:00
}
2005-09-08 05:05:36 +00:00
if ( argc > 3 & & ( Z_TYPE_PP ( len ) = = IS_ARRAY ) ) {
2003-05-02 10:02:40 +00:00
if ( SUCCESS = = zend_hash_get_current_data_ex ( Z_ARRVAL_PP ( len ) , ( void * * ) & tmp_len , & pos_len ) ) {
convert_to_long_ex ( tmp_len ) ;
l = Z_LVAL_PP ( tmp_len ) ;
zend_hash_move_forward_ex ( Z_ARRVAL_PP ( len ) , & pos_len ) ;
} else {
2005-09-08 12:40:01 +00:00
l = Z_UNILEN_PP ( tmp_str ) ;
2003-05-02 10:02:40 +00:00
}
2005-09-08 05:05:36 +00:00
} else if ( argc > 3 ) {
/* 'l' parsed & set at top of funcn */
2005-09-08 12:40:01 +00:00
l = Z_LVAL_PP ( len ) ;
2003-05-02 10:02:40 +00:00
} else {
2005-09-08 12:40:01 +00:00
l = Z_UNILEN_PP ( tmp_str ) ;
2003-12-01 23:17:22 +00:00
}
2003-05-02 10:02:40 +00:00
if ( Z_TYPE_PP ( repl ) = = IS_ARRAY ) {
if ( SUCCESS = = zend_hash_get_current_data_ex ( Z_ARRVAL_PP ( repl ) , ( void * * ) & tmp_repl , & pos_repl ) ) {
2006-09-20 20:30:19 +00:00
if ( Z_TYPE_PP ( tmp_repl ) ! = IS_UNICODE & & Z_TYPE_PP ( tmp_repl ) ! = IS_STRING ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( tmp_repl ) ;
2005-09-08 05:05:36 +00:00
}
2006-07-16 15:56:00 +00:00
zend_hash_move_forward_ex ( Z_ARRVAL_PP ( repl ) , & pos_repl ) ;
2003-05-02 10:02:40 +00:00
} else {
2005-09-08 05:05:36 +00:00
tmp_repl = NULL ;
2003-05-02 10:02:40 +00:00
}
} else {
2005-09-08 05:05:36 +00:00
tmp_repl = repl ;
}
2003-05-02 10:02:40 +00:00
2005-09-28 14:58:31 +00:00
if ( tmp_repl & & Z_TYPE_PP ( tmp_str ) ! = Z_TYPE_PP ( tmp_repl ) ) {
str_type = zend_get_unified_string_type ( 2 TSRMLS_CC , Z_TYPE_PP ( tmp_str ) , Z_TYPE_PP ( tmp_repl ) ) ;
2006-01-17 12:18:53 +00:00
convert_to_explicit_type_ex ( tmp_str , str_type ) ;
convert_to_explicit_type_ex ( tmp_repl , str_type ) ;
2005-09-28 14:58:31 +00:00
}
2005-09-08 05:05:36 +00:00
php_adjust_limits ( tmp_str , & f , & l ) ;
result_len = php_do_substr_replace ( & result , tmp_str , tmp_repl , f , l TSRMLS_CC ) ;
1999-11-16 22:44:13 +00:00
2005-09-08 05:05:36 +00:00
if ( Z_TYPE_PP ( tmp_str ) = = IS_UNICODE ) {
add_next_index_unicodel ( return_value , ( UChar * ) result , result_len , 0 ) ;
} else {
add_next_index_stringl ( return_value , ( char * ) result , result_len , 0 ) ;
2003-05-02 10:02:40 +00:00
}
zend_hash_move_forward_ex ( Z_ARRVAL_PP ( str ) , & pos_str ) ;
} /*while*/
} /* if */
1999-11-16 22:44:13 +00:00
}
/* }}} */
2006-09-22 19:35:05 +00:00
/* {{{ proto string quotemeta(string str) U
2001-09-04 10:44:28 +00:00
Quotes meta characters */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( quotemeta )
1999-04-17 00:37:12 +00:00
{
2006-09-22 19:35:05 +00:00
zstr str , old ;
zstr old_end ;
int old_len ;
zstr p , q ;
1999-04-17 00:37:12 +00:00
char c ;
2006-09-22 19:35:05 +00:00
UChar cp ;
zend_uchar type ;
2006-07-16 15:56:00 +00:00
2006-09-23 12:22:07 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & old , & old_len , & type ) = = FAILURE ) {
2006-09-22 19:35:05 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2003-02-08 15:26:17 +00:00
2006-09-22 19:35:05 +00:00
if ( old_len = = 0 ) {
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
2006-07-16 15:56:00 +00:00
2006-09-22 19:35:05 +00:00
if ( type = = IS_UNICODE ) {
old_end . u = old . u + old_len ;
str . u = safe_emalloc ( 2 , UBYTES ( old_len ) , 1 ) ;
for ( p . u = old . u , q . u = str . u ; p . u ! = old_end . u ; p . u + + ) {
cp = * p . u ;
switch ( cp ) {
case ' . ' :
case ' \\ ' :
case ' + ' :
case ' * ' :
case ' ? ' :
case ' [ ' :
case ' ^ ' :
case ' ] ' :
case ' $ ' :
case ' ( ' :
case ' ) ' :
* q . u + + = ' \\ ' ;
/* break is missing _intentionally_ */
default :
* q . u + + = cp ;
}
}
* q . u = 0 ;
RETURN_UNICODEL ( eurealloc ( str . u , q . u - str . u + 1 ) , q . u - str . u , 0 ) ;
} else {
old_end . s = old . s + old_len ;
str . s = safe_emalloc ( 2 , old_len , 1 ) ;
for ( p . s = old . s , q . s = str . s ; p . s ! = old_end . s ; p . s + + ) {
c = * p . s ;
switch ( c ) {
case ' . ' :
case ' \\ ' :
case ' + ' :
case ' * ' :
case ' ? ' :
case ' [ ' :
case ' ^ ' :
case ' ] ' :
case ' $ ' :
case ' ( ' :
case ' ) ' :
* q . s + + = ' \\ ' ;
/* break is missing _intentionally_ */
default :
* q . s + + = c ;
}
}
* q . s = 0 ;
RETURN_STRINGL ( erealloc ( str . s , q . s - str . s + 1 ) , q . s - str . s , 0 ) ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-06 21:49:21 +00:00
/* {{{ proto int ord(string character) U
2005-08-19 22:00:21 +00:00
Returns the codepoint value of a character */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( ord )
1999-04-17 00:37:12 +00:00
{
2008-08-16 21:16:25 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2001-09-04 06:18:11 +00:00
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE ) {
RETURN_LONG ( zend_get_codepoint_at ( str . u , str_len , 0 ) ) ;
2005-08-19 22:00:21 +00:00
} else {
2008-08-16 21:16:25 +00:00
RETURN_LONG ( ( unsigned char ) str . s [ 0 ] ) ;
2005-08-19 22:00:21 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-06 21:49:21 +00:00
/* {{{ proto string chr(int codepoint) U
2005-08-19 22:00:21 +00:00
Converts a codepoint number to a character */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( chr )
1999-04-17 00:37:12 +00:00
{
2009-03-26 20:02:53 +00:00
UChar buf [ 2 ] ;
int buf_len ;
2008-08-16 21:16:25 +00:00
long num ;
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & num ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2009-03-26 20:02:53 +00:00
if ( num > UCHAR_MAX_VALUE ) {
php_error ( E_WARNING , " Codepoint value cannot be greater than %X " , UCHAR_MAX_VALUE ) ;
return ;
2005-08-19 22:00:21 +00:00
}
2009-03-26 20:02:53 +00:00
buf_len = zend_codepoint_to_uchar ( ( uint32_t ) num , buf ) ;
RETURN_UNICODEL ( buf , buf_len , 1 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2008-01-19 19:23:25 +00:00
/* {{{ php_u_lcfirst()
Makes an Unicode string ' s first character lowercase */
static void php_u_lcfirst ( UChar * ustr , int ustr_len , zval * return_value TSRMLS_DC )
{
UChar tmp [ 3 ] = { 0 , 0 , 0 } ; /* UChar32 will be converted to upto 2 UChar units */
int tmp_len = 0 ;
int pos = 0 ;
UErrorCode status = U_ZERO_ERROR ;
U16_FWD_1 ( ustr , pos , ustr_len ) ;
2008-01-19 19:47:41 +00:00
tmp_len = u_strToLower ( tmp , sizeof ( tmp ) / sizeof ( UChar ) , ustr , pos , UG ( default_locale ) , & status ) ;
2008-01-19 19:23:25 +00:00
Z_USTRVAL_P ( return_value ) = eumalloc ( tmp_len + ustr_len - pos + 1 ) ;
Z_USTRVAL_P ( return_value ) [ 0 ] = tmp [ 0 ] ;
if ( tmp_len > 1 ) {
Z_USTRVAL_P ( return_value ) [ 1 ] = tmp [ 1 ] ;
}
u_memcpy ( Z_USTRVAL_P ( return_value ) + tmp_len , ustr + pos , ustr_len - pos + 1 ) ;
Z_USTRLEN_P ( return_value ) = tmp_len + ustr_len - pos ;
}
/* }}} */
/* {{{ php_lcfirst
Lowercase the first character of the word in a native string */
static void php_lcfirst ( char * str )
{
register char * r ;
r = str ;
* r = tolower ( ( unsigned char ) * r ) ;
}
/* }}} */
2008-01-29 01:44:38 +00:00
/* {{{ proto string lcfirst(string str) U
Makes a string ' s first character lowercase */
2008-01-19 19:23:25 +00:00
PHP_FUNCTION ( lcfirst )
{
zstr str ;
int str_len ;
zend_uchar str_type ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
}
if ( str_len = = 0 ) {
if ( str_type = = IS_UNICODE ) {
RETURN_EMPTY_UNICODE ( ) ;
} else {
RETURN_EMPTY_STRING ( ) ;
}
}
if ( str_type = = IS_UNICODE ) {
Z_TYPE_P ( return_value ) = IS_UNICODE ;
php_u_lcfirst ( str . u , str_len , return_value TSRMLS_CC ) ;
} else {
ZVAL_STRINGL ( return_value , str . s , str_len , ZSTR_DUPLICATE ) ;
php_lcfirst ( Z_STRVAL_P ( return_value ) ) ;
}
}
/* }}} */
2005-08-18 05:53:46 +00:00
/* {{{ php_u_ucfirst()
2005-08-17 17:33:19 +00:00
Makes an Unicode string ' s first character uppercase */
2008-01-16 03:09:01 +00:00
static void php_u_ucfirst ( UChar * ustr , int ustr_len , zval * return_value TSRMLS_DC )
2005-08-17 17:33:19 +00:00
{
2006-03-17 22:51:20 +00:00
UChar tmp [ 3 ] = { 0 , 0 , 0 } ; /* UChar32 will be converted to upto 2 UChar units */
int tmp_len = 0 ;
2006-03-02 20:37:07 +00:00
int pos = 0 ;
UErrorCode status = U_ZERO_ERROR ;
2005-08-17 17:33:19 +00:00
2008-01-16 03:09:01 +00:00
U16_FWD_1 ( ustr , pos , ustr_len ) ;
tmp_len = u_strToUpper ( tmp , sizeof ( tmp ) / sizeof ( UChar ) , ustr , pos , UG ( default_locale ) , & status ) ;
2005-08-17 17:33:19 +00:00
2008-01-16 03:09:01 +00:00
Z_USTRVAL_P ( return_value ) = eumalloc ( tmp_len + ustr_len - pos + 1 ) ;
2005-08-17 17:33:19 +00:00
Z_USTRVAL_P ( return_value ) [ 0 ] = tmp [ 0 ] ;
if ( tmp_len > 1 ) {
Z_USTRVAL_P ( return_value ) [ 1 ] = tmp [ 1 ] ;
}
2008-01-16 03:09:01 +00:00
u_memcpy ( Z_USTRVAL_P ( return_value ) + tmp_len , ustr + pos , ustr_len - pos + 1 ) ;
Z_USTRLEN_P ( return_value ) = tmp_len + ustr_len - pos ;
}
/* }}} */
/* {{{ php_ucfirst
Uppercase the first character of the word in a native string */
static void php_ucfirst ( char * str )
{
register char * r ;
r = str ;
* r = toupper ( ( unsigned char ) * r ) ;
2005-08-17 17:33:19 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string ucfirst(string str) U
2001-09-04 10:44:28 +00:00
Makes a string ' s first character uppercase */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( ucfirst )
1999-04-17 00:37:12 +00:00
{
2008-01-16 03:09:01 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2005-08-17 17:33:19 +00:00
2008-01-16 03:09:01 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2008-01-16 03:09:01 +00:00
if ( str_len = = 0 ) {
if ( str_type = = IS_UNICODE ) {
RETURN_EMPTY_UNICODE ( ) ;
} else {
RETURN_EMPTY_STRING ( ) ;
}
}
1999-11-14 17:20:56 +00:00
2008-01-16 03:09:01 +00:00
if ( str_type = = IS_UNICODE ) {
2005-08-17 17:33:19 +00:00
Z_TYPE_P ( return_value ) = IS_UNICODE ;
2008-01-16 03:09:01 +00:00
php_u_ucfirst ( str . u , str_len , return_value TSRMLS_CC ) ;
2005-08-17 17:33:19 +00:00
} else {
2008-01-16 03:09:01 +00:00
ZVAL_STRINGL ( return_value , str . s , str_len , ZSTR_DUPLICATE ) ;
php_ucfirst ( Z_STRVAL_P ( return_value ) ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-22 10:20:20 +00:00
/* {{{ php_ucwords()
Uppercase the first character of every word in a native string */
2006-10-04 17:38:09 +00:00
static void php_ucwords ( char * str , int str_len )
2006-03-22 10:20:20 +00:00
{
register char * r , * r_end ;
2006-10-04 17:38:09 +00:00
r = str ;
2006-03-22 10:20:20 +00:00
* r = toupper ( ( unsigned char ) * r ) ;
2006-10-04 17:38:09 +00:00
for ( r_end = r + str_len - 1 ; r < r_end ; ) {
2006-03-22 10:20:20 +00:00
if ( isspace ( ( int ) * ( unsigned char * ) r + + ) ) {
* r = toupper ( ( unsigned char ) * r ) ;
}
}
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ php_u_ucwords() U
2005-08-17 20:29:00 +00:00
Uppercase the first character of every word in an Unicode string */
2006-10-04 17:38:09 +00:00
static void php_u_ucwords ( UChar * ustr , int ustr_len , zval * retval TSRMLS_DC )
2005-08-17 20:29:00 +00:00
{
2006-03-02 23:12:33 +00:00
UChar32 cp = 0 ;
UChar * tmp ;
int retval_len ;
int pos = 0 , last_pos = 0 ;
int tmp_len = 0 ;
zend_bool last_was_space = TRUE ;
UErrorCode status = U_ZERO_ERROR ;
2005-08-17 20:29:00 +00:00
2006-03-02 23:12:33 +00:00
/*
* We can calculate maximum resulting length precisely considering that not
* more than half of the codepoints in the string can follow a whitespace
* and that maximum expansion is 2 UChar ' s .
*/
2006-10-04 17:38:09 +00:00
retval_len = ( ( 3 * ustr_len ) > > 1 ) + 2 ;
2006-03-02 23:12:33 +00:00
tmp = eumalloc ( retval_len ) ;
2005-08-17 20:29:00 +00:00
2006-10-04 17:38:09 +00:00
while ( pos < ustr_len ) {
2005-08-17 20:29:00 +00:00
2006-10-04 17:38:09 +00:00
U16_NEXT ( ustr , pos , ustr_len , cp ) ;
2006-03-02 23:12:33 +00:00
if ( u_isWhitespace ( cp ) = = TRUE ) {
tmp_len + = zend_codepoint_to_uchar ( cp , tmp + tmp_len ) ;
last_was_space = TRUE ;
} else {
if ( last_was_space ) {
2006-10-04 17:38:09 +00:00
tmp_len + = u_strToUpper ( tmp + tmp_len , retval_len - tmp_len , ustr + last_pos , 1 , UG ( default_locale ) , & status ) ;
2006-03-02 23:12:33 +00:00
last_was_space = FALSE ;
} else {
tmp_len + = zend_codepoint_to_uchar ( cp , tmp + tmp_len ) ;
}
}
2006-07-16 15:56:00 +00:00
2006-03-02 23:12:33 +00:00
last_pos = pos ;
2005-08-17 20:29:00 +00:00
}
2006-03-02 23:12:33 +00:00
tmp [ tmp_len ] = 0 ;
2005-08-17 20:29:00 +00:00
2006-03-02 23:12:33 +00:00
/*
* Try to avoid another alloc if the difference between allocated size and
* real length is " small " .
*/
if ( retval_len - tmp_len > 256 ) {
ZVAL_UNICODEL ( retval , tmp , tmp_len , 1 ) ;
efree ( tmp ) ;
2005-08-17 20:29:00 +00:00
} else {
2006-03-02 23:12:33 +00:00
ZVAL_UNICODEL ( retval , tmp , tmp_len , 0 ) ;
2005-08-17 20:29:00 +00:00
}
}
/* }}} */
2006-10-04 17:38:09 +00:00
/* {{{ proto string ucwords(string str) U
1999-04-17 00:37:12 +00:00
Uppercase the first character of every word in a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( ucwords )
1999-04-17 00:37:12 +00:00
{
2006-10-04 17:38:09 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
1999-04-17 00:37:12 +00:00
2006-10-04 17:38:09 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2005-08-17 20:29:00 +00:00
}
2006-10-04 17:38:09 +00:00
if ( str_len = = 0 ) {
if ( str_type = = IS_UNICODE ) {
RETURN_EMPTY_UNICODE ( ) ;
} else {
RETURN_EMPTY_STRING ( ) ;
}
1999-04-17 00:37:12 +00:00
}
2000-06-01 10:07:44 +00:00
2006-10-04 17:38:09 +00:00
if ( str_type = = IS_UNICODE ) {
2005-08-17 20:29:00 +00:00
Z_TYPE_P ( return_value ) = IS_UNICODE ;
2006-10-04 17:38:09 +00:00
php_u_ucwords ( str . u , str_len , return_value TSRMLS_CC ) ;
2005-08-17 20:29:00 +00:00
} else {
2006-10-04 17:38:09 +00:00
ZVAL_STRINGL ( return_value , str . s , str_len , 1 ) ;
php_ucwords ( Z_STRVAL_P ( return_value ) , str_len ) ;
1999-04-17 00:37:12 +00:00
}
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strtr
*/
2003-02-08 15:26:17 +00:00
PHPAPI char * php_strtr ( char * str , int len , char * str_from , char * str_to , int trlen )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
{
int i ;
unsigned char xlat [ 256 ] ;
if ( ( trlen < 1 ) | | ( len < 1 ) ) {
2000-02-08 22:21:43 +00:00
return str ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
for ( i = 0 ; i < 256 ; xlat [ i ] = i , i + + ) ;
for ( i = 0 ; i < trlen ; i + + ) {
xlat [ ( unsigned char ) str_from [ i ] ] = str_to [ i ] ;
}
for ( i = 0 ; i < len ; i + + ) {
2000-02-08 22:21:43 +00:00
str [ i ] = xlat [ ( unsigned char ) str [ i ] ] ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2000-02-08 22:21:43 +00:00
return str ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2006-03-17 14:29:05 +00:00
/* {{{ php_u_strtr
*/
2006-11-16 20:33:44 +00:00
static void text_iter_helper_move ( UChar * text , int32_t text_len , int32_t * offset , int32_t * cp_offset )
{
UChar32 cp ;
int32_t tmp , tmp2 ;
if ( * offset = = UBRK_DONE ) {
return ;
}
if ( * offset = = text_len ) {
* offset = UBRK_DONE ;
* cp_offset = UBRK_DONE ;
} else {
U16_NEXT ( text , ( * offset ) , text_len , cp ) ;
( * cp_offset ) + + ;
if ( u_getCombiningClass ( cp ) = = 0 ) {
tmp = * offset ;
tmp2 = * cp_offset ;
/*
* At the end of the from cp will be 0 because of the NULL
* terminating NULL , so combining class will be 0 as well .
*/
while ( tmp < text_len ) {
U16_NEXT ( text , tmp , text_len , cp ) ;
tmp2 + + ;
if ( u_getCombiningClass ( cp ) = = 0 ) {
break ;
} else {
* offset = tmp ;
* cp_offset = tmp2 ;
}
}
}
}
}
2006-03-27 06:02:42 +00:00
PHPAPI UChar * php_u_strtr ( UChar * str , int len , UChar * str_from , int str_from_len , UChar * str_to , int str_to_len , int trlen , int * outlen TSRMLS_DC )
2006-03-17 14:29:05 +00:00
{
2006-06-11 20:33:29 +00:00
int i ;
2006-03-17 14:29:05 +00:00
int can_optimize = 1 ;
2006-07-16 15:56:00 +00:00
2006-03-17 14:29:05 +00:00
if ( ( trlen < 1 ) | | ( len < 1 ) ) {
2008-01-21 14:37:19 +00:00
* outlen = len ;
2006-03-17 14:29:05 +00:00
return str ;
}
/* First loop to see if we can use the optimized version */
for ( i = 0 ; i < trlen ; i + + ) {
if ( str_from [ i ] > 255 | | str_to [ i ] > 255 ) {
can_optimize = 0 ;
break ;
}
}
if ( can_optimize ) {
for ( i = trlen ; i < str_from_len ; i + + ) {
if ( str_from [ i ] > 255 ) {
can_optimize = 0 ;
break ;
}
}
}
if ( can_optimize ) {
for ( i = trlen ; i < str_to_len ; i + + ) {
2008-11-24 19:31:02 +00:00
if ( str_to [ i ] > 255 ) {
2006-03-17 14:29:05 +00:00
can_optimize = 0 ;
break ;
}
}
}
if ( can_optimize ) {
UChar xlat [ 256 ] ;
2006-03-26 02:15:47 +00:00
UChar * tmp_str = eustrndup ( str , len ) ;
2006-03-17 14:29:05 +00:00
for ( i = 0 ; i < 256 ; xlat [ i ] = i , i + + ) ;
for ( i = 0 ; i < trlen ; i + + ) {
xlat [ str_from [ i ] ] = str_to [ i ] ;
}
for ( i = 0 ; i < len ; i + + ) {
2006-08-09 20:03:22 +00:00
if ( str [ i ] < 256 ) {
tmp_str [ i ] = xlat [ str [ i ] ] ;
}
2006-03-17 14:29:05 +00:00
}
2006-03-26 02:15:47 +00:00
* outlen = len ;
return tmp_str ;
2006-03-17 14:29:05 +00:00
} else {
2006-03-26 02:15:47 +00:00
/* We use the character break iterator here to assemble an mapping
* array in such a way that we can reuse the code in php_u_strtr_array
* to do the replacements in order to avoid duplicating code . */
HashTable * tmp_hash ;
2006-11-16 20:33:44 +00:00
int minlen = 128 * 1024 , maxlen = 0 ;
int32_t prev_from_offset = 0 , from_offset = 0 , from_cp_offset = 0 ;
int32_t prev_to_offset = 0 , to_offset = 0 , to_cp_offset = 0 ;
zval * entry ;
UChar * key_string ;
2006-07-16 15:56:00 +00:00
2006-03-26 02:15:47 +00:00
tmp_hash = emalloc ( sizeof ( HashTable ) ) ;
2006-11-17 16:44:23 +00:00
zend_hash_init ( tmp_hash , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
2006-03-26 02:15:47 +00:00
/* Loop over the two strings and prepare the hash entries */
2006-11-16 20:33:44 +00:00
do
{
text_iter_helper_move ( str_from , str_from_len , & from_offset , & from_cp_offset ) ;
text_iter_helper_move ( str_to , str_to_len , & to_offset , & to_cp_offset ) ;
if ( from_offset ! = - 1 & & to_offset ! = - 1 ) {
if ( from_cp_offset - prev_from_offset > maxlen ) {
maxlen = from_cp_offset - prev_from_offset ;
}
if ( from_cp_offset - prev_from_offset < minlen ) {
minlen = from_cp_offset - prev_from_offset ;
}
MAKE_STD_ZVAL ( entry ) ;
2006-11-17 16:44:23 +00:00
ZVAL_UNICODEL ( entry , str_to + prev_to_offset , to_cp_offset - prev_to_offset , 1 ) ;
Z_USTRVAL_P ( entry ) [ to_cp_offset - prev_to_offset ] = 0 ;
2006-11-16 20:33:44 +00:00
key_string = eumalloc ( from_cp_offset - prev_from_offset + 1 ) ;
2006-11-17 16:45:28 +00:00
u_memcpy ( key_string , str_from + prev_from_offset , from_cp_offset - prev_from_offset ) ;
2006-11-16 20:33:44 +00:00
key_string [ from_cp_offset - prev_from_offset ] = 0 ;
zend_u_hash_add ( tmp_hash , IS_UNICODE , ZSTR ( key_string ) , from_cp_offset - prev_from_offset + 1 , & entry , sizeof ( zval * ) , NULL ) ;
efree ( key_string ) ;
}
prev_from_offset = from_offset ;
prev_to_offset = to_offset ;
} while ( from_offset ! = - 1 & & to_offset ! = - 1 ) ;
2006-03-26 02:15:47 +00:00
/* Run the replacement */
2006-03-27 06:02:42 +00:00
str = php_u_strtr_array ( str , len , tmp_hash , minlen , maxlen , outlen TSRMLS_CC ) ;
2006-03-26 02:15:47 +00:00
zend_hash_destroy ( tmp_hash ) ;
efree ( tmp_hash ) ;
2006-03-17 14:29:05 +00:00
return str ;
}
}
/* }}} */
2007-06-05 13:37:05 +00:00
static HashTable * php_u_strtr_array_prepare_hashtable ( HashTable * hash , int * minlen_out , int * maxlen_out TSRMLS_DC ) /* { { { */
2006-03-17 14:29:05 +00:00
{
2006-03-26 02:15:47 +00:00
HashTable * tmp_hash = emalloc ( sizeof ( HashTable ) ) ;
HashPosition hpos ;
2006-03-17 14:29:05 +00:00
zval * * entry ;
zstr string_key ;
uint string_key_len ;
int minlen = 128 * 1024 ;
2006-03-26 02:15:47 +00:00
ulong num_key ;
int maxlen = 0 , len ;
zval ctmp ;
2006-07-16 15:56:00 +00:00
2006-10-03 17:45:16 +00:00
zend_hash_init ( tmp_hash , zend_hash_num_elements ( hash ) , NULL , NULL , 0 ) ;
2006-03-17 14:29:05 +00:00
zend_hash_internal_pointer_reset_ex ( hash , & hpos ) ;
while ( zend_hash_get_current_data_ex ( hash , ( void * * ) & entry , & hpos ) = = SUCCESS ) {
switch ( zend_hash_get_current_key_ex ( hash , & string_key , & string_key_len , & num_key , 0 , & hpos ) ) {
case HASH_KEY_IS_UNICODE :
len = string_key_len - 1 ;
if ( len < 1 ) {
2006-03-26 02:15:47 +00:00
zend_hash_destroy ( tmp_hash ) ;
2008-01-21 14:37:19 +00:00
efree ( tmp_hash ) ;
2006-03-26 02:15:47 +00:00
return NULL ;
2006-03-17 14:29:05 +00:00
}
2006-03-26 02:15:47 +00:00
zend_u_hash_add ( tmp_hash , IS_UNICODE , string_key , string_key_len , entry , sizeof ( zval * ) , NULL ) ;
2006-03-17 14:29:05 +00:00
if ( len > maxlen ) {
maxlen = len ;
}
if ( len < minlen ) {
minlen = len ;
}
2006-07-16 15:56:00 +00:00
break ;
2006-03-17 14:29:05 +00:00
case HASH_KEY_IS_LONG :
Z_TYPE ( ctmp ) = IS_LONG ;
Z_LVAL ( ctmp ) = num_key ;
2006-07-16 15:56:00 +00:00
2006-03-17 14:29:05 +00:00
convert_to_unicode ( & ctmp ) ;
len = Z_USTRLEN ( ctmp ) ;
2006-03-26 02:15:47 +00:00
zend_u_hash_add ( tmp_hash , IS_UNICODE , Z_UNIVAL ( ctmp ) , len + 1 , entry , sizeof ( zval * ) , NULL ) ;
2006-03-17 14:29:05 +00:00
zval_dtor ( & ctmp ) ;
if ( len > maxlen ) {
maxlen = len ;
}
if ( len < minlen ) {
minlen = len ;
}
break ;
}
zend_hash_move_forward_ex ( hash , & hpos ) ;
}
2006-03-26 02:15:47 +00:00
* minlen_out = minlen ;
* maxlen_out = maxlen ;
return tmp_hash ;
}
2007-06-05 13:37:05 +00:00
/* }}} */
2006-03-26 02:15:47 +00:00
/* {{{ php_u_strtr_array
*/
static UChar * php_u_strtr_array ( UChar * str , int slen , HashTable * hash , int minlen , int maxlen , int * outlen TSRMLS_DC )
{
zval * * trans ;
UChar * key ;
int pos , found , len ;
smart_str result = { 0 } ;
2006-03-17 14:29:05 +00:00
key = eumalloc ( maxlen + 1 ) ;
pos = 0 ;
while ( pos < slen ) {
if ( ( pos + maxlen ) > slen ) {
maxlen = slen - pos ;
}
found = 0 ;
2006-11-17 16:45:28 +00:00
u_memcpy ( key , str + pos , maxlen ) ;
2006-03-17 14:29:05 +00:00
for ( len = maxlen ; len > = minlen ; len - - ) {
key [ len ] = 0 ;
2006-07-16 15:56:00 +00:00
2006-03-26 02:15:47 +00:00
if ( zend_u_hash_find ( hash , IS_UNICODE , ZSTR ( key ) , len + 1 , ( void * * ) & trans ) = = SUCCESS ) {
2006-03-17 14:29:05 +00:00
UChar * tval ;
int tlen ;
zval tmp ;
if ( Z_TYPE_PP ( trans ) ! = IS_UNICODE ) {
tmp = * * trans ;
zval_copy_ctor ( & tmp ) ;
2006-03-26 02:15:47 +00:00
convert_to_unicode ( & tmp ) ;
2006-03-17 14:29:05 +00:00
tval = Z_USTRVAL ( tmp ) ;
tlen = Z_USTRLEN ( tmp ) ;
} else {
tval = Z_USTRVAL_PP ( trans ) ;
tlen = Z_USTRLEN_PP ( trans ) ;
}
smart_str_appendl ( & result , tval , UBYTES ( tlen ) ) ;
pos + = len ;
found = 1 ;
if ( Z_TYPE_PP ( trans ) ! = IS_UNICODE ) {
zval_dtor ( & tmp ) ;
}
break ;
2006-07-16 15:56:00 +00:00
}
2006-03-17 14:29:05 +00:00
}
if ( ! found ) {
smart_str_append2c ( & result , str [ pos ] ) ;
pos + + ;
}
}
efree ( key ) ;
smart_str_0 ( & result ) ;
2006-03-26 02:15:47 +00:00
* outlen = result . len > > 1 ;
return ( UChar * ) result . c ;
2006-03-17 14:29:05 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_strtr_array
*/
2001-08-11 17:03:37 +00:00
static void php_strtr_array ( zval * return_value , char * str , int slen , HashTable * hash )
1999-11-20 15:53:18 +00:00
{
2001-09-04 06:18:11 +00:00
zval * * entry ;
2006-02-21 20:12:43 +00:00
zstr string_key ;
2001-09-04 06:18:11 +00:00
uint string_key_len ;
1999-11-20 15:53:18 +00:00
zval * * trans ;
2001-09-04 06:18:11 +00:00
zval ctmp ;
1999-11-20 15:53:18 +00:00
ulong num_key ;
int minlen = 128 * 1024 ;
2000-10-12 01:26:26 +00:00
int maxlen = 0 , pos , len , found ;
char * key ;
2000-06-18 10:37:01 +00:00
HashPosition hpos ;
2000-10-12 01:26:26 +00:00
smart_str result = { 0 } ;
2004-03-18 09:48:37 +00:00
HashTable tmp_hash ;
2006-07-16 15:56:00 +00:00
2004-03-18 09:48:37 +00:00
zend_hash_init ( & tmp_hash , 0 , NULL , NULL , 0 ) ;
2000-06-18 10:37:01 +00:00
zend_hash_internal_pointer_reset_ex ( hash , & hpos ) ;
while ( zend_hash_get_current_data_ex ( hash , ( void * * ) & entry , & hpos ) = = SUCCESS ) {
2001-09-04 06:18:11 +00:00
switch ( zend_hash_get_current_key_ex ( hash , & string_key , & string_key_len , & num_key , 0 , & hpos ) ) {
2003-02-08 15:26:17 +00:00
case HASH_KEY_IS_STRING :
len = string_key_len - 1 ;
2003-09-20 16:10:49 +00:00
if ( len < 1 ) {
2004-03-18 09:48:37 +00:00
zend_hash_destroy ( & tmp_hash ) ;
2003-09-20 16:10:49 +00:00
RETURN_FALSE ;
}
2006-02-21 20:12:43 +00:00
zend_u_hash_add ( & tmp_hash , IS_STRING , string_key , string_key_len , entry , sizeof ( zval * ) , NULL ) ;
2003-02-08 15:26:17 +00:00
if ( len > maxlen ) {
maxlen = len ;
}
if ( len < minlen ) {
minlen = len ;
}
2006-07-16 15:56:00 +00:00
break ;
2003-02-08 15:26:17 +00:00
case HASH_KEY_IS_LONG :
Z_TYPE ( ctmp ) = IS_LONG ;
Z_LVAL ( ctmp ) = num_key ;
2006-07-16 15:56:00 +00:00
2003-02-08 15:26:17 +00:00
convert_to_string ( & ctmp ) ;
len = Z_STRLEN ( ctmp ) ;
2004-03-18 09:48:37 +00:00
zend_hash_add ( & tmp_hash , Z_STRVAL ( ctmp ) , len + 1 , entry , sizeof ( zval * ) , NULL ) ;
2003-02-08 15:26:17 +00:00
zval_dtor ( & ctmp ) ;
1999-11-20 15:53:18 +00:00
2003-02-08 15:26:17 +00:00
if ( len > maxlen ) {
maxlen = len ;
}
if ( len < minlen ) {
minlen = len ;
}
break ;
1999-11-20 15:53:18 +00:00
}
2000-06-18 10:37:01 +00:00
zend_hash_move_forward_ex ( hash , & hpos ) ;
1999-11-20 15:53:18 +00:00
}
2000-10-12 01:26:26 +00:00
1999-11-20 15:53:18 +00:00
key = emalloc ( maxlen + 1 ) ;
2000-10-12 01:26:26 +00:00
pos = 0 ;
1999-11-20 15:53:18 +00:00
while ( pos < slen ) {
if ( ( pos + maxlen ) > slen ) {
maxlen = slen - pos ;
}
2001-09-04 06:18:11 +00:00
1999-11-20 15:53:18 +00:00
found = 0 ;
2001-08-11 17:03:37 +00:00
memcpy ( key , str + pos , maxlen ) ;
1999-11-20 15:53:18 +00:00
for ( len = maxlen ; len > = minlen ; len - - ) {
2001-09-04 06:18:11 +00:00
key [ len ] = 0 ;
2006-07-16 15:56:00 +00:00
2004-03-18 09:48:37 +00:00
if ( zend_hash_find ( & tmp_hash , key , len + 1 , ( void * * ) & trans ) = = SUCCESS ) {
1999-11-20 15:53:18 +00:00
char * tval ;
int tlen ;
zval tmp ;
2001-09-04 06:18:11 +00:00
if ( Z_TYPE_PP ( trans ) ! = IS_STRING ) {
1999-11-20 15:53:18 +00:00
tmp = * * trans ;
zval_copy_ctor ( & tmp ) ;
convert_to_string ( & tmp ) ;
2001-09-04 06:18:11 +00:00
tval = Z_STRVAL ( tmp ) ;
tlen = Z_STRLEN ( tmp ) ;
1999-11-20 15:53:18 +00:00
} else {
2001-09-04 06:18:11 +00:00
tval = Z_STRVAL_PP ( trans ) ;
tlen = Z_STRLEN_PP ( trans ) ;
1999-11-20 15:53:18 +00:00
}
2000-10-12 01:26:26 +00:00
smart_str_appendl ( & result , tval , tlen ) ;
1999-11-20 15:53:18 +00:00
pos + = len ;
found = 1 ;
2001-09-04 06:18:11 +00:00
if ( Z_TYPE_PP ( trans ) ! = IS_STRING ) {
1999-11-20 15:53:18 +00:00
zval_dtor ( & tmp ) ;
}
break ;
2006-07-16 15:56:00 +00:00
}
1999-11-20 15:53:18 +00:00
}
if ( ! found ) {
2000-10-12 01:26:26 +00:00
smart_str_appendc ( & result , str [ pos + + ] ) ;
1999-11-20 15:53:18 +00:00
}
}
efree ( key ) ;
2004-03-18 09:48:37 +00:00
zend_hash_destroy ( & tmp_hash ) ;
2000-10-12 01:26:26 +00:00
smart_str_0 ( & result ) ;
2001-08-11 17:03:37 +00:00
RETVAL_STRINGL ( result . c , result . len , 0 ) ;
1999-11-20 15:53:18 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-11-20 15:53:18 +00:00
2006-11-30 21:20:56 +00:00
/* {{{ proto string strtr(string str, string from[, string to]) U
2001-09-04 10:44:28 +00:00
Translates characters in str using given translation tables */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strtr )
2006-07-16 15:56:00 +00:00
{
2008-10-21 22:06:49 +00:00
zstr str , to = NULL_ZSTR ;
int str_len , to_len = 0 ;
2008-08-16 21:16:25 +00:00
zend_uchar str_type , to_type ;
zval * * from ;
2000-06-05 19:47:54 +00:00
int ac = ZEND_NUM_ARGS ( ) ;
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TZ|T " , & str , & str_len , & str_type , & from ,
& to , & to_len , & to_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2001-09-25 21:58:48 +00:00
if ( ac = = 2 & & Z_TYPE_PP ( from ) ! = IS_ARRAY ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The second argument is not an array " ) ;
1999-11-20 15:53:18 +00:00
RETURN_FALSE ;
}
2000-12-13 10:22:36 +00:00
/* shortcut for empty string */
2008-08-16 21:16:25 +00:00
if ( str_len = = 0 ) {
if ( str_type = = IS_UNICODE ) {
RETURN_EMPTY_UNICODE ( ) ;
} else {
RETURN_EMPTY_STRING ( ) ;
}
2000-12-13 10:22:36 +00:00
}
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE ) {
2008-01-21 14:37:19 +00:00
int outlen = 0 ;
2006-03-26 02:15:47 +00:00
UChar * outstr ;
2006-03-17 14:29:05 +00:00
if ( ac = = 2 ) {
2008-01-21 14:37:19 +00:00
int minlen = 0 , maxlen = 0 ;
2006-03-26 02:15:47 +00:00
HashTable * hash ;
2006-07-16 15:56:00 +00:00
2006-03-27 06:02:42 +00:00
hash = php_u_strtr_array_prepare_hashtable ( HASH_OF ( * from ) , & minlen , & maxlen TSRMLS_CC ) ;
2008-01-21 14:37:19 +00:00
if ( hash ) {
2008-08-16 21:16:25 +00:00
outstr = php_u_strtr_array ( str . u , str_len , hash , minlen , maxlen , & outlen TSRMLS_CC ) ;
2008-01-21 14:37:19 +00:00
zend_hash_destroy ( hash ) ;
efree ( hash ) ;
RETVAL_UNICODEL ( outstr , outlen , 0 ) ;
Z_TYPE_P ( return_value ) = IS_UNICODE ;
} else {
2008-08-16 21:16:25 +00:00
RETURN_UNICODEL ( str . u , str_len , 1 ) ;
2008-01-21 14:37:19 +00:00
}
2006-03-17 14:29:05 +00:00
} else {
convert_to_unicode_ex ( from ) ;
2008-08-16 21:16:25 +00:00
outstr = php_u_strtr ( str . u , str_len , Z_USTRVAL_PP ( from ) , Z_USTRLEN_PP ( from ) , to . u , to_len ,
MIN ( Z_USTRLEN_PP ( from ) , to_len ) , & outlen TSRMLS_CC ) ;
if ( str . u = = outstr ) {
2008-01-21 14:37:19 +00:00
ZVAL_UNICODEL ( return_value , outstr , outlen , 1 ) ;
} else {
ZVAL_UNICODEL ( return_value , outstr , outlen , 0 ) ;
}
2006-03-17 14:29:05 +00:00
}
1999-11-20 15:53:18 +00:00
} else {
2006-03-17 14:29:05 +00:00
if ( ac = = 2 ) {
2008-08-16 21:16:25 +00:00
php_strtr_array ( return_value , str . s , str_len , HASH_OF ( * from ) ) ;
2006-03-17 14:29:05 +00:00
} else {
convert_to_string_ex ( from ) ;
1999-11-20 15:53:18 +00:00
2008-08-16 21:16:25 +00:00
ZVAL_STRINGL ( return_value , str . s , str_len , 1 ) ;
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
php_strtr ( Z_STRVAL_P ( return_value ) , Z_STRLEN_P ( return_value ) , Z_STRVAL_PP ( from ) , to . s , MIN ( Z_STRLEN_PP ( from ) , to_len ) ) ;
2006-03-17 14:29:05 +00:00
}
1999-11-20 15:53:18 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string strrev(string str) U
1999-04-17 00:37:12 +00:00
Reverse a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( strrev )
1999-04-17 00:37:12 +00:00
{
2006-08-03 23:09:29 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-13 17:55:50 +00:00
char * s , * e , * n = NULL , * p ;
2005-08-26 10:21:07 +00:00
int32_t i , x1 , x2 ;
UChar32 ch ;
2006-07-13 17:55:50 +00:00
UChar * u_s , * u_n = NULL , * u_p ;
2006-07-16 15:56:00 +00:00
2006-08-03 23:09:29 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2005-08-19 10:59:19 +00:00
}
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE ) {
u_n = eumalloc ( str_len + 1 ) ;
2005-08-19 10:59:19 +00:00
u_p = u_n ;
2006-08-03 23:09:29 +00:00
u_s = str . u ;
2005-08-19 10:59:19 +00:00
2006-08-03 23:09:29 +00:00
i = str_len ;
2005-08-26 10:21:07 +00:00
while ( i > 0 ) {
U16_PREV ( u_s , 0 , i , ch ) ;
if ( u_getCombiningClass ( ch ) = = 0 ) {
u_p + = zend_codepoint_to_uchar ( ch , u_p ) ;
2005-08-19 10:59:19 +00:00
} else {
2005-08-26 10:21:07 +00:00
x2 = i ;
do {
U16_PREV ( u_s , 0 , i , ch ) ;
} while ( u_getCombiningClass ( ch ) ! = 0 ) ;
x1 = i ;
while ( x1 < = x2 ) {
2006-08-03 23:09:29 +00:00
U16_NEXT ( u_s , x1 , str_len , ch ) ;
2005-08-26 10:21:07 +00:00
u_p + = zend_codepoint_to_uchar ( ch , u_p ) ;
}
2005-08-19 10:59:19 +00:00
}
}
* u_p = 0 ;
} else {
2006-08-03 23:09:29 +00:00
n = emalloc ( str_len + 1 ) ;
2005-08-19 10:59:19 +00:00
p = n ;
2006-08-03 23:09:29 +00:00
s = str . s ;
e = s + str_len ;
2005-08-19 10:59:19 +00:00
while ( - - e > = s ) {
* ( p + + ) = * e ;
}
* p = ' \0 ' ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-03 23:09:29 +00:00
if ( str_type = = IS_UNICODE ) {
RETVAL_UNICODEL ( u_n , str_len , 0 ) ;
2005-08-19 10:59:19 +00:00
} else {
2006-08-03 23:09:29 +00:00
RETVAL_STRINGL ( n , str_len , 0 ) ;
2005-08-19 10:59:19 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2005-10-03 06:14:10 +00:00
/* {{{ php_u_similar_str
*/
2006-03-02 13:12:45 +00:00
static void php_u_similar_str ( const UChar * txt1 , int len1 ,
const UChar * txt2 , int len2 ,
int * pos1 , int * end1 ,
int * pos2 , int * end2 , int * max )
2005-10-03 06:14:10 +00:00
{
int32_t i1 , i2 , j1 , j2 , l ;
UChar32 ch1 , ch2 ;
* max = 0 ;
for ( i1 = 0 ; i1 < len1 ; ) {
for ( i2 = 0 ; i2 < len2 ; ) {
l = 0 ; j1 = 0 ; j2 = 0 ;
while ( ( i1 + j1 < len1 ) & & ( i2 + j2 < len2 ) ) {
U16_NEXT ( txt1 + i1 , j1 , len1 - i1 , ch1 ) ;
U16_NEXT ( txt2 + i2 , j2 , len2 - i2 , ch2 ) ;
if ( ch1 ! = ch2 ) {
U16_BACK_1 ( txt1 + i1 , 0 , j1 ) ;
U16_BACK_1 ( txt2 + i2 , 0 , j2 ) ;
break ;
}
l + + ;
}
if ( l > * max ) {
* max = l ;
* pos1 = i1 ; * end1 = j1 ;
* pos2 = i2 ; * end2 = j2 ;
}
U16_FWD_1 ( txt2 , i2 , len2 ) ;
}
U16_FWD_1 ( txt1 , i1 , len1 ) ;
}
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_similar_str
*/
2003-02-08 15:26:17 +00:00
static void php_similar_str ( const char * txt1 , int len1 , const char * txt2 , int len2 , int * pos1 , int * pos2 , int * max )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
{
char * p , * q ;
char * end1 = ( char * ) txt1 + len1 ;
char * end2 = ( char * ) txt2 + len2 ;
int l ;
2006-07-16 15:56:00 +00:00
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
* max = 0 ;
for ( p = ( char * ) txt1 ; p < end1 ; p + + ) {
for ( q = ( char * ) txt2 ; q < end2 ; q + + ) {
2002-10-10 18:41:24 +00:00
for ( l = 0 ; ( p + l < end1 ) & & ( q + l < end2 ) & & ( p [ l ] = = q [ l ] ) ; l + + ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( l > * max ) {
* max = l ;
* pos1 = p - txt1 ;
* pos2 = q - txt2 ;
}
}
}
}
2001-06-05 13:12:10 +00:00
/* }}} */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2005-10-04 06:33:10 +00:00
/* {{{ php_similar_char
2005-10-03 06:14:10 +00:00
*/
2005-10-04 06:33:10 +00:00
static int php_similar_char ( const char * txt1 , int len1 , const char * txt2 , int len2 )
2005-10-03 06:14:10 +00:00
{
2005-10-04 06:33:10 +00:00
int sum ;
int pos1 , pos2 , max ;
2005-10-03 06:14:10 +00:00
2005-10-04 06:33:10 +00:00
php_similar_str ( txt1 , len1 , txt2 , len2 , & pos1 , & pos2 , & max ) ;
2005-10-03 06:14:10 +00:00
if ( ( sum = max ) ) {
if ( pos1 & & pos2 ) {
2006-07-16 15:56:00 +00:00
sum + = php_similar_char ( txt1 , pos1 ,
2005-10-04 06:33:10 +00:00
txt2 , pos2 ) ;
2005-10-03 06:14:10 +00:00
}
2005-10-04 06:33:10 +00:00
if ( ( pos1 + max < len1 ) & & ( pos2 + max < len2 ) ) {
2006-07-16 15:56:00 +00:00
sum + = php_similar_char ( txt1 + pos1 + max , len1 - pos1 - max ,
2005-10-04 06:33:10 +00:00
txt2 + pos2 + max , len2 - pos2 - max ) ;
2005-10-03 06:14:10 +00:00
}
}
2005-10-04 06:33:10 +00:00
2005-10-03 06:14:10 +00:00
return sum ;
}
/* }}} */
2005-10-04 06:33:10 +00:00
/* {{{ php_u_similar_char
2001-06-05 13:12:10 +00:00
*/
2006-03-02 13:12:45 +00:00
static int php_u_similar_char ( const UChar * txt1 , int len1 , const UChar * txt2 , int len2 )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
{
2005-10-04 06:33:10 +00:00
int sum , max ;
2006-03-02 13:12:45 +00:00
int pos1 , pos2 , end1 , end2 ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2005-10-04 06:33:10 +00:00
php_u_similar_str ( txt1 , len1 , txt2 , len2 , & pos1 , & end1 , & pos2 , & end2 , & max ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( ( sum = max ) ) {
2003-02-08 15:26:17 +00:00
if ( pos1 & & pos2 ) {
2005-10-04 06:33:10 +00:00
sum + = php_u_similar_char ( txt1 , pos1 , txt2 , pos2 ) ;
2003-02-08 15:26:17 +00:00
}
2005-10-04 06:33:10 +00:00
if ( ( pos1 + end1 < len1 ) & & ( pos2 + end2 < len2 ) ) {
2006-08-02 21:53:43 +00:00
sum + = php_u_similar_char ( ( UChar * ) txt1 + pos1 + end1 , len1 - pos1 - end1 ,
2005-10-04 06:33:10 +00:00
( UChar * ) txt2 + pos2 + end2 , len2 - pos2 - end2 ) ;
2003-02-08 15:26:17 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
return sum ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto int similar_text(string str1, string str2 [, float percent]) U
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
Calculates the similarity between two strings */
PHP_FUNCTION ( similar_text )
{
2006-08-03 21:46:16 +00:00
zstr t1 , t2 ;
int t1_len , t2_len ;
zend_uchar t1_type , t2_type ;
zval * percent = NULL ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
int sim ;
2005-10-03 06:14:10 +00:00
2006-08-03 21:46:16 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT|z " , & t1 , & t1_len ,
& t1_type , & t2 , & t2_len , & t2_type , & percent ) = = FAILURE ) {
2006-01-17 12:18:53 +00:00
return ;
2005-10-03 06:14:10 +00:00
}
2006-08-03 21:46:16 +00:00
if ( percent ) {
zval_dtor ( percent ) ;
Z_TYPE_P ( percent ) = IS_DOUBLE ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2005-10-03 06:14:10 +00:00
2006-08-03 21:46:16 +00:00
if ( t1_len + t2_len = = 0 ) {
if ( percent ) {
Z_DVAL_P ( percent ) = 0 ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2001-09-04 06:18:11 +00:00
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
RETURN_LONG ( 0 ) ;
}
2005-10-03 06:14:10 +00:00
2006-08-03 21:46:16 +00:00
/* t1_type and t2_type are guaranteed to be the same */
if ( t1_type = = IS_UNICODE ) {
sim = php_u_similar_char ( t1 . u , t1_len , t2 . u , t2_len ) ;
2005-10-03 06:14:10 +00:00
} else {
2006-08-03 21:46:16 +00:00
sim = php_similar_char ( t1 . s , t1_len , t2 . s , t2_len ) ;
2005-10-03 06:14:10 +00:00
}
2002-09-11 14:40:52 +00:00
2006-08-03 21:46:16 +00:00
if ( percent ) {
if ( t1_type = = IS_UNICODE ) {
Z_DVAL_P ( percent ) = sim * 200.0 / ( u_countChar32 ( t1 . u , t1_len ) + u_countChar32 ( t2 . u , t2_len ) ) ;
2005-10-03 06:14:10 +00:00
} else {
2006-08-03 21:46:16 +00:00
Z_DVAL_P ( percent ) = sim * 200.0 / ( t1_len + t2_len ) ;
2005-10-03 06:14:10 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2001-09-04 06:18:11 +00:00
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
RETURN_LONG ( sim ) ;
}
/* }}} */
1999-04-17 00:37:12 +00:00
2005-09-28 09:22:08 +00:00
/* {{{ php_u_stripslashes
*
* be careful , this edits the string in - place */
2006-03-02 13:12:45 +00:00
PHPAPI void php_u_stripslashes ( UChar * str , int * len TSRMLS_DC )
2005-09-28 09:22:08 +00:00
{
2006-03-02 13:12:45 +00:00
int32_t tmp_len = 0 , i = 0 , src_len = * len ;
2005-09-28 09:22:08 +00:00
UChar32 ch1 , ch2 ;
ch1 = - 1 ; ch2 = - 1 ;
2006-03-08 00:43:32 +00:00
while ( i < src_len ) {
U16_NEXT ( str , i , src_len , ch1 ) ;
if ( ch1 = = ' \\ ' ) {
if ( i < src_len ) {
U16_NEXT ( str , i , src_len , ch2 ) ;
if ( ch2 = = ' 0 ' ) {
tmp_len + = zend_codepoint_to_uchar ( ' \0 ' , str + tmp_len ) ;
2005-09-28 09:22:08 +00:00
} else {
2006-03-08 00:43:32 +00:00
tmp_len + = zend_codepoint_to_uchar ( ch2 , str + tmp_len ) ;
2005-09-28 09:22:08 +00:00
}
}
2006-03-08 00:43:32 +00:00
} else {
tmp_len + = zend_codepoint_to_uchar ( ch1 , str + tmp_len ) ;
2005-09-28 09:22:08 +00:00
}
}
* ( str + tmp_len ) = 0 ;
str = eurealloc ( str , tmp_len + 1 ) ;
* len = tmp_len ;
return ;
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_stripslashes
*
* be careful , this edits the string in - place */
2001-08-06 03:50:52 +00:00
PHPAPI void php_stripslashes ( char * str , int * len TSRMLS_DC )
1999-04-17 00:37:12 +00:00
{
char * s , * t ;
int l ;
if ( len ! = NULL ) {
l = * len ;
} else {
2000-02-08 22:21:43 +00:00
l = strlen ( str ) ;
1999-04-17 00:37:12 +00:00
}
2000-02-08 22:21:43 +00:00
s = str ;
t = str ;
2002-03-27 20:20:57 +00:00
1999-04-17 00:37:12 +00:00
while ( l > 0 ) {
2002-06-18 11:51:06 +00:00
if ( * t = = ' \\ ' ) {
1999-04-17 00:37:12 +00:00
t + + ; /* skip the slash */
2003-02-08 15:26:17 +00:00
if ( len ! = NULL ) {
1999-04-17 00:37:12 +00:00
( * len ) - - ;
2003-02-08 15:26:17 +00:00
}
1999-04-17 00:37:12 +00:00
l - - ;
if ( l > 0 ) {
2002-10-02 17:56:04 +00:00
if ( * t = = ' 0 ' ) {
1999-04-17 00:37:12 +00:00
* s + + = ' \0 ' ;
t + + ;
} else {
* s + + = * t + + ; /* preserve the next character */
}
l - - ;
}
} else {
2003-03-31 12:08:31 +00:00
* s + + = * t + + ;
1999-04-17 00:37:12 +00:00
l - - ;
}
}
if ( s ! = t ) {
* s = ' \0 ' ;
}
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-08-09 17:40:21 +00:00
/* {{{ proto binary addcslashes(binary str, binary charlist) U
2001-09-04 10:44:28 +00:00
Escapes all chars mentioned in charlist with backslash . It creates octal representations if asked to backslash characters with 8 th bit set or with ASCII < 32 ( except ' \n ' , ' \r ' , ' \t ' etc . . . ) */
1999-09-05 20:55:13 +00:00
PHP_FUNCTION ( addcslashes )
{
2006-08-09 17:40:21 +00:00
char * str , * what ;
int str_len , what_len ;
1999-09-05 20:55:13 +00:00
2006-08-09 18:15:06 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " SS " , & str , & str_len ,
2006-08-09 17:40:21 +00:00
& what , & what_len ) = = FAILURE ) {
return ;
1999-09-05 20:55:13 +00:00
}
2000-09-17 09:15:48 +00:00
2006-08-09 17:40:21 +00:00
if ( str_len = = 0 ) {
2000-09-17 09:15:48 +00:00
RETURN_EMPTY_STRING ( ) ;
}
2006-08-09 17:40:21 +00:00
if ( what_len = = 0 ) {
RETURN_STRINGL ( str , str_len , 1 ) ;
2000-09-17 09:15:48 +00:00
}
2007-03-26 10:23:50 +00:00
Z_STRVAL_P ( return_value ) = php_addcslashes ( str , str_len , & Z_STRLEN_P ( return_value ) , 0 , what , what_len TSRMLS_CC ) ;
RETURN_STRINGL ( Z_STRVAL_P ( return_value ) , Z_STRLEN_P ( return_value ) , 0 ) ;
1999-09-05 20:55:13 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string addslashes(string str) U
2001-09-04 10:44:28 +00:00
Escapes single quote , double quotes and backslash characters in a string with backslashes */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( addslashes )
1999-04-17 00:37:12 +00:00
{
2008-08-16 21:16:25 +00:00
zstr str ;
int str_len , tmp_len = 0 ;
zend_uchar str_type ;
2005-09-28 09:22:08 +00:00
void * tmp = NULL ;
1999-04-17 00:37:12 +00:00
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2000-09-17 09:15:48 +00:00
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE & & str_len = = 0 ) {
2005-09-28 09:22:08 +00:00
RETURN_EMPTY_UNICODE ( ) ;
2008-08-16 21:16:25 +00:00
} else if ( str_type = = IS_STRING & & str_len = = 0 ) {
2000-09-17 09:15:48 +00:00
RETURN_EMPTY_STRING ( ) ;
}
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE ) {
tmp = ( UChar * ) php_u_addslashes ( str . u , str_len , & tmp_len , 0 TSRMLS_CC ) ;
2005-09-28 09:22:08 +00:00
RETURN_UNICODEL ( ( UChar * ) tmp , tmp_len , 0 ) ;
} else {
2008-08-16 21:16:25 +00:00
tmp = ( char * ) php_addslashes ( str . s , str_len , & tmp_len , 0 TSRMLS_CC ) ;
2006-01-17 12:18:53 +00:00
RETURN_STRINGL ( ( char * ) tmp , tmp_len , 0 ) ;
2005-09-28 09:22:08 +00:00
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-08-09 17:40:21 +00:00
/* {{{ proto binary stripcslashes(binary str) U
2001-09-04 10:44:28 +00:00
Strips backslashes from a string . Uses C - style conventions */
1999-09-05 20:55:13 +00:00
PHP_FUNCTION ( stripcslashes )
{
2006-08-09 17:40:21 +00:00
char * str ;
int str_len ;
2006-07-16 15:56:00 +00:00
2006-08-09 18:15:06 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S " , & str , & str_len ) = = FAILURE ) {
2006-08-09 17:40:21 +00:00
return ;
1999-09-05 20:55:13 +00:00
}
2006-08-09 17:40:21 +00:00
ZVAL_STRINGL ( return_value , str , str_len , 1 ) ;
2001-09-04 06:18:11 +00:00
php_stripcslashes ( Z_STRVAL_P ( return_value ) , & Z_STRLEN_P ( return_value ) ) ;
1999-09-05 20:55:13 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string stripslashes(string str) U
2001-09-04 10:44:28 +00:00
Strips backslashes from a string */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( stripslashes )
1999-04-17 00:37:12 +00:00
{
2008-08-16 21:16:25 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE ) {
ZVAL_UNICODEL ( return_value , str . u , str_len , 1 ) ;
2005-09-28 09:22:08 +00:00
php_u_stripslashes ( Z_USTRVAL_P ( return_value ) , & Z_USTRLEN_P ( return_value ) TSRMLS_CC ) ;
} else {
2008-08-16 21:16:25 +00:00
ZVAL_STRINGL ( return_value , str . s , str_len , 1 ) ;
2005-09-28 09:22:08 +00:00
php_stripslashes ( Z_STRVAL_P ( return_value ) , & Z_STRLEN_P ( return_value ) TSRMLS_CC ) ;
}
1999-04-17 00:37:12 +00:00
}
/* }}} */
# ifndef HAVE_STRERROR
2001-06-05 13:12:10 +00:00
/* {{{ php_strerror
*/
2006-07-16 15:56:00 +00:00
char * php_strerror ( int errnum )
1999-04-17 00:37:12 +00:00
{
extern int sys_nerr ;
extern char * sys_errlist [ ] ;
2001-07-28 11:36:37 +00:00
TSRMLS_FETCH ( ) ;
1999-04-17 00:37:12 +00:00
2003-02-08 15:26:17 +00:00
if ( ( unsigned int ) errnum < sys_nerr ) {
return ( sys_errlist [ errnum ] ) ;
}
2007-02-24 16:25:58 +00:00
( void ) snprintf ( BG ( str_ebuf ) , sizeof ( php_basic_globals . str_ebuf ) , " Unknown error: %d " , errnum ) ;
1999-11-28 00:31:02 +00:00
return ( BG ( str_ebuf ) ) ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
# endif
2001-06-05 13:12:10 +00:00
/* {{{ php_stripcslashes
*/
1999-09-05 20:55:13 +00:00
PHPAPI void php_stripcslashes ( char * str , int * len )
{
2001-08-11 17:03:37 +00:00
char * source , * target , * end ;
1999-09-05 20:55:13 +00:00
int nlen = * len , i ;
char numtmp [ 4 ] ;
2002-10-02 17:56:04 +00:00
for ( source = str , end = str + nlen , target = str ; source < end ; source + + ) {
if ( * source = = ' \\ ' & & source + 1 < end ) {
1999-09-05 20:55:13 +00:00
source + + ;
switch ( * source ) {
2003-02-08 15:26:17 +00:00
case ' n ' : * target + + = ' \n ' ; nlen - - ; break ;
case ' r ' : * target + + = ' \r ' ; nlen - - ; break ;
case ' a ' : * target + + = ' \a ' ; nlen - - ; break ;
case ' t ' : * target + + = ' \t ' ; nlen - - ; break ;
case ' v ' : * target + + = ' \v ' ; nlen - - ; break ;
case ' b ' : * target + + = ' \b ' ; nlen - - ; break ;
case ' f ' : * target + + = ' \f ' ; nlen - - ; break ;
1999-09-05 20:55:13 +00:00
case ' \\ ' : * target + + = ' \\ ' ; nlen - - ; break ;
2003-02-08 15:26:17 +00:00
case ' x ' :
if ( source + 1 < end & & isxdigit ( ( int ) ( * ( source + 1 ) ) ) ) {
1999-09-05 20:55:13 +00:00
numtmp [ 0 ] = * + + source ;
2002-10-02 17:56:04 +00:00
if ( source + 1 < end & & isxdigit ( ( int ) ( * ( source + 1 ) ) ) ) {
1999-09-05 20:55:13 +00:00
numtmp [ 1 ] = * + + source ;
numtmp [ 2 ] = ' \0 ' ;
nlen - = 3 ;
} else {
numtmp [ 1 ] = ' \0 ' ;
nlen - = 2 ;
}
1999-09-07 20:29:31 +00:00
* target + + = ( char ) strtol ( numtmp , NULL , 16 ) ;
1999-09-05 20:55:13 +00:00
break ;
}
/* break is left intentionally */
2006-07-16 15:56:00 +00:00
default :
i = 0 ;
2002-10-02 17:56:04 +00:00
while ( source < end & & * source > = ' 0 ' & & * source < = ' 7 ' & & i < 3 ) {
1999-09-05 20:55:13 +00:00
numtmp [ i + + ] = * source + + ;
}
if ( i ) {
numtmp [ i ] = ' \0 ' ;
1999-09-07 20:29:31 +00:00
* target + + = ( char ) strtol ( numtmp , NULL , 8 ) ;
1999-09-05 20:55:13 +00:00
nlen - = i ;
source - - ;
} else {
* target + + = * source ;
2000-06-09 13:58:10 +00:00
nlen - - ;
1999-09-05 20:55:13 +00:00
}
}
} else {
* target + + = * source ;
}
}
2000-07-17 10:22:30 +00:00
2002-10-02 17:56:04 +00:00
if ( nlen ! = 0 ) {
2000-07-17 10:22:30 +00:00
* target = ' \0 ' ;
}
1999-09-05 20:55:13 +00:00
* len = nlen ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
2006-07-16 15:56:00 +00:00
2001-06-05 13:12:10 +00:00
/* {{{ php_addcslashes
*/
2001-08-06 03:50:52 +00:00
PHPAPI char * php_addcslashes ( char * str , int length , int * new_length , int should_free , char * what , int wlength TSRMLS_DC )
1999-09-05 00:55:48 +00:00
{
char flags [ 256 ] ;
2003-08-11 23:16:54 +00:00
char * new_str = safe_emalloc ( 4 , ( length ? length : ( length = strlen ( str ) ) ) , 1 ) ;
2001-08-11 17:03:37 +00:00
char * source , * target ;
1999-09-05 00:55:48 +00:00
char * end ;
char c ;
1999-09-05 20:55:13 +00:00
int newlen ;
1999-09-05 00:55:48 +00:00
if ( ! wlength ) {
wlength = strlen ( what ) ;
}
if ( ! length ) {
length = strlen ( str ) ;
}
2006-03-02 13:12:45 +00:00
php_charmask ( ( unsigned char * ) what , wlength , flags TSRMLS_CC ) ;
1999-09-05 00:55:48 +00:00
2007-05-24 20:56:20 +00:00
for ( source = str , end = source + length , target = new_str ; source < end ; source + + ) {
2007-05-24 21:31:35 +00:00
c = * source ;
1999-09-05 20:55:13 +00:00
if ( flags [ ( unsigned char ) c ] ) {
2003-02-08 15:26:17 +00:00
if ( ( unsigned char ) c < 32 | | ( unsigned char ) c > 126 ) {
1999-09-05 00:55:48 +00:00
* target + + = ' \\ ' ;
switch ( c ) {
case ' \n ' : * target + + = ' n ' ; break ;
case ' \t ' : * target + + = ' t ' ; break ;
case ' \r ' : * target + + = ' r ' ; break ;
1999-09-05 20:55:13 +00:00
case ' \a ' : * target + + = ' a ' ; break ;
case ' \v ' : * target + + = ' v ' ; break ;
case ' \b ' : * target + + = ' b ' ; break ;
case ' \f ' : * target + + = ' f ' ; break ;
2003-02-08 15:26:17 +00:00
default : target + = sprintf ( target , " %03o " , ( unsigned char ) c ) ;
1999-09-05 00:55:48 +00:00
}
1999-09-05 20:55:13 +00:00
continue ;
2006-07-16 15:56:00 +00:00
}
1999-09-05 20:55:13 +00:00
* target + + = ' \\ ' ;
}
* target + + = c ;
1999-09-05 00:55:48 +00:00
}
* target = 0 ;
2003-02-08 15:26:17 +00:00
newlen = target - new_str ;
if ( target - new_str < length * 4 ) {
new_str = erealloc ( new_str , newlen + 1 ) ;
1999-09-05 20:55:13 +00:00
}
1999-09-05 00:55:48 +00:00
if ( new_length ) {
1999-09-05 20:55:13 +00:00
* new_length = newlen ;
1999-09-05 00:55:48 +00:00
}
if ( should_free ) {
STR_FREE ( str ) ;
}
return new_str ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2005-09-28 09:22:08 +00:00
/* {{{ php_u_addslashes
*/
2006-03-02 13:12:45 +00:00
PHPAPI UChar * php_u_addslashes ( UChar * str , int length , int * new_length , int should_free TSRMLS_DC )
2005-09-28 09:22:08 +00:00
{
2009-05-23 18:03:27 +00:00
return php_u_addslashes_ex ( str , length , new_length , should_free TSRMLS_CC ) ;
2005-09-28 09:22:08 +00:00
}
2005-10-15 12:50:20 +00:00
/* }}} */
2005-09-28 09:22:08 +00:00
/* {{{ php_u_addslashes_ex
*/
2009-05-23 18:03:27 +00:00
PHPAPI UChar * php_u_addslashes_ex ( UChar * str , int length , int * new_length , int should_free TSRMLS_DC )
2005-09-28 09:22:08 +00:00
{
UChar * buf ;
int32_t buf_len = 0 , i = 0 ;
UChar32 ch ;
if ( ! new_length ) {
new_length = & buf_len ;
}
if ( ! str ) {
* new_length = 0 ;
return str ;
}
2006-06-30 09:35:21 +00:00
buf = eumalloc ( length * 2 + 1 ) ;
2006-03-08 00:43:32 +00:00
while ( i < length ) {
U16_NEXT ( str , i , length , ch ) ;
switch ( ch ) {
2005-09-28 09:22:08 +00:00
case ' \0 ' :
2005-09-29 09:33:38 +00:00
* ( buf + buf_len ) = ( UChar ) 0x5C ; buf_len + + ; /* \ */
* ( buf + buf_len ) = ( UChar ) 0x30 ; buf_len + + ; /* 0 */
2005-09-28 09:22:08 +00:00
break ;
case ' \' ' :
2006-12-04 18:55:40 +00:00
case ' \" ' :
2005-09-28 09:22:08 +00:00
case ' \\ ' :
2006-03-08 00:43:32 +00:00
* ( buf + buf_len ) = ( UChar ) 0x5C ; buf_len + + ; /* \ */
/* break is missing *intentionally* */
2005-09-28 09:22:08 +00:00
default :
2006-03-08 00:43:32 +00:00
buf_len + = zend_codepoint_to_uchar ( ch , buf + buf_len ) ;
2006-07-16 15:56:00 +00:00
break ;
2005-09-28 09:22:08 +00:00
}
}
2006-03-08 00:43:32 +00:00
2005-09-28 09:22:08 +00:00
* ( buf + buf_len ) = 0 ;
if ( should_free ) {
STR_FREE ( str ) ;
}
buf = eurealloc ( buf , buf_len + 1 ) ;
* new_length = buf_len ;
return buf ;
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_addslashes
*/
2001-08-06 03:50:52 +00:00
PHPAPI char * php_addslashes ( char * str , int length , int * new_length , int should_free TSRMLS_DC )
2005-05-31 12:54:56 +00:00
{
2009-05-23 18:03:27 +00:00
return php_addslashes_ex ( str , length , new_length , should_free TSRMLS_CC ) ;
2005-05-31 12:54:56 +00:00
}
/* }}} */
/* {{{ php_addslashes_ex
*/
2009-05-23 18:03:27 +00:00
PHPAPI char * php_addslashes_ex ( char * str , int length , int * new_length , int should_free TSRMLS_DC )
1999-04-17 00:37:12 +00:00
{
/* maximum string length, worst case situation */
2000-02-02 21:53:27 +00:00
char * new_str ;
2001-08-11 17:03:37 +00:00
char * source , * target ;
1999-04-17 00:37:12 +00:00
char * end ;
2002-10-22 18:27:56 +00:00
int local_new_length ;
2006-07-16 15:56:00 +00:00
2002-10-22 18:27:56 +00:00
if ( ! new_length ) {
new_length = & local_new_length ;
}
2000-02-02 21:53:27 +00:00
if ( ! str ) {
* new_length = 0 ;
return str ;
}
2003-08-11 23:16:54 +00:00
new_str = ( char * ) safe_emalloc ( 2 , ( length ? length : ( length = strlen ( str ) ) ) , 1 ) ;
2002-10-09 13:37:02 +00:00
source = str ;
end = source + length ;
target = new_str ;
2006-07-16 15:56:00 +00:00
2006-03-08 00:43:32 +00:00
while ( source < end ) {
switch ( * source ) {
case ' \0 ' :
* target + + = ' \\ ' ;
* target + + = ' 0 ' ;
break ;
case ' \' ' :
2002-03-12 07:05:40 +00:00
case ' \" ' :
2006-03-08 00:43:32 +00:00
case ' \\ ' :
2002-03-12 07:05:40 +00:00
* target + + = ' \\ ' ;
/* break is missing *intentionally* */
2006-03-08 00:43:32 +00:00
default :
2002-10-09 13:37:02 +00:00
* target + + = * source ;
2006-07-16 15:56:00 +00:00
break ;
1999-04-17 00:37:12 +00:00
}
2006-03-08 00:43:32 +00:00
source + + ;
1999-04-17 00:37:12 +00:00
}
2006-03-08 00:43:32 +00:00
1999-04-17 00:37:12 +00:00
* target = 0 ;
2002-10-22 18:27:56 +00:00
* new_length = target - new_str ;
1999-04-17 00:37:12 +00:00
if ( should_free ) {
STR_FREE ( str ) ;
}
2003-02-08 15:26:17 +00:00
new_str = ( char * ) erealloc ( new_str , * new_length + 1 ) ;
1999-04-17 00:37:12 +00:00
return new_str ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
# define _HEB_BLOCK_TYPE_ENG 1
# define _HEB_BLOCK_TYPE_HEB 2
2003-02-08 15:26:17 +00:00
# define isheb(c) (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)
# define _isblank(c) (((((unsigned char) c) == ' ' || ((unsigned char) c) == '\t')) ? 1 : 0)
# define _isnewline(c) (((((unsigned char) c) == '\n' || ((unsigned char) c) == '\r')) ? 1 : 0)
1999-04-17 00:37:12 +00:00
2003-07-25 01:03:39 +00:00
/* {{{ php_char_to_str_ex
2001-06-05 13:12:10 +00:00
*/
2003-07-25 01:03:39 +00:00
PHPAPI int php_char_to_str_ex ( char * str , uint len , char from , char * to , int to_len , zval * result , int case_sensitivity , int * replace_count )
1999-04-17 00:37:12 +00:00
{
2001-09-09 12:55:48 +00:00
int char_count = 0 ;
int replaced = 0 ;
char * source , * target , * tmp , * source_end = str + len , * tmp_end = NULL ;
2006-07-16 15:56:00 +00:00
2006-06-10 15:51:23 +00:00
if ( case_sensitivity ) {
char * p = str , * e = p + len ;
while ( ( p = memchr ( p , from , ( e - p ) ) ) ) {
1999-04-17 00:37:12 +00:00
char_count + + ;
2006-06-10 15:51:23 +00:00
p + + ;
}
} else {
for ( source = str ; source < source_end ; source + + ) {
if ( tolower ( * source ) = = tolower ( from ) ) {
char_count + + ;
}
1999-04-17 00:37:12 +00:00
}
}
2004-10-07 23:10:35 +00:00
if ( char_count = = 0 & & case_sensitivity ) {
2001-09-04 06:18:11 +00:00
ZVAL_STRINGL ( result , str , len , 1 ) ;
2001-09-09 12:55:48 +00:00
return 0 ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2001-09-04 06:18:11 +00:00
Z_STRLEN_P ( result ) = len + ( char_count * ( to_len - 1 ) ) ;
2007-02-10 00:48:17 +00:00
Z_STRVAL_P ( result ) = target = safe_emalloc ( char_count , to_len , len + 1 ) ;
2001-09-04 06:18:11 +00:00
Z_TYPE_P ( result ) = IS_STRING ;
2006-06-10 15:51:23 +00:00
if ( case_sensitivity ) {
char * p = str , * e = p + len , * s = str ;
while ( ( p = memchr ( p , from , ( e - p ) ) ) ) {
memcpy ( target , s , ( p - s ) ) ;
target + = p - s ;
memcpy ( target , to , to_len ) ;
target + = to_len ;
p + + ;
s = p ;
2006-10-05 22:40:38 +00:00
if ( replace_count ) {
* replace_count + = 1 ;
}
2006-06-10 15:51:23 +00:00
}
if ( s < e ) {
memcpy ( target , s , ( e - s ) ) ;
target + = e - s ;
}
} else {
for ( source = str ; source < source_end ; source + + ) {
if ( tolower ( * source ) = = tolower ( from ) ) {
replaced = 1 ;
if ( replace_count ) {
* replace_count + = 1 ;
}
for ( tmp = to , tmp_end = tmp + to_len ; tmp < tmp_end ; tmp + + ) {
* target = * tmp ;
target + + ;
}
} else {
* target = * source ;
1999-04-17 00:37:12 +00:00
target + + ;
}
}
}
* target = 0 ;
2001-09-09 12:55:48 +00:00
return replaced ;
1999-04-17 00:37:12 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2003-07-25 01:03:39 +00:00
/* {{{ php_char_to_str
*/
PHPAPI int php_char_to_str ( char * str , uint len , char from , char * to , int to_len , zval * result )
{
return php_char_to_str_ex ( str , len , from , to , to_len , result , 1 , NULL ) ;
}
/* }}} */
2006-10-05 22:40:38 +00:00
/* {{{ php_u_char_to_str_ex */
PHPAPI int php_u_char_to_str_ex ( UChar * str , uint len , UChar from , UChar * to , int to_len , zval * result , int * replace_count )
{
int char_count = 0 ;
int replaced = 0 ;
UChar * target ;
UChar * p , * e , * s ;
p = str ;
e = p + len ;
while ( ( p = u_memchr ( p , from , ( e - p ) ) ) ) {
char_count + + ;
p + + ;
}
if ( char_count = = 0 ) {
ZVAL_UNICODEL ( result , str , len , 1 ) ;
return 0 ;
}
Z_USTRLEN_P ( result ) = len + ( char_count * ( to_len - 1 ) ) ;
Z_USTRVAL_P ( result ) = target = eumalloc ( Z_USTRLEN_P ( result ) + 1 ) ;
Z_TYPE_P ( result ) = IS_UNICODE ;
p = str ;
e = p + len ;
s = str ;
while ( ( p = u_memchr ( p , from , ( e - p ) ) ) ) {
u_memcpy ( target , s , ( p - s ) ) ;
target + = p - s ;
u_memcpy ( target , to , to_len ) ;
target + = to_len ;
p + + ;
s = p ;
if ( replace_count ) {
* replace_count + = 1 ;
}
}
if ( s < e ) {
u_memcpy ( target , s , ( e - s ) ) ;
target + = e - s ;
}
* target = 0 ;
return replaced ;
}
/* }}} */
2003-01-30 05:00:41 +00:00
/* {{{ php_str_to_str_ex
*/
2006-07-16 15:56:00 +00:00
PHPAPI char * php_str_to_str_ex ( char * haystack , int length ,
2003-04-13 22:59:19 +00:00
char * needle , int needle_len , char * str , int str_len , int * _new_length , int case_sensitivity , int * replace_count )
2003-01-30 05:00:41 +00:00
{
char * new_str ;
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( needle_len < length ) {
2004-02-23 20:34:59 +00:00
char * end , * haystack_dup = NULL , * needle_dup = NULL ;
2003-01-30 05:00:41 +00:00
char * e , * s , * p , * r ;
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( needle_len = = str_len ) {
new_str = estrndup ( haystack , length ) ;
* _new_length = length ;
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( case_sensitivity ) {
end = new_str + length ;
for ( p = new_str ; ( r = php_memnstr ( p , needle , needle_len , end ) ) ; p = r + needle_len ) {
memcpy ( r , str , str_len ) ;
2003-04-13 22:59:19 +00:00
if ( replace_count ) {
( * replace_count ) + + ;
}
2003-01-30 05:00:41 +00:00
}
} else {
haystack_dup = estrndup ( haystack , length ) ;
needle_dup = estrndup ( needle , needle_len ) ;
php_strtolower ( haystack_dup , length ) ;
php_strtolower ( needle_dup , needle_len ) ;
end = haystack_dup + length ;
for ( p = haystack_dup ; ( r = php_memnstr ( p , needle_dup , needle_len , end ) ) ; p = r + needle_len ) {
memcpy ( new_str + ( r - haystack_dup ) , str , str_len ) ;
2003-04-13 22:59:19 +00:00
if ( replace_count ) {
( * replace_count ) + + ;
}
2003-01-30 05:00:41 +00:00
}
efree ( haystack_dup ) ;
efree ( needle_dup ) ;
}
return new_str ;
} else {
2004-03-26 19:23:42 +00:00
if ( ! case_sensitivity ) {
haystack_dup = estrndup ( haystack , length ) ;
needle_dup = estrndup ( needle , needle_len ) ;
php_strtolower ( haystack_dup , length ) ;
php_strtolower ( needle_dup , needle_len ) ;
}
2003-01-30 05:00:41 +00:00
if ( str_len < needle_len ) {
new_str = emalloc ( length + 1 ) ;
} else {
2004-02-23 20:06:01 +00:00
int count = 0 ;
2004-02-23 20:34:59 +00:00
char * o , * n , * endp ;
2004-02-23 20:06:01 +00:00
2004-02-23 20:34:59 +00:00
if ( case_sensitivity ) {
o = haystack ;
n = needle ;
} else {
o = haystack_dup ;
n = needle_dup ;
}
endp = o + length ;
while ( ( o = php_memnstr ( o , n , needle_len , endp ) ) ) {
2004-02-23 20:06:01 +00:00
o + = needle_len ;
count + + ;
}
2004-02-23 20:13:14 +00:00
if ( count = = 0 ) {
/* Needle doesn't occur, shortcircuit the actual replacement. */
2004-02-23 20:34:59 +00:00
if ( haystack_dup ) {
efree ( haystack_dup ) ;
}
if ( needle_dup ) {
efree ( needle_dup ) ;
}
2004-02-23 20:13:14 +00:00
new_str = estrndup ( haystack , length ) ;
if ( _new_length ) {
* _new_length = length ;
}
return new_str ;
} else {
new_str = safe_emalloc ( count , str_len - needle_len , length + 1 ) ;
}
2001-07-20 01:22:29 +00:00
}
2003-01-30 05:00:41 +00:00
e = s = new_str ;
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( case_sensitivity ) {
end = haystack + length ;
for ( p = haystack ; ( r = php_memnstr ( p , needle , needle_len , end ) ) ; p = r + needle_len ) {
memcpy ( e , p , r - p ) ;
e + = r - p ;
memcpy ( e , str , str_len ) ;
e + = str_len ;
2003-04-13 22:59:19 +00:00
if ( replace_count ) {
( * replace_count ) + + ;
}
2003-01-30 05:00:41 +00:00
}
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( p < end ) {
memcpy ( e , p , end - p ) ;
e + = end - p ;
}
} else {
end = haystack_dup + length ;
for ( p = haystack_dup ; ( r = php_memnstr ( p , needle_dup , needle_len , end ) ) ; p = r + needle_len ) {
memcpy ( e , haystack + ( p - haystack_dup ) , r - p ) ;
e + = r - p ;
memcpy ( e , str , str_len ) ;
e + = str_len ;
2003-04-13 22:59:19 +00:00
if ( replace_count ) {
( * replace_count ) + + ;
}
2003-01-30 05:00:41 +00:00
}
2001-07-20 01:22:29 +00:00
2003-01-30 05:00:41 +00:00
if ( p < end ) {
memcpy ( e , haystack + ( p - haystack_dup ) , end - p ) ;
e + = end - p ;
}
2004-02-23 20:34:59 +00:00
}
if ( haystack_dup ) {
2003-01-30 05:00:41 +00:00
efree ( haystack_dup ) ;
2004-02-23 20:34:59 +00:00
}
if ( needle_dup ) {
2003-01-30 05:00:41 +00:00
efree ( needle_dup ) ;
}
* e = ' \0 ' ;
* _new_length = e - s ;
new_str = erealloc ( new_str , * _new_length + 1 ) ;
return new_str ;
}
} else if ( needle_len > length ) {
nothing_todo :
* _new_length = length ;
new_str = estrndup ( haystack , length ) ;
return new_str ;
} else {
2006-11-24 21:57:31 +00:00
if ( case_sensitivity & & memcmp ( haystack , needle , length ) ) {
2003-01-30 05:00:41 +00:00
goto nothing_todo ;
2006-11-24 21:57:31 +00:00
} else if ( ! case_sensitivity ) {
char * l_haystack , * l_needle ;
l_haystack = estrndup ( haystack , length ) ;
l_needle = estrndup ( needle , length ) ;
php_strtolower ( l_haystack , length ) ;
php_strtolower ( l_needle , length ) ;
if ( memcmp ( l_haystack , l_needle , length ) ) {
efree ( l_haystack ) ;
efree ( l_needle ) ;
goto nothing_todo ;
2003-04-13 22:59:19 +00:00
}
2006-11-24 21:57:31 +00:00
efree ( l_haystack ) ;
efree ( l_needle ) ;
}
* _new_length = str_len ;
new_str = estrndup ( str , str_len ) ;
if ( replace_count ) {
( * replace_count ) + + ;
2003-01-30 05:00:41 +00:00
}
2006-11-24 21:57:31 +00:00
return new_str ;
2003-01-30 05:00:41 +00:00
}
2001-07-20 01:22:29 +00:00
}
/* }}} */
2006-10-05 22:40:38 +00:00
/* {{{ php_str_to_str */
2006-07-16 15:56:00 +00:00
PHPAPI char * php_str_to_str ( char * haystack , int length ,
1999-04-17 00:37:12 +00:00
char * needle , int needle_len , char * str , int str_len , int * _new_length )
{
2003-04-13 22:59:19 +00:00
return php_str_to_str_ex ( haystack , length , needle , needle_len , str , str_len , _new_length , 1 , NULL ) ;
2006-07-16 15:56:00 +00:00
}
2006-10-05 22:40:38 +00:00
/* }}} */
/* {{{ php_u_str_to_str_ex */
PHPAPI UChar * php_u_str_to_str_ex ( UChar * haystack , int length ,
UChar * needle , int needle_len , UChar * repl , int repl_len , int * _new_length , int * replace_count )
{
UChar * new_str ;
if ( needle_len < length ) {
UChar * end ;
UChar * e , * s , * p , * r ;
if ( needle_len = = repl_len ) {
new_str = eustrndup ( haystack , length ) ;
* _new_length = length ;
end = new_str + length ;
for ( p = new_str ; ( r = zend_u_memnstr ( p , needle , needle_len , end ) ) ; p = r + needle_len ) {
u_memcpy ( r , repl , repl_len ) ;
if ( replace_count ) {
( * replace_count ) + + ;
}
}
return new_str ;
} else {
if ( repl_len < needle_len ) {
new_str = eumalloc ( length + 1 ) ;
} else {
int count = 0 ;
UChar * o , * n , * endp ;
o = haystack ;
n = needle ;
endp = o + length ;
while ( ( o = zend_u_memnstr ( o , n , needle_len , endp ) ) ) {
o + = needle_len ;
count + + ;
}
if ( count = = 0 ) {
/* Needle doesn't occur, shortcircuit the actual replacement. */
new_str = eustrndup ( haystack , length ) ;
if ( _new_length ) {
* _new_length = length ;
}
return new_str ;
} else {
new_str = safe_emalloc ( count , UBYTES ( repl_len - needle_len ) , UBYTES ( length + 1 ) ) ;
}
}
e = s = new_str ;
end = haystack + length ;
for ( p = haystack ; ( r = zend_u_memnstr ( p , needle , needle_len , end ) ) ; p = r + needle_len ) {
u_memcpy ( e , p , r - p ) ;
e + = r - p ;
u_memcpy ( e , repl , repl_len ) ;
e + = repl_len ;
if ( replace_count ) {
( * replace_count ) + + ;
}
}
if ( p < end ) {
u_memcpy ( e , p , end - p ) ;
e + = end - p ;
}
* e = 0 ;
* _new_length = e - s ;
new_str = eurealloc ( new_str , * _new_length + 1 ) ;
return new_str ;
}
} else if ( needle_len > length ) {
nothing_todo :
* _new_length = length ;
new_str = eustrndup ( haystack , length ) ;
return new_str ;
} else {
2006-11-24 21:57:31 +00:00
if ( u_memcmp ( haystack , needle , length ) ) {
2006-10-05 22:40:38 +00:00
goto nothing_todo ;
} else {
* _new_length = repl_len ;
new_str = eustrndup ( repl , repl_len ) ;
if ( replace_count ) {
( * replace_count ) + + ;
}
return new_str ;
}
}
}
/* }}} */
/* {{{ php_u_str_to_str_case_ex */
2006-10-05 22:44:31 +00:00
/* TODO
* - optimize for cases where pat_len > = str_len
*/
2006-10-05 22:40:38 +00:00
PHPAPI UChar * php_u_str_to_str_case_ex ( UChar * str , int str_len ,
UChar * pat , int pat_len , UChar * repl , int repl_len , int * result_len , int * replace_count TSRMLS_DC )
{
UChar * str_fold , * pat_fold , * result ;
int str_fold_len , pat_fold_len , alloc_len ;
UChar * p , * found , * end ;
int offset , found_len ;
UErrorCode status = U_ZERO_ERROR ;
zend_case_fold_string ( & str_fold , & str_fold_len , str , str_len , U_FOLD_CASE_DEFAULT , & status ) ;
if ( str_fold_len = = str_len ) {
alloc_len = str_len ;
result = eumalloc ( alloc_len + 1 ) ;
* result_len = 0 ;
zend_case_fold_string ( & pat_fold , & pat_fold_len , pat , pat_len , U_FOLD_CASE_DEFAULT , & status ) ;
end = str_fold + str_fold_len ;
for ( p = str_fold ;
( found = u_strFindFirst ( p , end - p , pat_fold , pat_fold_len ) ) ;
p = found + pat_fold_len ) { /* we can increment by pattern length since the match in
the subject string is guaranteed to be of the same length */
if ( * result_len + ( found - p + repl_len ) > alloc_len ) {
alloc_len + = ( alloc_len > > 1 ) ; /* grow by 1.5x factor */
result = eurealloc ( result , alloc_len + 1 ) ;
}
u_memcpy ( result + * result_len , str + ( p - str_fold ) , found - p ) ;
* result_len + = found - p ;
u_memcpy ( result + * result_len , repl , repl_len ) ;
* result_len + = repl_len ;
if ( replace_count ) {
( * replace_count ) + + ;
}
}
/* add remaining chunk, if any */
if ( p < end ) {
int chunk_len = end - p ;
if ( * result_len + chunk_len > alloc_len ) {
alloc_len + = * result_len + chunk_len - alloc_len ;
result = eurealloc ( result , alloc_len + 1 ) ;
}
u_memcpy ( result + * result_len , str + ( p - str_fold ) , chunk_len ) ;
* result_len + = chunk_len ;
}
result [ * result_len ] = 0 ;
if ( * result_len < alloc_len ) {
result = eurealloc ( result , * result_len + 1 ) ;
}
efree ( pat_fold ) ;
} else {
usearch_setText ( UG ( root_search ) , str , str_len , & status ) ;
usearch_setPattern ( UG ( root_search ) , pat , pat_len , & status ) ;
usearch_setOffset ( UG ( root_search ) , 0 , & status ) ;
alloc_len = str_len ;
result = eumalloc ( alloc_len + 1 ) ;
* result_len = 0 ;
p = str ;
end = str + str_len ;
for ( offset = usearch_first ( UG ( root_search ) , & status ) ;
offset ! = USEARCH_DONE ;
offset = usearch_next ( UG ( root_search ) , & status ) ) {
found = str + offset ;
/* matched length is not simply pattern length */
found_len = usearch_getMatchedLength ( UG ( root_search ) ) ;
if ( * result_len + ( found - p + repl_len ) > alloc_len ) {
alloc_len + = ( alloc_len > > 1 ) ; /* grow by 1.5x factor */
result = eurealloc ( result , alloc_len + 1 ) ;
}
u_memcpy ( result + * result_len , p , found - p ) ;
* result_len + = found - p ;
u_memcpy ( result + * result_len , repl , repl_len ) ;
* result_len + = repl_len ;
p = found + found_len ;
if ( replace_count ) {
( * replace_count ) + + ;
}
}
/* add remaining chunk, if any */
if ( p < end ) {
int chunk_len = end - p ;
if ( * result_len + chunk_len > alloc_len ) {
alloc_len + = * result_len + chunk_len - alloc_len ;
result = eurealloc ( result , alloc_len + 1 ) ;
}
u_memcpy ( result + * result_len , p , chunk_len ) ;
* result_len + = chunk_len ;
}
result [ * result_len ] = 0 ;
if ( * result_len < alloc_len ) {
result = eurealloc ( result , * result_len + 1 ) ;
}
}
efree ( str_fold ) ;
return result ;
}
/* }}} */
1999-04-17 00:37:12 +00:00
2001-06-05 13:12:10 +00:00
/* {{{ php_str_replace_in_subject
*/
2006-10-05 22:40:38 +00:00
static void php_str_replace_in_subject ( zval * search , zval * replace , zval * * subject , zval * result , int case_sensitivity , int * replace_count TSRMLS_DC )
2001-01-22 21:39:55 +00:00
{
zval * * search_entry ,
* * replace_entry = NULL ,
temp_result ;
2006-10-05 22:40:38 +00:00
zstr replace_value = NULL_ZSTR ;
2001-01-22 21:39:55 +00:00
int replace_len = 0 ;
2006-07-16 15:56:00 +00:00
/* Make sure we're dealing with strings. */
2009-03-26 20:02:53 +00:00
convert_to_unicode_ex ( subject ) ;
Z_TYPE_P ( result ) = IS_UNICODE ;
2006-10-05 22:40:38 +00:00
if ( Z_UNILEN_PP ( subject ) = = 0 ) {
2009-05-25 14:32:15 +00:00
ZVAL_EMPTY_UNICODE ( result ) ;
2001-01-22 21:39:55 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2001-01-22 21:39:55 +00:00
/* If search is an array */
if ( Z_TYPE_P ( search ) = = IS_ARRAY ) {
/* Duplicate subject string for repeated replacement */
* result = * * subject ;
zval_copy_ctor ( result ) ;
2001-11-10 23:44:04 +00:00
INIT_PZVAL ( result ) ;
2006-07-16 15:56:00 +00:00
2001-01-22 21:39:55 +00:00
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( search ) ) ;
1999-04-17 00:37:12 +00:00
2001-01-22 21:39:55 +00:00
if ( Z_TYPE_P ( replace ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( replace ) ) ;
} else {
/* Set replacement value to the passed one */
2006-10-05 22:40:38 +00:00
replace_value = Z_UNIVAL_P ( replace ) ;
replace_len = Z_UNILEN_P ( replace ) ;
2001-01-22 21:39:55 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2001-01-22 21:39:55 +00:00
/* For each entry in the search array, get the entry */
2001-09-04 06:18:11 +00:00
while ( zend_hash_get_current_data ( Z_ARRVAL_P ( search ) , ( void * * ) & search_entry ) = = SUCCESS ) {
2006-07-16 15:56:00 +00:00
/* Make sure we're dealing with strings. */
2003-02-14 18:59:50 +00:00
SEPARATE_ZVAL ( search_entry ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( * search_entry ) ;
2006-10-05 22:40:38 +00:00
if ( Z_UNILEN_PP ( search_entry ) = = 0 ) {
2001-01-22 21:39:55 +00:00
zend_hash_move_forward ( Z_ARRVAL_P ( search ) ) ;
2003-06-20 15:41:43 +00:00
if ( Z_TYPE_P ( replace ) = = IS_ARRAY ) {
zend_hash_move_forward ( Z_ARRVAL_P ( replace ) ) ;
}
2001-01-22 21:39:55 +00:00
continue ;
}
2001-09-04 06:18:11 +00:00
2001-01-22 21:39:55 +00:00
/* If replace is an array. */
if ( Z_TYPE_P ( replace ) = = IS_ARRAY ) {
/* Get current entry */
if ( zend_hash_get_current_data ( Z_ARRVAL_P ( replace ) , ( void * * ) & replace_entry ) = = SUCCESS ) {
2006-07-16 15:56:00 +00:00
/* Make sure we're dealing with strings. */
2006-10-05 22:40:38 +00:00
SEPARATE_ZVAL ( replace_entry ) ;
2009-03-26 20:02:53 +00:00
convert_to_unicode ( * replace_entry ) ;
2006-07-16 15:56:00 +00:00
2001-01-22 21:39:55 +00:00
/* Set replacement value to the one we got from array */
2006-10-05 22:40:38 +00:00
replace_value = Z_UNIVAL_PP ( replace_entry ) ;
replace_len = Z_UNILEN_PP ( replace_entry ) ;
2001-01-22 21:39:55 +00:00
zend_hash_move_forward ( Z_ARRVAL_P ( replace ) ) ;
} else {
/* We've run out of replacement strings, so use an empty one. */
2006-10-05 22:40:38 +00:00
replace_value = EMPTY_ZSTR ;
2001-01-22 21:39:55 +00:00
replace_len = 0 ;
}
}
2006-07-16 15:56:00 +00:00
2006-10-05 22:40:38 +00:00
if ( Z_UNILEN_PP ( search_entry ) = = 1 ) {
2009-03-26 20:02:53 +00:00
if ( case_sensitivity ) {
php_u_char_to_str_ex ( Z_USTRVAL_P ( result ) , Z_USTRLEN_P ( result ) ,
Z_USTRVAL_PP ( search_entry ) [ 0 ] ,
replace_value . u , replace_len ,
& temp_result , replace_count ) ;
2006-10-05 22:40:38 +00:00
} else {
2009-03-26 20:02:53 +00:00
Z_USTRVAL ( temp_result ) = php_u_str_to_str_case_ex ( Z_USTRVAL_P ( result ) , Z_USTRLEN_P ( result ) ,
Z_USTRVAL_PP ( search_entry ) , Z_USTRLEN_PP ( search_entry ) ,
replace_value . u , replace_len ,
& Z_USTRLEN ( temp_result ) , replace_count TSRMLS_CC ) ;
2006-10-05 22:40:38 +00:00
}
} else if ( Z_UNILEN_PP ( search_entry ) > 1 ) {
2009-03-26 20:02:53 +00:00
if ( case_sensitivity ) {
Z_USTRVAL ( temp_result ) = php_u_str_to_str_ex ( Z_USTRVAL_P ( result ) , Z_USTRLEN_P ( result ) ,
Z_USTRVAL_PP ( search_entry ) , Z_USTRLEN_PP ( search_entry ) ,
replace_value . u , replace_len ,
& Z_USTRLEN ( temp_result ) , replace_count ) ;
2006-10-05 22:40:38 +00:00
} else {
2009-03-26 20:02:53 +00:00
Z_USTRVAL ( temp_result ) = php_u_str_to_str_case_ex ( Z_USTRVAL_P ( result ) , Z_USTRLEN_P ( result ) ,
Z_USTRVAL_PP ( search_entry ) , Z_USTRLEN_PP ( search_entry ) ,
replace_value . u , replace_len ,
& Z_USTRLEN ( temp_result ) , replace_count TSRMLS_CC ) ;
2006-10-05 22:40:38 +00:00
}
2001-01-22 21:39:55 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2006-10-05 22:40:38 +00:00
efree ( Z_UNIVAL_P ( result ) . v ) ;
Z_UNIVAL_P ( result ) = Z_UNIVAL ( temp_result ) ;
Z_UNILEN_P ( result ) = Z_UNILEN ( temp_result ) ;
2001-01-22 21:39:55 +00:00
2006-10-05 22:40:38 +00:00
if ( Z_UNILEN_P ( result ) = = 0 ) {
2001-11-10 23:44:04 +00:00
return ;
}
2001-01-22 21:39:55 +00:00
zend_hash_move_forward ( Z_ARRVAL_P ( search ) ) ;
}
} else {
2006-10-05 22:40:38 +00:00
if ( Z_UNILEN_P ( search ) = = 1 ) {
2009-03-26 20:02:53 +00:00
if ( case_sensitivity ) {
php_u_char_to_str_ex ( Z_USTRVAL_PP ( subject ) , Z_USTRLEN_PP ( subject ) ,
Z_USTRVAL_P ( search ) [ 0 ] ,
Z_USTRVAL_P ( replace ) , Z_USTRLEN_P ( replace ) ,
result , replace_count ) ;
2006-10-05 22:40:38 +00:00
} else {
2009-03-26 20:02:53 +00:00
Z_USTRVAL_P ( result ) = php_u_str_to_str_case_ex ( Z_USTRVAL_PP ( subject ) , Z_USTRLEN_PP ( subject ) ,
Z_USTRVAL_P ( search ) , Z_USTRLEN_P ( search ) ,
Z_USTRVAL_P ( replace ) , Z_USTRLEN_P ( replace ) ,
& Z_USTRLEN_P ( result ) , replace_count TSRMLS_CC ) ;
2006-10-05 22:40:38 +00:00
}
2001-01-22 21:39:55 +00:00
} else if ( Z_STRLEN_P ( search ) > 1 ) {
2009-03-26 20:02:53 +00:00
if ( case_sensitivity ) {
Z_USTRVAL_P ( result ) = php_u_str_to_str_ex ( Z_USTRVAL_PP ( subject ) , Z_USTRLEN_PP ( subject ) ,
Z_USTRVAL_P ( search ) , Z_USTRLEN_P ( search ) ,
Z_USTRVAL_P ( replace ) , Z_USTRLEN_P ( replace ) ,
& Z_USTRLEN_P ( result ) , replace_count ) ;
2006-10-05 22:40:38 +00:00
} else {
2009-03-26 20:02:53 +00:00
Z_USTRVAL_P ( result ) = php_u_str_to_str_case_ex ( Z_USTRVAL_PP ( subject ) , Z_USTRLEN_PP ( subject ) ,
Z_USTRVAL_P ( search ) , Z_USTRLEN_P ( search ) ,
Z_USTRVAL_P ( replace ) , Z_USTRLEN_P ( replace ) ,
& Z_USTRLEN_P ( result ) , replace_count TSRMLS_CC ) ;
2006-10-05 22:40:38 +00:00
}
2001-01-22 21:39:55 +00:00
} else {
* result = * * subject ;
zval_copy_ctor ( result ) ;
2001-11-10 23:44:04 +00:00
INIT_PZVAL ( result ) ;
2001-01-22 21:39:55 +00:00
}
1999-04-17 00:37:12 +00:00
}
2001-01-22 21:39:55 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
2001-01-22 21:39:55 +00:00
2003-01-30 20:09:19 +00:00
/* {{{ php_str_replace_common
*/
static void php_str_replace_common ( INTERNAL_FUNCTION_PARAMETERS , int case_sensitivity )
2001-01-22 21:39:55 +00:00
{
2008-10-21 22:06:49 +00:00
zval * subject , * search , * replace , * * subject_entry , * zcount = NULL ;
2001-01-22 21:39:55 +00:00
zval * result ;
2006-02-21 20:12:43 +00:00
zstr string_key ;
2001-08-21 12:57:53 +00:00
uint string_key_len ;
ulong num_key ;
2003-04-13 22:59:19 +00:00
int count = 0 ;
int argc = ZEND_NUM_ARGS ( ) ;
2001-01-22 21:39:55 +00:00
2006-10-05 22:40:38 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " z/z/z/|z " , & search ,
& replace , & subject , & zcount ) = = FAILURE ) {
return ;
1999-05-12 15:40:15 +00:00
}
2003-01-30 05:00:41 +00:00
/* Make sure we're dealing with strings and do the replacement. */
2006-10-05 22:40:38 +00:00
if ( Z_TYPE_P ( search ) ! = IS_ARRAY ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode ( search ) ;
convert_to_unicode ( replace ) ;
2006-10-05 22:40:38 +00:00
} else if ( Z_TYPE_P ( replace ) ! = IS_ARRAY ) {
2009-03-26 20:02:53 +00:00
convert_to_unicode ( replace ) ;
2001-07-20 01:22:29 +00:00
}
2003-01-30 05:00:41 +00:00
/* if subject is an array */
2006-10-05 22:40:38 +00:00
if ( Z_TYPE_P ( subject ) = = IS_ARRAY ) {
2003-01-30 05:00:41 +00:00
array_init ( return_value ) ;
2006-10-05 22:40:38 +00:00
zend_hash_internal_pointer_reset ( Z_ARRVAL_P ( subject ) ) ;
2003-01-30 05:00:41 +00:00
/* For each subject entry, convert it to string, then perform replacement
and add the result to the return_value array . */
2006-10-05 22:40:38 +00:00
while ( zend_hash_get_current_data ( Z_ARRVAL_P ( subject ) , ( void * * ) & subject_entry ) = = SUCCESS ) {
2006-09-19 10:38:31 +00:00
zend_uchar utype ;
2003-05-16 23:30:08 +00:00
if ( Z_TYPE_PP ( subject_entry ) ! = IS_ARRAY & & Z_TYPE_PP ( subject_entry ) ! = IS_OBJECT ) {
MAKE_STD_ZVAL ( result ) ;
2003-05-25 21:48:57 +00:00
SEPARATE_ZVAL ( subject_entry ) ;
2006-10-05 22:40:38 +00:00
php_str_replace_in_subject ( search , replace , subject_entry , result , case_sensitivity , ( argc > 3 ) ? & count : NULL TSRMLS_CC ) ;
2003-05-16 23:30:08 +00:00
} else {
2003-09-29 02:23:40 +00:00
ALLOC_ZVAL ( result ) ;
2007-10-07 05:15:07 +00:00
Z_ADDREF_P ( * subject_entry ) ;
2003-09-29 02:23:40 +00:00
COPY_PZVAL_TO_ZVAL ( * result , * subject_entry ) ;
2003-05-16 23:30:08 +00:00
}
2003-01-30 05:00:41 +00:00
/* Add to return array */
2006-10-05 22:40:38 +00:00
switch ( ( utype = zend_hash_get_current_key_ex ( Z_ARRVAL_P ( subject ) , & string_key ,
& string_key_len , & num_key , 0 , NULL ) ) ) {
2003-01-30 05:00:41 +00:00
case HASH_KEY_IS_STRING :
2006-05-28 21:09:58 +00:00
case HASH_KEY_IS_UNICODE :
2006-09-19 10:38:31 +00:00
add_u_assoc_zval_ex ( return_value , utype , string_key , string_key_len , result ) ;
2003-01-30 05:00:41 +00:00
break ;
case HASH_KEY_IS_LONG :
add_index_zval ( return_value , num_key , result ) ;
break ;
}
2006-07-16 15:56:00 +00:00
2006-10-05 22:40:38 +00:00
zend_hash_move_forward ( Z_ARRVAL_P ( subject ) ) ;
2003-01-30 05:00:41 +00:00
}
} else { /* if subject is not an array */
2006-10-05 22:40:38 +00:00
php_str_replace_in_subject ( search , replace , & subject , return_value , case_sensitivity , ( argc > 3 ) ? & count : NULL TSRMLS_CC ) ;
2006-07-16 15:56:00 +00:00
}
2003-04-13 22:59:19 +00:00
if ( argc > 3 ) {
2006-10-05 22:40:38 +00:00
zval_dtor ( zcount ) ;
ZVAL_LONG ( zcount , count ) ;
2003-04-13 22:59:19 +00:00
}
2003-01-30 05:00:41 +00:00
}
/* }}} */
2006-10-05 22:40:38 +00:00
/* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject [, int &replace_count]) U
2003-01-30 20:09:19 +00:00
Replaces all occurrences of search in haystack with replace */
PHP_FUNCTION ( str_replace )
{
php_str_replace_common ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
/* }}} */
2006-10-05 22:40:38 +00:00
/* {{{ proto mixed str_ireplace(mixed search, mixed replace, mixed subject [, int &replace_count]) U
2003-01-30 05:00:41 +00:00
Replaces all occurrences of search in haystack with replace / case - insensitive */
PHP_FUNCTION ( str_ireplace )
{
2003-01-30 20:09:19 +00:00
php_str_replace_common ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2001-06-05 13:12:10 +00:00
/* {{{ php_hebrev
*
* Converts Logical Hebrew text ( Hebrew Windows style ) to Visual text
1999-04-17 00:37:12 +00:00
* Cheers / complaints / flames - Zeev Suraski < zeev @ php . net >
*/
2001-08-11 17:03:37 +00:00
static void php_hebrev ( INTERNAL_FUNCTION_PARAMETERS , int convert_newlines )
1999-04-17 00:37:12 +00:00
{
2006-12-12 18:17:56 +00:00
char * str ;
int str_len ;
2002-05-04 17:38:45 +00:00
char * heb_str , * tmp , * target , * broken_str ;
1999-04-17 00:37:12 +00:00
int block_start , block_end , block_type , block_length , i ;
long max_chars = 0 ;
2001-08-11 17:03:37 +00:00
int begin , end , char_count , orig_begin ;
1999-04-17 00:37:12 +00:00
2006-07-16 15:56:00 +00:00
2006-12-12 18:17:56 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S|l " , & str , & str_len , & max_chars ) = = FAILURE ) {
return ;
1999-04-17 00:37:12 +00:00
}
2006-12-12 18:17:56 +00:00
if ( str_len = = 0 ) {
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
2006-12-12 18:17:56 +00:00
tmp = str ;
1999-04-17 00:37:12 +00:00
block_start = block_end = 0 ;
2006-12-12 18:17:56 +00:00
heb_str = ( char * ) emalloc ( str_len + 1 ) ;
target = heb_str + str_len ;
1999-04-17 00:37:12 +00:00
* target = 0 ;
target - - ;
block_length = 0 ;
if ( isheb ( * tmp ) ) {
block_type = _HEB_BLOCK_TYPE_HEB ;
} else {
block_type = _HEB_BLOCK_TYPE_ENG ;
}
2006-07-16 15:56:00 +00:00
1999-04-17 00:37:12 +00:00
do {
2002-10-02 17:56:04 +00:00
if ( block_type = = _HEB_BLOCK_TYPE_HEB ) {
2006-12-12 18:17:56 +00:00
while ( ( isheb ( ( int ) * ( tmp + 1 ) ) | | _isblank ( ( int ) * ( tmp + 1 ) ) | | ispunct ( ( int ) * ( tmp + 1 ) ) | | ( int ) * ( tmp + 1 ) = = ' \n ' ) & & block_end < str_len - 1 ) {
1999-04-17 00:37:12 +00:00
tmp + + ;
block_end + + ;
block_length + + ;
}
2002-10-02 17:56:04 +00:00
for ( i = block_start ; i < = block_end ; i + + ) {
2006-12-12 18:17:56 +00:00
* target = str [ i ] ;
1999-04-17 00:37:12 +00:00
switch ( * target ) {
case ' ( ' :
* target = ' ) ' ;
break ;
case ' ) ' :
* target = ' ( ' ;
break ;
2002-03-26 07:57:07 +00:00
case ' [ ' :
* target = ' ] ' ;
break ;
case ' ] ' :
* target = ' [ ' ;
break ;
case ' { ' :
* target = ' } ' ;
break ;
case ' } ' :
* target = ' { ' ;
break ;
case ' < ' :
* target = ' > ' ;
break ;
case ' > ' :
* target = ' < ' ;
break ;
case ' \\ ' :
* target = ' / ' ;
break ;
case ' / ' :
* target = ' \\ ' ;
break ;
1999-04-17 00:37:12 +00:00
default :
break ;
}
target - - ;
}
block_type = _HEB_BLOCK_TYPE_ENG ;
} else {
2006-12-12 18:17:56 +00:00
while ( ! isheb ( * ( tmp + 1 ) ) & & ( int ) * ( tmp + 1 ) ! = ' \n ' & & block_end < str_len - 1 ) {
1999-04-17 00:37:12 +00:00
tmp + + ;
block_end + + ;
block_length + + ;
}
2002-10-02 17:56:04 +00:00
while ( ( _isblank ( ( int ) * tmp ) | | ispunct ( ( int ) * tmp ) ) & & * tmp ! = ' / ' & & * tmp ! = ' - ' & & block_end > block_start ) {
1999-04-17 00:37:12 +00:00
tmp - - ;
block_end - - ;
}
2002-10-02 17:56:04 +00:00
for ( i = block_end ; i > = block_start ; i - - ) {
2006-12-12 18:17:56 +00:00
* target = str [ i ] ;
1999-04-17 00:37:12 +00:00
target - - ;
}
block_type = _HEB_BLOCK_TYPE_HEB ;
}
block_start = block_end + 1 ;
2006-12-12 18:17:56 +00:00
} while ( block_end < str_len - 1 ) ;
1999-04-17 00:37:12 +00:00
2006-12-12 18:17:56 +00:00
broken_str = ( char * ) emalloc ( str_len + 1 ) ;
begin = end = str_len - 1 ;
1999-04-17 00:37:12 +00:00
target = broken_str ;
2006-07-16 15:56:00 +00:00
1999-04-17 00:37:12 +00:00
while ( 1 ) {
char_count = 0 ;
2002-10-02 17:56:04 +00:00
while ( ( ! max_chars | | char_count < max_chars ) & & begin > 0 ) {
1999-04-17 00:37:12 +00:00
char_count + + ;
begin - - ;
2002-10-02 17:56:04 +00:00
if ( begin < = 0 | | _isnewline ( heb_str [ begin ] ) ) {
while ( begin > 0 & & _isnewline ( heb_str [ begin - 1 ] ) ) {
1999-04-17 00:37:12 +00:00
begin - - ;
char_count + + ;
}
break ;
}
}
2002-10-02 17:56:04 +00:00
if ( char_count = = max_chars ) { /* try to avoid breaking words */
1999-04-17 00:37:12 +00:00
int new_char_count = char_count , new_begin = begin ;
2006-07-16 15:56:00 +00:00
2002-10-02 17:56:04 +00:00
while ( new_char_count > 0 ) {
1999-04-17 00:37:12 +00:00
if ( _isblank ( heb_str [ new_begin ] ) | | _isnewline ( heb_str [ new_begin ] ) ) {
break ;
}
new_begin + + ;
new_char_count - - ;
}
2002-10-02 17:56:04 +00:00
if ( new_char_count > 0 ) {
1999-04-17 00:37:12 +00:00
char_count = new_char_count ;
begin = new_begin ;
}
}
orig_begin = begin ;
2006-07-16 15:56:00 +00:00
1999-04-17 00:37:12 +00:00
if ( _isblank ( heb_str [ begin ] ) ) {
heb_str [ begin ] = ' \n ' ;
}
2002-10-02 17:56:04 +00:00
while ( begin < = end & & _isnewline ( heb_str [ begin ] ) ) { /* skip leading newlines */
1999-04-17 00:37:12 +00:00
begin + + ;
}
2002-10-02 17:56:04 +00:00
for ( i = begin ; i < = end ; i + + ) { /* copy content */
1999-04-17 00:37:12 +00:00
* target = heb_str [ i ] ;
target + + ;
}
2002-10-02 17:56:04 +00:00
for ( i = orig_begin ; i < = end & & _isnewline ( heb_str [ i ] ) ; i + + ) {
1999-04-17 00:37:12 +00:00
* target = heb_str [ i ] ;
target + + ;
}
begin = orig_begin ;
2002-10-02 17:56:04 +00:00
if ( begin < = 0 ) {
1999-04-17 00:37:12 +00:00
* target = 0 ;
break ;
}
begin - - ;
end = begin ;
}
efree ( heb_str ) ;
if ( convert_newlines ) {
2006-12-12 18:17:56 +00:00
php_char_to_str ( broken_str , str_len , ' \n ' , " <br /> \n " , 7 , return_value ) ;
1999-04-17 00:37:12 +00:00
efree ( broken_str ) ;
} else {
2001-09-25 21:58:48 +00:00
Z_STRVAL_P ( return_value ) = broken_str ;
2006-12-12 18:17:56 +00:00
Z_STRLEN_P ( return_value ) = str_len ;
2001-09-25 21:58:48 +00:00
Z_TYPE_P ( return_value ) = IS_STRING ;
1999-04-17 00:37:12 +00:00
}
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-12-12 18:17:56 +00:00
/* {{{ proto string hebrev(string str [, int max_chars_per_line]) U
2001-09-04 10:44:28 +00:00
Converts logical Hebrew text to visual text */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( hebrev )
1999-04-17 00:37:12 +00:00
{
2001-08-11 17:03:37 +00:00
php_hebrev ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-12-12 18:17:56 +00:00
/* {{{ proto string hebrevc(string str [, int max_chars_per_line]) U
2001-09-04 10:44:28 +00:00
Converts logical Hebrew text to visual text with newline conversion */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
PHP_FUNCTION ( hebrevc )
1999-04-17 00:37:12 +00:00
{
2001-08-11 17:03:37 +00:00
php_hebrev ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2008-08-14 02:55:13 +00:00
/* {{{ proto string nl2br(string str [, bool is_xhtml]) U
1999-04-17 00:37:12 +00:00
Converts newlines to HTML line breaks */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
PHP_FUNCTION ( nl2br )
1999-04-17 00:37:12 +00:00
{
2008-08-14 02:55:13 +00:00
/* in brief this inserts <br /> or <br> before matched regexp \n\r?|\r\n? */
zstr str ;
int str_len ;
zend_uchar str_type ;
zstr p , end , tmp , target ;
2006-08-08 21:03:11 +00:00
int new_length ;
int repl_cnt = 0 ;
2008-08-14 02:55:13 +00:00
zend_bool is_xhtml = 1 ;
2001-09-26 19:34:46 +00:00
2008-08-14 02:55:13 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t|b " , & str , & str_len , & str_type , & is_xhtml ) = = FAILURE ) {
2006-08-08 21:03:11 +00:00
return ;
1999-04-17 00:37:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-08 21:03:11 +00:00
p = str ;
2006-07-16 15:56:00 +00:00
2001-09-26 19:34:46 +00:00
/* it is really faster to scan twice and allocate mem once insted scanning once
and constantly reallocing */
2006-08-08 21:03:11 +00:00
if ( str_type = = IS_UNICODE ) {
end . u = p . u + str_len ;
while ( p . u < end . u ) {
if ( * p . u = = ( UChar ) 0x0d /*'\r'*/ ) {
if ( * ( p . u + 1 ) = = ( UChar ) 0x0a /*'\n'*/ ) {
p . u + + ;
}
repl_cnt + + ;
} else if ( * p . u = = ( UChar ) 0x0a /*'\n'*/ ) {
if ( * ( p . u + 1 ) = = ( UChar ) 0x0d /*'\r'*/ ) {
p . u + + ;
}
repl_cnt + + ;
2002-10-09 13:37:02 +00:00
}
2006-08-08 21:03:11 +00:00
p . u + + ;
2002-10-09 13:37:02 +00:00
}
2006-08-08 21:03:11 +00:00
} else {
end . s = p . s + str_len ;
while ( p . s < end . s ) {
if ( * p . s = = ' \r ' ) {
if ( * ( p . s + 1 ) = = ' \n ' ) {
p . s + + ;
}
repl_cnt + + ;
} else if ( * p . s = = ' \n ' ) {
if ( * ( p . s + 1 ) = = ' \r ' ) {
p . s + + ;
}
repl_cnt + + ;
}
2006-07-16 15:56:00 +00:00
2006-08-08 21:03:11 +00:00
p . s + + ;
}
2001-09-26 19:34:46 +00:00
}
2006-07-16 15:56:00 +00:00
2001-09-26 19:34:46 +00:00
if ( repl_cnt = = 0 ) {
2006-12-19 21:38:59 +00:00
RETURN_ZSTRL ( str_type , str , str_len , 1 ) ;
2001-09-24 08:33:51 +00:00
}
2001-09-09 12:55:48 +00:00
2008-08-14 02:55:13 +00:00
if ( is_xhtml ) {
new_length = str_len + repl_cnt * ( sizeof ( " <br /> " ) - 1 ) ;
} else {
new_length = str_len + repl_cnt * ( sizeof ( " <br> " ) - 1 ) ;
}
2002-10-09 13:37:02 +00:00
2006-08-08 21:03:11 +00:00
if ( str_type = = IS_UNICODE ) {
tmp . u = target . u = eumalloc ( new_length + 1 ) ;
p = str ;
while ( p . u < end . u ) {
switch ( * p . u ) {
case 0x0d /*'\r'*/ :
case 0x0a /*'\n'*/ :
* target . u + + = ( UChar ) 0x3c /*'<'*/ ;
* target . u + + = ( UChar ) 0x62 /*'b'*/ ;
* target . u + + = ( UChar ) 0x72 /*'r'*/ ;
2008-08-14 02:55:13 +00:00
if ( is_xhtml ) {
* target . u + + = ( UChar ) 0x20 /*' '*/ ;
* target . u + + = ( UChar ) 0x2f /*'/'*/ ;
}
2006-08-08 21:03:11 +00:00
* target . u + + = ( UChar ) 0x3e /*'>'*/ ;
if ( ( * p . u = = ( UChar ) 0x0d /*'\r'*/ & & * ( p . u + 1 ) = = ( UChar ) 0x0a /*'\n'*/ )
| | ( * p . u = = ( UChar ) 0x0a /*'\n'*/ & & * ( p . u + 1 ) = = ( UChar ) 0x0d /*'\r'*/ ) ) {
* target . u + + = * p . u + + ;
}
/* lack of a break; is intentional */
default :
* target . u + + = * p . u ;
}
2002-10-09 13:37:02 +00:00
2006-08-08 21:03:11 +00:00
p . u + + ;
}
2006-07-16 15:56:00 +00:00
2006-08-08 21:03:11 +00:00
* target . u = 0 ;
} else {
tmp . s = target . s = emalloc ( new_length + 1 ) ;
p = str ;
while ( p . s < end . s ) {
switch ( * p . s ) {
case ' \r ' :
case ' \n ' :
* target . s + + = ' < ' ;
* target . s + + = ' b ' ;
* target . s + + = ' r ' ;
2008-08-14 02:55:13 +00:00
if ( is_xhtml ) {
* target . s + + = ' ' ;
* target . s + + = ' / ' ;
}
2006-08-08 21:03:11 +00:00
* target . s + + = ' > ' ;
if ( ( * p . s = = ' \r ' & & * ( p . s + 1 ) = = ' \n ' ) | | ( * p . s = = ' \n ' & & * ( p . s + 1 ) = = ' \r ' ) ) {
* target . s + + = * p . s + + ;
}
/* lack of a break; is intentional */
default :
* target . s + + = * p . s ;
}
p . s + + ;
2002-10-09 13:37:02 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-08 21:03:11 +00:00
* target . s = ' \0 ' ;
2002-10-09 13:37:02 +00:00
}
2006-07-16 15:56:00 +00:00
2001-09-26 19:34:46 +00:00
2006-12-19 21:38:59 +00:00
RETURN_ZSTRL ( str_type , tmp , new_length , 0 ) ;
1999-04-17 00:37:12 +00:00
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string strip_tags(string str [, string allowable_tags]) U
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
Strips HTML and PHP tags from a string */
PHP_FUNCTION ( strip_tags )
{
2005-10-05 12:16:02 +00:00
void * str , * allow = NULL ;
2005-12-09 13:41:06 +00:00
int str_len , allow_len = 0 ;
2005-10-03 17:00:00 +00:00
zend_uchar str_type , allow_type ;
void * buf ;
2006-03-02 13:12:45 +00:00
int retval_len ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2005-10-03 17:00:00 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|T " , & str , & str_len , & str_type ,
& allow , & allow_len , & allow_type ) = = FAILURE ) {
return ;
}
if ( str_type = = IS_UNICODE ) {
buf = eustrndup ( str , str_len ) ;
retval_len = php_u_strip_tags ( ( UChar * ) buf , str_len , NULL , ( UChar * ) allow , allow_len TSRMLS_CC ) ;
RETURN_UNICODEL ( ( UChar * ) buf , retval_len , 0 ) ;
} else {
buf = estrndup ( str , str_len ) ;
2006-12-18 15:04:36 +00:00
retval_len = php_strip_tags_ex ( ( char * ) buf , str_len , NULL , ( char * ) allow , allow_len , 0 ) ;
2006-01-17 12:18:53 +00:00
RETURN_STRINGL ( ( char * ) buf , retval_len , 0 ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
}
/* }}} */
2006-11-30 21:46:54 +00:00
/* {{{ proto string setlocale(mixed category, string locale [, string ...]) U
1999-04-17 00:37:12 +00:00
Set locale information */
1999-06-15 21:51:00 +00:00
PHP_FUNCTION ( setlocale )
1999-04-17 00:37:12 +00:00
{
2008-08-16 21:16:25 +00:00
zval * * * args = NULL ;
1999-12-23 14:59:01 +00:00
zval * * pcategory , * * plocale ;
2008-08-16 21:16:25 +00:00
int cat , num_args , i = 0 ;
1999-04-17 00:37:12 +00:00
char * loc , * retval ;
2008-08-16 21:16:25 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Z+ " , & pcategory , & args , & num_args ) = = FAILURE ) {
return ;
2002-09-18 07:55:30 +00:00
}
2008-08-16 21:16:25 +00:00
2009-03-26 20:02:53 +00:00
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " deprecated in Unicode mode, please use ICU locale functions " ) ;
2006-09-22 18:24:12 +00:00
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
# ifdef HAVE_SETLOCALE
2000-12-21 13:46:50 +00:00
if ( Z_TYPE_PP ( pcategory ) = = IS_LONG ) {
2006-07-16 15:56:00 +00:00
convert_to_long_ex ( pcategory ) ;
2000-12-21 13:46:50 +00:00
cat = Z_LVAL_PP ( pcategory ) ;
2008-08-16 21:16:25 +00:00
} else {
/* FIXME: The following behaviour should be removed. */
2002-09-18 07:55:30 +00:00
char * category ;
2008-08-16 21:16:25 +00:00
2008-02-23 17:03:53 +00:00
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " Passing locale category name as string is deprecated. Use the LC_* -constants instead " ) ;
2008-08-16 21:16:25 +00:00
2000-12-21 13:46:50 +00:00
convert_to_string_ex ( pcategory ) ;
2008-08-16 21:16:25 +00:00
category = Z_STRVAL_PP ( pcategory ) ;
2000-12-21 13:46:50 +00:00
2008-08-16 21:16:25 +00:00
if ( ! strcasecmp ( " LC_ALL " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_ALL ;
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_COLLATE " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_COLLATE ;
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_CTYPE " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_CTYPE ;
2000-06-17 16:49:03 +00:00
# ifdef LC_MESSAGES
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_MESSAGES " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_MESSAGES ;
2000-06-17 14:48:03 +00:00
# endif
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_MONETARY " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_MONETARY ;
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_NUMERIC " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_NUMERIC ;
2008-08-16 21:16:25 +00:00
} else if ( ! strcasecmp ( " LC_TIME " , category ) ) {
2000-12-21 13:46:50 +00:00
cat = LC_TIME ;
2008-08-16 21:16:25 +00:00
} else {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME " , category ) ;
2008-08-16 21:16:25 +00:00
if ( args ) {
efree ( args ) ;
}
2000-12-21 13:46:50 +00:00
RETURN_FALSE ;
}
1999-04-17 00:37:12 +00:00
}
2002-09-18 07:55:30 +00:00
2008-08-16 21:16:25 +00:00
if ( Z_TYPE_PP ( args [ 0 ] ) = = IS_ARRAY ) {
zend_hash_internal_pointer_reset ( Z_ARRVAL_PP ( args [ 0 ] ) ) ;
2000-12-21 13:46:50 +00:00
}
2008-08-16 21:16:25 +00:00
2002-10-02 17:56:04 +00:00
while ( 1 ) {
2008-08-16 21:16:25 +00:00
if ( Z_TYPE_PP ( args [ 0 ] ) = = IS_ARRAY ) {
if ( ! zend_hash_num_elements ( Z_ARRVAL_PP ( args [ 0 ] ) ) ) {
2003-04-03 06:21:59 +00:00
break ;
}
2008-08-16 21:16:25 +00:00
zend_hash_get_current_data ( Z_ARRVAL_PP ( args [ 0 ] ) , ( void * * ) & plocale ) ;
2002-09-18 07:55:30 +00:00
} else {
plocale = args [ i ] ;
1999-10-08 02:10:57 +00:00
}
2002-09-18 07:55:30 +00:00
convert_to_string_ex ( plocale ) ;
2006-07-16 15:56:00 +00:00
2002-09-18 07:55:30 +00:00
if ( ! strcmp ( " 0 " , Z_STRVAL_PP ( plocale ) ) ) {
loc = NULL ;
} else {
loc = Z_STRVAL_PP ( plocale ) ;
2007-09-07 02:28:26 +00:00
if ( Z_STRLEN_PP ( plocale ) > = 255 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Specified locale name is too long " ) ;
break ;
}
2002-09-18 07:55:30 +00:00
}
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
retval = setlocale ( cat , loc ) ;
2006-12-05 02:55:27 +00:00
zend_update_current_locale ( ) ;
2002-09-18 07:55:30 +00:00
if ( retval ) {
/* Remember if locale was changed */
if ( loc ) {
STR_FREE ( BG ( locale_string ) ) ;
BG ( locale_string ) = estrdup ( retval ) ;
}
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
if ( args ) {
efree ( args ) ;
}
RETURN_STRING ( retval , 1 ) ;
2002-09-18 07:55:30 +00:00
}
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
if ( Z_TYPE_PP ( args [ 0 ] ) = = IS_ARRAY ) {
if ( zend_hash_move_forward ( Z_ARRVAL_PP ( args [ 0 ] ) ) = = FAILURE ) break ;
2002-09-18 07:55:30 +00:00
} else {
2008-08-16 21:16:25 +00:00
if ( + + i > = num_args ) break ;
2002-09-18 07:55:30 +00:00
}
1999-04-17 00:37:12 +00:00
}
2002-09-18 07:55:30 +00:00
1999-04-17 00:37:12 +00:00
# endif
2008-08-16 21:16:25 +00:00
if ( args ) {
efree ( args ) ;
}
1999-04-17 00:37:12 +00:00
RETURN_FALSE ;
}
/* }}} */
2001-09-04 10:44:28 +00:00
/* {{{ proto void parse_str(string encoded_string [, array result])
2000-07-26 11:43:01 +00:00
Parses GET / POST / COOKIE data and sets global variables */
1999-07-24 22:16:54 +00:00
PHP_FUNCTION ( parse_str )
1999-04-17 00:37:12 +00:00
{
2008-08-16 21:16:25 +00:00
char * enc_string , * res = NULL ;
int enc_string_len ;
zval * result = NULL ;
1999-04-17 00:37:12 +00:00
2009-06-28 02:36:19 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|z " , & enc_string , & enc_string_len , & result ) = = FAILURE ) {
2008-08-16 21:16:25 +00:00
return ;
2000-09-11 14:50:26 +00:00
}
2008-08-16 21:16:25 +00:00
res = estrndup ( enc_string , enc_string_len ) ;
2000-09-11 14:50:26 +00:00
2008-08-16 21:16:25 +00:00
if ( ZEND_NUM_ARGS ( ) = = 1 ) {
2005-09-28 22:31:29 +00:00
zval tmp ;
2008-04-29 08:15:49 +00:00
if ( ! EG ( active_symbol_table ) ) {
zend_rebuild_symbol_table ( TSRMLS_C ) ;
}
Z_ARRVAL ( tmp ) = EG ( active_symbol_table ) ;
2005-09-28 22:31:29 +00:00
sapi_module . treat_data ( PARSE_STRING , res , & tmp TSRMLS_CC ) ;
2000-09-12 10:56:25 +00:00
} else {
2000-09-11 14:50:26 +00:00
/* Clear out the array that was passed in. */
2008-08-16 21:16:25 +00:00
zval_dtor ( result ) ;
array_init ( result ) ;
2006-07-16 15:56:00 +00:00
2008-08-16 21:16:25 +00:00
sapi_module . treat_data ( PARSE_STRING , res , result TSRMLS_CC ) ;
1999-04-17 00:37:12 +00:00
}
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
/* }}} */
1999-09-20 15:50:56 +00:00
# define PHP_TAG_BUF_SIZE 1023
2005-10-03 17:00:00 +00:00
/* php_u_tag_find / php_tag_find
2001-06-05 13:12:10 +00:00
*
2006-07-16 15:56:00 +00:00
* Check if tag is in a set of tags
1999-09-20 15:50:56 +00:00
*
* states :
2005-10-03 17:00:00 +00:00
*
1999-09-20 15:50:56 +00:00
* 0 start tag
* 1 first non - whitespace char seen
*/
2005-10-03 17:00:00 +00:00
/* {{{ php_u_tag_find
*/
2006-03-02 13:12:45 +00:00
int php_u_tag_find ( UChar * tag , int len , UChar * set , int set_len )
2005-10-03 17:00:00 +00:00
{
int32_t idx = 0 ;
2005-10-05 12:16:02 +00:00
UChar32 ch ;
UChar * norm , * n ;
2005-10-03 17:00:00 +00:00
int state = 0 , done = 0 ;
2006-12-20 23:36:43 +00:00
if ( len < = 0 ) {
2005-10-03 17:00:00 +00:00
return 0 ;
}
norm = eumalloc ( len + 1 ) ;
n = norm ;
while ( ! done ) {
U16_NEXT ( tag , idx , len , ch ) ;
2009-04-24 21:23:47 +00:00
ch = u_tolower ( ch ) ;
switch ( ch ) {
2005-10-03 17:00:00 +00:00
case ' < ' :
* ( n + + ) = ch ;
break ;
case ' > ' :
done = 1 ;
break ;
default :
if ( u_isWhitespace ( ch ) = = FALSE ) {
if ( state = = 0 ) {
state = 1 ;
if ( ch ! = ' / ' )
* ( n + + ) = ch ;
} else {
* ( n + + ) = ch ;
}
} else {
if ( state = = 1 )
done = 1 ;
}
break ;
}
}
* ( n + + ) = ' > ' ;
2005-10-05 12:16:02 +00:00
* n = 0 ;
2005-10-03 17:00:00 +00:00
2005-10-05 12:16:02 +00:00
if ( u_strFindFirst ( set , set_len , norm , n - norm ) ! = NULL ) {
2005-10-03 17:00:00 +00:00
done = 1 ;
} else {
done = 0 ;
}
efree ( norm ) ;
return done ;
}
/* }}} */
/* {{{ php_tag_find
*/
1999-09-20 15:50:56 +00:00
int php_tag_find ( char * tag , int len , char * set ) {
char c , * n , * t ;
2000-02-13 15:59:32 +00:00
int state = 0 , done = 0 ;
2006-12-20 23:36:43 +00:00
char * norm ;
if ( len < = 0 ) {
return 0 ;
}
norm = emalloc ( len + 1 ) ;
1999-09-20 15:50:56 +00:00
n = norm ;
t = tag ;
c = tolower ( * t ) ;
2006-07-16 15:56:00 +00:00
/*
1999-09-20 15:50:56 +00:00
normalize the tag removing leading and trailing whitespace
and turn any < a whatever . . . > into just < a > and any < / tag >
into < tag >
*/
2002-10-02 17:56:04 +00:00
while ( ! done ) {
switch ( c ) {
case ' < ' :
* ( n + + ) = c ;
break ;
case ' > ' :
done = 1 ;
break ;
default :
if ( ! isspace ( ( int ) c ) ) {
if ( state = = 0 ) {
state = 1 ;
if ( c ! = ' / ' )
* ( n + + ) = c ;
} else {
* ( n + + ) = c ;
}
1999-09-20 15:50:56 +00:00
} else {
2002-10-02 17:56:04 +00:00
if ( state = = 1 )
done = 1 ;
1999-09-20 15:50:56 +00:00
}
2002-10-02 17:56:04 +00:00
break ;
1999-09-20 15:50:56 +00:00
}
c = tolower ( * ( + + t ) ) ;
2006-07-16 15:56:00 +00:00
}
1999-09-20 15:50:56 +00:00
* ( n + + ) = ' > ' ;
2006-07-16 15:56:00 +00:00
* n = ' \0 ' ;
2002-10-02 17:56:04 +00:00
if ( strstr ( set , norm ) ) {
2000-02-13 15:56:07 +00:00
done = 1 ;
} else {
done = 0 ;
}
1999-09-20 15:50:56 +00:00
efree ( norm ) ;
return done ;
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-09-20 15:50:56 +00:00
2005-10-03 17:00:00 +00:00
/* php_u_strip_tags / php_strip_tags
2006-07-16 15:56:00 +00:00
A simple little state - machine to strip out html and php tags
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
State 0 is the output state , State 1 means we are inside a
normal html tag and state 2 means we are inside a php tag .
The state variable is passed in to allow a function like fgetss
to maintain state across calls to the function .
lc holds the last significant character read and br is a bracket
counter .
1999-09-20 15:50:56 +00:00
When an allow string is passed in we keep track of the string
in state 1 and when the tag is closed check it against the
allow string to see if we should allow it .
2001-08-22 02:03:14 +00:00
swm : Added ability to strip < ? xml tags without assuming it PHP
code .
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
*/
2005-10-03 17:00:00 +00:00
/* {{{ php_u_strip_tags
*/
2006-03-02 13:12:45 +00:00
PHPAPI int php_u_strip_tags ( UChar * rbuf , int len , int * stateptr , UChar * allow , int allow_len TSRMLS_DC )
2005-10-03 17:00:00 +00:00
{
UChar * tbuf = NULL , * tp = NULL ;
UChar * buf , * rp ;
int32_t idx = 0 , tmp , codepts ;
UChar32 ch , next , prev1 , prev2 , last , doctype [ 6 ] ;
int br = 0 , depth = 0 , state = 0 , i ;
2007-06-18 11:50:41 +00:00
UChar in_q = 0 ;
2005-10-03 17:00:00 +00:00
if ( stateptr )
state = * stateptr ;
buf = eustrndup ( rbuf , len ) ;
rp = rbuf ;
2005-10-05 12:16:02 +00:00
if ( allow_len ! = 0 ) {
2006-08-03 23:09:29 +00:00
allow = php_u_strtolower ( allow , & allow_len , UG ( default_locale ) ) ;
2005-10-03 17:00:00 +00:00
tbuf = eumalloc ( PHP_TAG_BUF_SIZE + 1 ) ;
tp = tbuf ;
}
last = 0x00 ;
ch = prev1 = prev2 = next = - 1 ;
codepts = 0 ;
while ( idx < len ) {
prev2 = prev1 ; prev1 = ch ;
U16_NEXT ( buf , idx , len , ch ) ;
codepts + + ;
switch ( ch ) {
case 0x00 : /* '\0' */
break ;
case 0x3C : /* '<' */
2009-04-24 21:23:47 +00:00
if ( in_q ) {
break ;
}
2005-10-03 17:00:00 +00:00
U16_GET ( buf , 0 , idx , len , next ) ;
if ( u_isWhitespace ( next ) = = TRUE ) {
goto reg_u_char ;
}
if ( state = = 0 ) {
last = 0x3C ;
state = 1 ;
2005-10-05 12:16:02 +00:00
if ( allow_len ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
}
} else if ( state = = 1 ) {
depth + + ;
}
break ;
case 0x28 : /* '(' */
if ( state = = 2 ) {
if ( last ! = 0x22 & & last ! = 0x27 ) { /* '"' & '\'' */
last = 0x28 ;
br + + ;
}
2005-10-05 12:16:02 +00:00
} else if ( allow_len & & state = = 1 ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
} else if ( state = = 0 ) {
* ( rp + + ) = ch ;
}
2006-07-16 15:56:00 +00:00
break ;
2005-10-03 17:00:00 +00:00
case 0x29 : /* ')' */
if ( state = = 2 ) {
if ( last ! = 0x22 & & last ! = 0x27 ) { /* '"' & '\'' */
last = ch ;
br - - ;
}
2005-10-05 12:16:02 +00:00
} else if ( allow_len & & state = = 1 ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
} else if ( state = = 0 ) {
* ( rp + + ) = ch ;
}
2006-07-16 15:56:00 +00:00
break ;
2005-10-03 17:00:00 +00:00
case 0x3E : /* '>' */
if ( depth ) {
depth - - ;
break ;
}
2006-07-16 15:56:00 +00:00
2007-06-18 11:50:41 +00:00
if ( in_q ) {
break ;
}
2005-10-03 17:00:00 +00:00
switch ( state ) {
case 1 : /* HTML/XML */
last = ch ;
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2005-10-05 12:16:02 +00:00
if ( allow_len ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
* ( tp ) = 0 ;
if ( php_u_tag_find ( tbuf , tp - tbuf , allow , allow_len ) ) {
u_memcpy ( rp , tbuf , tp - tbuf ) ;
rp + = tp - tbuf ;
}
tp = tbuf ;
}
break ;
2006-07-16 15:56:00 +00:00
2005-10-03 17:00:00 +00:00
case 2 : /* PHP */
if ( ! br & & last ! = 0x22 & & prev1 = = 0x3F ) { /* '"' & '?' */
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2005-10-03 17:00:00 +00:00
tp = tbuf ;
}
break ;
2006-07-16 15:56:00 +00:00
2005-10-03 17:00:00 +00:00
case 3 :
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2005-10-03 17:00:00 +00:00
tp = tbuf ;
break ;
case 4 : /* JavaScript/CSS/etc... */
if ( codepts > = 2 & & prev1 = = 0x2D & & prev2 = = 0x2D ) { /* '-' */
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2005-10-03 17:00:00 +00:00
tp = tbuf ;
}
break ;
default :
* ( rp + + ) = ch ;
break ;
}
break ;
case 0x22 : /* '"' */
case 0x27 : /* '\'' */
2008-11-21 19:14:47 +00:00
if ( state = = 4 ) {
/* Inside <!-- comment --> */
break ;
} else if ( state = = 2 & & prev1 ! = 0x5C ) { /* '\\' */
2005-10-03 17:00:00 +00:00
if ( last = = ch ) {
last = 0x00 ;
} else if ( last ! = 0x5C ) {
last = ch ;
}
} else if ( state = = 0 ) {
* ( rp + + ) = ch ;
2005-10-05 12:16:02 +00:00
} else if ( allow_len & & state = = 1 ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
}
2009-04-24 21:50:51 +00:00
if ( state & & prev1 ! = 0x5C /*'\\'*/ & & ( ! in_q | | ch = = in_q ) ) {
2007-06-18 11:50:41 +00:00
if ( in_q ) {
in_q = 0 ;
} else {
in_q = ch ;
}
}
2005-10-03 17:00:00 +00:00
break ;
2006-07-16 15:56:00 +00:00
2005-10-03 17:00:00 +00:00
case 0x21 : /* '!' */
/* JavaScript & Other HTML scripting languages */
if ( state = = 1 & & prev1 = = 0x3C ) { /* '<' */
state = 3 ;
last = ch ;
} else {
if ( state = = 0 ) {
2005-10-05 12:16:02 +00:00
* ( rp + + ) = ch ;
} else if ( allow_len & & state = = 1 ) {
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
* ( tp + + ) = ch ;
2005-10-03 17:00:00 +00:00
}
}
break ;
case 0x2D : /* '-' */
if ( state = = 3 & & codepts > = 2 & & prev1 = = 0x2D & & prev2 = = 0x21 ) { /* '-' & '!' */
state = 4 ;
} else {
goto reg_u_char ;
}
break ;
case 0x3F : /* '?' */
if ( state = = 1 & & prev1 = = 0x3C ) { /* '<' */
br = 0 ;
state = 2 ;
break ;
}
case ' E ' :
case ' e ' :
/* !DOCTYPE exception */
if ( state = = 3 & & codepts > 6 ) {
tmp = idx ;
for ( i = 0 ; i < 6 ; i + + ) {
U16_PREV ( buf , 0 , tmp , doctype [ i ] ) ;
}
if ( u_tolower ( doctype [ 0 ] ) = = ' p ' & & u_tolower ( doctype [ 1 ] ) = = ' y ' & &
u_tolower ( doctype [ 2 ] ) = = ' t ' & & u_tolower ( doctype [ 3 ] ) = = ' c ' & &
u_tolower ( doctype [ 4 ] ) = = ' o ' & & u_tolower ( doctype [ 5 ] ) = = ' d ' ) {
state = 1 ;
break ;
}
}
/* fall-through */
case ' l ' :
2008-07-11 12:43:06 +00:00
case ' L ' :
2005-10-03 17:00:00 +00:00
/* swm: If we encounter '<?xml' then we shouldn't be in
* state = = 2 ( PHP ) . Switch back to HTML .
*/
2008-07-11 12:43:06 +00:00
if ( state = = 2 & & codepts > 2 & & ( prev1 = = ' m ' | | prev1 = = ' M ' ) & & ( prev2 = = ' x ' | | prev2 = = ' X ' ) ) {
2005-10-03 17:00:00 +00:00
state = 1 ;
break ;
}
/* fall-through */
default :
reg_u_char :
if ( state = = 0 ) {
rp + = zend_codepoint_to_uchar ( ch , rp ) ;
2005-10-05 12:16:02 +00:00
} else if ( allow_len & & state = = 1 ) {
2005-10-03 17:00:00 +00:00
tp = ( ( tp - tbuf ) > = UBYTES ( PHP_TAG_BUF_SIZE ) ? tbuf : tp ) ;
tp + = zend_codepoint_to_uchar ( ch , tp ) ;
2006-07-16 15:56:00 +00:00
}
2005-10-03 17:00:00 +00:00
break ;
}
}
* rp = 0 ;
efree ( buf ) ;
2005-10-05 12:16:02 +00:00
if ( allow_len ) {
2005-10-03 17:00:00 +00:00
efree ( tbuf ) ;
2005-10-05 12:16:02 +00:00
efree ( allow ) ;
}
2005-10-03 17:00:00 +00:00
if ( stateptr )
* stateptr = state ;
2006-03-02 13:12:45 +00:00
return ( int ) ( rp - rbuf ) ;
2005-10-03 17:00:00 +00:00
}
/* }}} */
2007-06-05 13:37:05 +00:00
PHPAPI size_t php_strip_tags ( char * rbuf , int len , int * stateptr , char * allow , int allow_len ) /* { { { */
2006-12-18 15:04:36 +00:00
{
return php_strip_tags_ex ( rbuf , len , stateptr , allow , allow_len , 0 ) ;
}
2007-06-05 13:37:05 +00:00
/* }}} */
2006-12-18 15:04:36 +00:00
2005-10-03 17:00:00 +00:00
/* {{{ php_strip_tags
*/
2006-12-18 15:04:36 +00:00
PHPAPI size_t php_strip_tags_ex ( char * rbuf , int len , int * stateptr , char * allow , int allow_len , zend_bool allow_tag_spaces )
2000-02-08 21:29:18 +00:00
{
1999-09-20 15:50:56 +00:00
char * tbuf , * buf , * p , * tp , * rp , c , lc ;
2007-06-18 11:50:41 +00:00
int br , i = 0 , depth = 0 , in_q = 0 ;
2002-04-07 10:56:30 +00:00
int state = 0 ;
2002-03-20 14:38:13 +00:00
if ( stateptr )
state = * stateptr ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2001-08-11 17:03:37 +00:00
buf = estrndup ( rbuf , len ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
c = * buf ;
lc = ' \0 ' ;
p = buf ;
rp = rbuf ;
br = 0 ;
2002-10-02 17:56:04 +00:00
if ( allow ) {
2000-02-08 21:29:18 +00:00
php_strtolower ( allow , allow_len ) ;
1999-09-20 15:50:56 +00:00
tbuf = emalloc ( PHP_TAG_BUF_SIZE + 1 ) ;
tp = tbuf ;
1999-09-24 15:34:54 +00:00
} else {
tbuf = tp = NULL ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2002-10-02 17:56:04 +00:00
while ( i < len ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
switch ( c ) {
2004-06-26 07:43:02 +00:00
case ' \0 ' :
break ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
case ' < ' :
2008-07-15 14:44:46 +00:00
if ( in_q ) {
break ;
}
2006-12-18 15:04:36 +00:00
if ( isspace ( * ( p + 1 ) ) & & ! allow_tag_spaces ) {
2003-01-06 22:13:03 +00:00
goto reg_char ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( state = = 0 ) {
lc = ' < ' ;
state = 1 ;
2002-10-02 17:56:04 +00:00
if ( allow ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
1999-09-20 15:50:56 +00:00
* ( tp + + ) = ' < ' ;
}
2002-09-21 17:34:06 +00:00
} else if ( state = = 1 ) {
2002-09-20 11:48:47 +00:00
depth + + ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
break ;
case ' ( ' :
if ( state = = 2 ) {
2002-09-21 17:34:06 +00:00
if ( lc ! = ' " ' & & lc ! = ' \' ' ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
lc = ' ( ' ;
br + + ;
}
2001-04-29 13:16:05 +00:00
} else if ( allow & & state = = 1 ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
2001-04-28 23:07:51 +00:00
* ( tp + + ) = c ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
} else if ( state = = 0 ) {
* ( rp + + ) = c ;
}
2006-07-16 15:56:00 +00:00
break ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
case ' ) ' :
if ( state = = 2 ) {
2002-09-21 17:34:06 +00:00
if ( lc ! = ' " ' & & lc ! = ' \' ' ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
lc = ' ) ' ;
br - - ;
}
2001-04-29 13:16:05 +00:00
} else if ( allow & & state = = 1 ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
2001-04-28 23:07:51 +00:00
* ( tp + + ) = c ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
} else if ( state = = 0 ) {
* ( rp + + ) = c ;
}
2006-07-16 15:56:00 +00:00
break ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
case ' > ' :
2002-09-20 11:48:47 +00:00
if ( depth ) {
depth - - ;
break ;
}
2006-07-16 15:56:00 +00:00
2007-06-18 11:50:41 +00:00
if ( in_q ) {
break ;
}
2002-10-03 18:15:18 +00:00
switch ( state ) {
2002-09-21 17:34:06 +00:00
case 1 : /* HTML/XML */
lc = ' > ' ;
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2002-10-02 17:56:04 +00:00
if ( allow ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
2002-09-21 17:34:06 +00:00
* ( tp + + ) = ' > ' ;
* tp = ' \0 ' ;
2002-10-02 17:56:04 +00:00
if ( php_tag_find ( tbuf , tp - tbuf , allow ) ) {
2002-09-21 17:34:06 +00:00
memcpy ( rp , tbuf , tp - tbuf ) ;
rp + = tp - tbuf ;
}
tp = tbuf ;
}
break ;
2006-07-16 15:56:00 +00:00
2002-09-21 17:34:06 +00:00
case 2 : /* PHP */
2002-10-02 17:56:04 +00:00
if ( ! br & & lc ! = ' \" ' & & * ( p - 1 ) = = ' ? ' ) {
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2002-09-21 17:34:06 +00:00
tp = tbuf ;
}
break ;
2006-07-16 15:56:00 +00:00
2003-05-04 12:44:36 +00:00
case 3 :
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2003-05-04 11:45:58 +00:00
tp = tbuf ;
2002-09-21 17:34:06 +00:00
break ;
2003-05-04 12:44:36 +00:00
case 4 : /* JavaScript/CSS/etc... */
if ( p > = buf + 2 & & * ( p - 1 ) = = ' - ' & & * ( p - 2 ) = = ' - ' ) {
2007-06-18 11:50:41 +00:00
in_q = state = 0 ;
2003-05-04 12:44:36 +00:00
tp = tbuf ;
}
break ;
2002-09-21 17:34:06 +00:00
default :
* ( rp + + ) = c ;
break ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
break ;
2002-09-21 17:34:06 +00:00
case ' " ' :
case ' \' ' :
2008-11-21 19:14:47 +00:00
if ( state = = 4 ) {
/* Inside <!-- comment --> */
break ;
} else if ( state = = 2 & & * ( p - 1 ) ! = ' \\ ' ) {
2002-09-21 17:34:06 +00:00
if ( lc = = c ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
lc = ' \0 ' ;
} else if ( lc ! = ' \\ ' ) {
2002-09-21 17:34:06 +00:00
lc = c ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
} else if ( state = = 0 ) {
* ( rp + + ) = c ;
1999-09-20 15:50:56 +00:00
} else if ( allow & & state = = 1 ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
1999-09-20 15:50:56 +00:00
* ( tp + + ) = c ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2007-06-18 11:50:41 +00:00
if ( state & & p ! = buf & & * ( p - 1 ) ! = ' \\ ' & & ( ! in_q | | * p = = in_q ) ) {
if ( in_q ) {
in_q = 0 ;
} else {
in_q = * p ;
}
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
break ;
2006-07-16 15:56:00 +00:00
case ' ! ' :
2002-09-21 17:34:06 +00:00
/* JavaScript & Other HTML scripting languages */
2006-07-16 15:56:00 +00:00
if ( state = = 1 & & * ( p - 1 ) = = ' < ' ) {
2002-09-21 17:34:06 +00:00
state = 3 ;
2002-12-31 15:18:52 +00:00
lc = c ;
2002-11-27 06:20:19 +00:00
} else {
2003-01-19 11:32:54 +00:00
if ( state = = 0 ) {
* ( rp + + ) = c ;
} else if ( allow & & state = = 1 ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
2003-01-19 11:32:54 +00:00
* ( tp + + ) = c ;
}
}
2002-09-21 17:34:06 +00:00
break ;
2002-12-31 15:18:52 +00:00
2003-05-04 12:44:36 +00:00
case ' - ' :
if ( state = = 3 & & p > = buf + 2 & & * ( p - 1 ) = = ' - ' & & * ( p - 2 ) = = ' ! ' ) {
state = 4 ;
2003-05-16 06:19:51 +00:00
} else {
goto reg_char ;
2003-05-04 12:44:36 +00:00
}
break ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
case ' ? ' :
2001-08-22 02:03:14 +00:00
2006-07-16 15:56:00 +00:00
if ( state = = 1 & & * ( p - 1 ) = = ' < ' ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
br = 0 ;
state = 2 ;
break ;
}
2001-08-22 05:47:11 +00:00
2002-12-31 15:18:52 +00:00
case ' E ' :
case ' e ' :
/* !DOCTYPE exception */
if ( state = = 3 & & p > buf + 6
& & tolower ( * ( p - 1 ) ) = = ' p '
& & tolower ( * ( p - 2 ) ) = = ' y '
& & tolower ( * ( p - 3 ) ) = = ' t '
& & tolower ( * ( p - 4 ) ) = = ' c '
& & tolower ( * ( p - 5 ) ) = = ' o '
& & tolower ( * ( p - 6 ) ) = = ' d ' ) {
state = 1 ;
break ;
}
/* fall-through */
2001-08-22 05:47:11 +00:00
case ' l ' :
2008-07-11 12:43:06 +00:00
case ' L ' :
2001-08-22 05:47:11 +00:00
/* swm: If we encounter '<?xml' then we shouldn't be in
* state = = 2 ( PHP ) . Switch back to HTML .
*/
2008-07-11 12:43:06 +00:00
if ( state = = 2 & & p > buf + 2 & & strncasecmp ( p - 2 , " xm " , 2 ) = = 0 ) {
2001-08-22 05:47:11 +00:00
state = 1 ;
break ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
2001-08-22 02:03:14 +00:00
/* fall-through */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
default :
2003-01-06 22:13:03 +00:00
reg_char :
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
if ( state = = 0 ) {
* ( rp + + ) = c ;
2002-10-02 17:56:04 +00:00
} else if ( allow & & state = = 1 ) {
2003-07-12 09:33:31 +00:00
tp = ( ( tp - tbuf ) > = PHP_TAG_BUF_SIZE ? tbuf : tp ) ;
1999-09-20 15:50:56 +00:00
* ( tp + + ) = c ;
2006-07-16 15:56:00 +00:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
break ;
}
c = * ( + + p ) ;
1999-09-20 15:50:56 +00:00
i + + ;
2006-07-16 15:56:00 +00:00
}
2003-02-24 22:19:36 +00:00
if ( rp < rbuf + len ) {
* rp = ' \0 ' ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
efree ( buf ) ;
2002-10-02 17:56:04 +00:00
if ( allow )
efree ( tbuf ) ;
2002-03-20 14:38:13 +00:00
if ( stateptr )
* stateptr = state ;
2003-02-24 22:01:12 +00:00
return ( size_t ) ( rp - rbuf ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
1999-04-17 00:37:12 +00:00
2006-12-05 04:52:44 +00:00
/* {{{ proto array str_getcsv(string input[, string delimiter[, string enclosure[, string escape]]]) U
Parse a CSV string into an array */
PHP_FUNCTION ( str_getcsv )
{
zend_uchar str_type , delim_type = IS_STRING , enc_type = IS_STRING , esc_type = IS_STRING ;
2006-12-06 23:14:15 +00:00
zstr str , delim = ZSTR ( " , " ) , enc = ZSTR ( " \" " ) , esc = ZSTR ( " \\ " ) ;
2006-12-05 04:52:44 +00:00
int str_len , delim_len = 1 , enc_len = 1 , esc_len = 1 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|TTT " ,
& str , & str_len , & str_type ,
& delim , & delim_len , & delim_type ,
& enc , & enc_len , & enc_type ,
& esc , & esc_len , & esc_type ) = = FAILURE ) {
return ;
}
if ( str_type = = IS_UNICODE ) {
UChar udelim = ' , ' , uenc = ' " ' , uesc = ' \\ ' ;
2006-12-06 23:14:15 +00:00
/* When a unicode string is passed for the main argument,
* the ' T ' specifiers will atuomatically align any remaining
* arguments that are actually passed to be Unicode as well .
*
* However , since they are optional , they may have reached
* this point still in IS_STRING form ( because they wern ' t passed ) .
*
* The " clean " way to handle this would be to use zend_string_to_unicode ( )
* to convert the binary defaults to their unicode counterparts .
*
* However , since these are simple fixed constants , it ' s cheaper
* to declare them as UChars locally and point at these versions .
*/
2006-12-05 04:52:44 +00:00
if ( delim_type = = IS_STRING ) {
2006-12-06 23:14:15 +00:00
delim . u = & udelim ;
2006-12-05 04:52:44 +00:00
delim_len = 1 ;
}
if ( enc_type = = IS_STRING ) {
2006-12-06 23:14:15 +00:00
enc . u = & uenc ;
2006-12-05 04:52:44 +00:00
enc_len = 1 ;
}
if ( esc_type = = IS_STRING ) {
2006-12-06 23:14:15 +00:00
esc . u = & uesc ;
2006-12-05 04:52:44 +00:00
esc_len = 1 ;
}
2006-12-06 23:14:15 +00:00
php_u_fgetcsv ( NULL , delim . u , delim_len , enc . u , enc_len , esc . u , esc_len , str . u , str_len , return_value TSRMLS_CC ) ;
2006-12-05 04:52:44 +00:00
} else {
2006-12-06 23:14:15 +00:00
php_fgetcsv_ex ( NULL , delim . s , delim_len , enc . s , enc_len , esc . s , esc_len , str . s , str_len , return_value TSRMLS_CC ) ;
2006-12-05 04:52:44 +00:00
}
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto string str_repeat(string input, int mult) U
1999-10-27 22:06:05 +00:00
Returns the input string repeat mult times */
PHP_FUNCTION ( str_repeat )
{
2005-08-11 23:36:07 +00:00
void * input_str ; /* Input string */
2006-03-02 13:12:45 +00:00
int input_str_len ;
int input_str_chars ;
2005-08-11 23:36:07 +00:00
zend_uchar input_str_type ;
long mult ; /* Multiplier */
void * result ; /* Resulting string */
2006-08-10 19:02:32 +00:00
size_t result_len ; /* Length of the resulting string, in bytes */
size_t result_chars ; /* Chars/UChars in resulting string */
2005-08-11 23:36:07 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " tl " , & input_str ,
& input_str_chars , & input_str_type , & mult ) = = FAILURE ) {
return ;
1999-10-27 22:06:05 +00:00
}
2005-08-11 23:36:07 +00:00
if ( mult < 0 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Second argument has to be greater than or equal to 0 " ) ;
1999-10-27 22:06:05 +00:00
return ;
}
2005-08-11 23:36:07 +00:00
/* Don't waste our time if input is empty or if the multiplier is zero */
if ( input_str_chars = = 0 | | mult = = 0 ) {
if ( input_str_type = = IS_UNICODE ) {
RETURN_UNICODEL ( USTR_MAKE ( " " ) , 0 , 0 ) ;
} else {
2006-01-17 12:18:53 +00:00
RETURN_STRINGL ( " " , 0 , 1 ) ;
2005-08-11 23:36:07 +00:00
}
}
2006-07-16 15:56:00 +00:00
/* Initialize the result string */
2005-08-11 23:36:07 +00:00
result_chars = ( input_str_chars * mult ) + 1 ;
if ( input_str_type = = IS_UNICODE ) {
input_str_len = UBYTES ( input_str_chars ) ;
result_len = UBYTES ( result_chars ) ;
2006-08-10 19:02:32 +00:00
result = ( char * ) safe_emalloc ( UBYTES ( input_str_chars ) , UBYTES ( mult ) , UBYTES ( 1 ) ) ;
2005-08-11 23:36:07 +00:00
} else {
input_str_len = input_str_chars ;
result_len = result_chars ;
2006-08-10 19:02:32 +00:00
result = ( char * ) safe_emalloc ( input_str_chars , mult , 1 ) ;
2003-04-02 00:25:45 +00:00
}
2006-07-16 15:56:00 +00:00
2002-10-04 17:10:51 +00:00
/* Heavy optimization for situations where input string is 1 byte long */
2005-08-11 23:36:07 +00:00
if ( input_str_len = = 1 ) {
memset ( result , * ( ( char * ) input_str ) , mult ) ;
2002-10-03 13:59:31 +00:00
} else {
char * s , * e , * ee ;
int l = 0 ;
2005-08-11 23:36:07 +00:00
memcpy ( result , input_str , input_str_len ) ;
2002-10-03 13:59:31 +00:00
s = result ;
2005-08-12 10:10:41 +00:00
e = ( char * ) result + input_str_len ;
ee = ( char * ) result + result_len ;
2005-08-11 23:36:07 +00:00
while ( e < ee ) {
2002-10-03 13:59:31 +00:00
l = ( e - s ) < ( ee - e ) ? ( e - s ) : ( ee - e ) ;
memmove ( e , s , l ) ;
e + = l ;
}
1999-10-27 22:06:05 +00:00
}
2006-07-16 15:56:00 +00:00
2005-08-11 23:36:07 +00:00
if ( input_str_type = = IS_UNICODE ) {
* ( ( ( UChar * ) result ) + result_chars - 1 ) = 0 ;
2005-08-12 13:41:15 +00:00
RETURN_UNICODEL ( ( UChar * ) result , result_chars - 1 , 0 ) ;
2005-08-11 23:36:07 +00:00
} else {
* ( ( ( char * ) result ) + result_chars - 1 ) = ' \0 ' ;
2006-01-17 12:18:53 +00:00
RETURN_STRINGL ( ( char * ) result , result_chars - 1 , 0 ) ;
2005-08-11 23:36:07 +00:00
}
1999-10-27 22:06:05 +00:00
}
/* }}} */
2006-09-22 17:47:09 +00:00
/* {{{ proto mixed count_chars(string input [, int mode]) U
1999-12-14 03:52:12 +00:00
Returns info about what characters are used in input */
PHP_FUNCTION ( count_chars )
{
2006-09-22 17:47:09 +00:00
zstr input ;
int input_len ;
zend_uchar type ;
long mode = 0 ;
1999-12-14 03:52:12 +00:00
int chars [ 256 ] ;
2006-09-22 17:47:09 +00:00
HashTable uchars ;
UChar32 cp ;
int * uchar_cnt_ptr , uchar_cnt ;
1999-12-14 03:52:12 +00:00
unsigned char * buf ;
2006-09-22 17:47:09 +00:00
int inx ;
1999-12-14 03:52:12 +00:00
char retstr [ 256 ] ;
int retlen = 0 ;
2006-10-03 13:44:14 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t|l " , & input , & input_len ,
2006-09-22 17:47:09 +00:00
& type , & mode ) = = FAILURE ) {
return ;
1999-12-14 03:52:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-09-22 17:47:09 +00:00
if ( ZEND_NUM_ARGS ( ) > 1 ) {
if ( mode < 0 | | mode > 4 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unknown mode " ) ;
1999-12-14 03:52:12 +00:00
RETURN_FALSE ;
}
2009-03-26 20:02:53 +00:00
if ( mode ! = 1 ) {
2006-09-23 12:22:07 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Only mode=1 is supported with Unicode strings " ) ;
2006-10-04 10:52:32 +00:00
RETURN_FALSE ;
2006-09-22 17:47:09 +00:00
}
1999-12-14 03:52:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-09-22 17:47:09 +00:00
if ( type = = IS_UNICODE ) {
UChar buf [ 3 ] ;
int buf_len ;
1999-12-14 03:52:12 +00:00
2006-09-22 17:47:09 +00:00
zend_hash_init ( & uchars , 0 , NULL , NULL , 0 ) ;
1999-12-14 03:52:12 +00:00
2006-09-22 17:47:09 +00:00
inx = 0 ;
while ( inx < input_len ) {
U16_NEXT_UNSAFE ( input . u , inx , cp ) ;
if ( zend_hash_index_find ( & uchars , cp , ( void * * ) & uchar_cnt_ptr ) = = SUCCESS ) {
( * uchar_cnt_ptr ) + + ;
} else {
uchar_cnt = 1 ;
zend_hash_index_update ( & uchars , cp , & uchar_cnt , sizeof ( int ) , NULL ) ;
}
}
1999-12-14 03:52:12 +00:00
2006-09-22 17:47:09 +00:00
if ( mode < 3 ) {
array_init ( return_value ) ;
}
for ( zend_hash_internal_pointer_reset ( & uchars ) ;
zend_hash_get_current_data ( & uchars , ( void * * ) & uchar_cnt_ptr ) = = SUCCESS ;
zend_hash_move_forward ( & uchars ) ) {
zend_hash_get_current_key ( & uchars , NULL , ( ulong * ) & cp , 0 ) ;
buf_len = zend_codepoint_to_uchar ( cp , buf ) ;
buf [ buf_len ] = 0 ;
add_u_assoc_long_ex ( return_value , IS_UNICODE , ZSTR ( buf ) , buf_len + 1 , * uchar_cnt_ptr ) ;
}
zend_hash_destroy ( & uchars ) ;
} else {
buf = ( unsigned char * ) input . s ;
memset ( ( void * ) chars , 0 , sizeof ( chars ) ) ;
while ( input_len > 0 ) {
chars [ * buf ] + + ;
buf + + ;
input_len - - ;
1999-12-14 03:52:12 +00:00
}
2006-07-16 15:56:00 +00:00
2006-09-22 17:47:09 +00:00
if ( mode < 3 ) {
array_init ( return_value ) ;
}
for ( inx = 0 ; inx < 256 ; inx + + ) {
switch ( mode ) {
case 0 :
add_index_long ( return_value , inx , chars [ inx ] ) ;
break ;
case 1 :
if ( chars [ inx ] ! = 0 ) {
add_index_long ( return_value , inx , chars [ inx ] ) ;
}
break ;
case 2 :
if ( chars [ inx ] = = 0 ) {
add_index_long ( return_value , inx , chars [ inx ] ) ;
}
break ;
case 3 :
if ( chars [ inx ] ! = 0 ) {
retstr [ retlen + + ] = inx ;
}
break ;
case 4 :
if ( chars [ inx ] = = 0 ) {
retstr [ retlen + + ] = inx ;
}
break ;
}
}
if ( mode > = 3 & & mode < = 4 ) {
RETURN_STRINGL ( retstr , retlen , 1 ) ;
}
1999-12-14 03:52:12 +00:00
}
}
/* }}} */
2000-04-12 19:39:02 +00:00
2001-06-05 13:12:10 +00:00
/* {{{ php_strnatcmp
*/
2000-04-12 19:39:02 +00:00
static void php_strnatcmp ( INTERNAL_FUNCTION_PARAMETERS , int fold_case )
{
2006-12-21 21:47:56 +00:00
zstr s1 , s2 ;
int s1_len , s2_len ;
zend_uchar type ;
2000-04-12 19:39:02 +00:00
2006-12-21 21:47:56 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT " , & s1 , & s1_len ,
& type , & s2 , & s2_len , & type ) = = FAILURE ) {
return ;
2000-04-12 19:39:02 +00:00
}
2006-12-21 21:47:56 +00:00
if ( type = = IS_UNICODE ) {
RETURN_LONG ( u_strnatcmp_ex ( s1 . u , s1_len , s2 . u , s2_len , fold_case ) ) ;
} else {
RETURN_LONG ( strnatcmp_ex ( s1 . s , s1_len , s2 . s , s2_len , fold_case ) ) ;
}
2000-04-12 19:39:02 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
2000-04-26 00:29:59 +00:00
2006-12-21 21:47:56 +00:00
/* {{{ proto int strnatcmp(string s1, string s2) U
2000-04-26 00:29:59 +00:00
Returns the result of string comparison using ' natural ' algorithm */
2000-04-12 19:39:02 +00:00
PHP_FUNCTION ( strnatcmp )
{
php_strnatcmp ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
}
2000-04-26 00:29:59 +00:00
/* }}} */
2000-04-12 19:39:02 +00:00
2006-09-22 18:24:12 +00:00
/* {{{ proto array localeconv(void) U
2001-04-29 13:30:56 +00:00
Returns numeric formatting information based on the current locale */
2001-01-14 16:36:30 +00:00
PHP_FUNCTION ( localeconv )
{
zval * grouping , * mon_grouping ;
int len , i ;
/* We don't need no stinkin' parameters... */
2008-02-28 14:16:25 +00:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
2006-09-22 18:24:12 +00:00
return ;
}
2009-03-26 20:02:53 +00:00
php_error_docref ( NULL TSRMLS_CC , E_DEPRECATED , " deprecated in Unicode mode, please use ICU locale functions " ) ;
2001-01-14 16:36:30 +00:00
2003-01-05 04:29:14 +00:00
MAKE_STD_ZVAL ( grouping ) ;
MAKE_STD_ZVAL ( mon_grouping ) ;
2002-12-05 22:28:02 +00:00
array_init ( return_value ) ;
array_init ( grouping ) ;
array_init ( mon_grouping ) ;
2001-01-14 16:36:30 +00:00
# ifdef HAVE_LOCALECONV
{
struct lconv currlocdata ;
localeconv_r ( & currlocdata ) ;
2006-07-16 15:56:00 +00:00
2001-01-14 16:36:30 +00:00
/* Grab the grouping data out of the array */
len = strlen ( currlocdata . grouping ) ;
2002-10-02 17:56:04 +00:00
for ( i = 0 ; i < len ; i + + ) {
2001-01-14 16:36:30 +00:00
add_index_long ( grouping , i , currlocdata . grouping [ i ] ) ;
}
/* Grab the monetary grouping data out of the array */
len = strlen ( currlocdata . mon_grouping ) ;
2002-10-02 17:56:04 +00:00
for ( i = 0 ; i < len ; i + + ) {
2001-01-14 16:36:30 +00:00
add_index_long ( mon_grouping , i , currlocdata . mon_grouping [ i ] ) ;
}
2006-09-19 10:38:31 +00:00
add_ascii_assoc_string ( return_value , " decimal_point " , currlocdata . decimal_point , 1 ) ;
add_ascii_assoc_string ( return_value , " thousands_sep " , currlocdata . thousands_sep , 1 ) ;
add_ascii_assoc_string ( return_value , " int_curr_symbol " , currlocdata . int_curr_symbol , 1 ) ;
add_ascii_assoc_string ( return_value , " currency_symbol " , currlocdata . currency_symbol , 1 ) ;
add_ascii_assoc_string ( return_value , " mon_decimal_point " , currlocdata . mon_decimal_point , 1 ) ;
add_ascii_assoc_string ( return_value , " mon_thousands_sep " , currlocdata . mon_thousands_sep , 1 ) ;
add_ascii_assoc_string ( return_value , " positive_sign " , currlocdata . positive_sign , 1 ) ;
add_ascii_assoc_string ( return_value , " negative_sign " , currlocdata . negative_sign , 1 ) ;
add_ascii_assoc_long ( return_value , " int_frac_digits " , currlocdata . int_frac_digits ) ;
add_ascii_assoc_long ( return_value , " frac_digits " , currlocdata . frac_digits ) ;
add_ascii_assoc_long ( return_value , " p_cs_precedes " , currlocdata . p_cs_precedes ) ;
add_ascii_assoc_long ( return_value , " p_sep_by_space " , currlocdata . p_sep_by_space ) ;
add_ascii_assoc_long ( return_value , " n_cs_precedes " , currlocdata . n_cs_precedes ) ;
add_ascii_assoc_long ( return_value , " n_sep_by_space " , currlocdata . n_sep_by_space ) ;
add_ascii_assoc_long ( return_value , " p_sign_posn " , currlocdata . p_sign_posn ) ;
add_ascii_assoc_long ( return_value , " n_sign_posn " , currlocdata . n_sign_posn ) ;
2001-01-14 16:36:30 +00:00
}
# else
/* Ok, it doesn't look like we have locale info floating around, so I guess it
wouldn ' t hurt to just go ahead and return the POSIX locale information ? */
add_index_long ( grouping , 0 , - 1 ) ;
add_index_long ( mon_grouping , 0 , - 1 ) ;
2006-09-19 10:38:31 +00:00
add_ascii_assoc_string ( return_value , " decimal_point " , " \x2E " , 1 ) ;
add_ascii_assoc_string ( return_value , " thousands_sep " , " " , 1 ) ;
add_ascii_assoc_string ( return_value , " int_curr_symbol " , " " , 1 ) ;
add_ascii_assoc_string ( return_value , " currency_symbol " , " " , 1 ) ;
add_ascii_assoc_string ( return_value , " mon_decimal_point " , " \x2E " , 1 ) ;
add_ascii_assoc_string ( return_value , " mon_thousands_sep " , " " , 1 ) ;
add_ascii_assoc_string ( return_value , " positive_sign " , " " , 1 ) ;
add_ascii_assoc_string ( return_value , " negative_sign " , " " , 1 ) ;
add_ascii_assoc_long ( return_value , " int_frac_digits " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " frac_digits " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " p_cs_precedes " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " p_sep_by_space " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " n_cs_precedes " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " n_sep_by_space " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " p_sign_posn " , CHAR_MAX ) ;
add_ascii_assoc_long ( return_value , " n_sign_posn " , CHAR_MAX ) ;
2001-01-14 16:36:30 +00:00
# endif
2006-09-19 10:38:31 +00:00
zend_ascii_hash_update ( Z_ARRVAL_P ( return_value ) , " grouping " , 9 , & grouping , sizeof ( zval * ) , NULL ) ;
zend_ascii_hash_update ( Z_ARRVAL_P ( return_value ) , " mon_grouping " , 13 , & mon_grouping , sizeof ( zval * ) , NULL ) ;
2001-01-14 16:36:30 +00:00
}
2001-06-05 13:12:10 +00:00
/* }}} */
2000-04-26 00:29:59 +00:00
2006-12-21 21:47:56 +00:00
/* {{{ proto int strnatcasecmp(string s1, string s2) U
2000-04-26 00:29:59 +00:00
Returns the result of case - insensitive string comparison using ' natural ' algorithm */
2000-04-12 19:39:02 +00:00
PHP_FUNCTION ( strnatcasecmp )
{
php_strnatcmp ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
2000-04-26 00:29:59 +00:00
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto int substr_count(string haystack, string needle [, int offset [, int length]]) U
2000-08-06 14:36:10 +00:00
Returns the number of times a substring occurs in the string */
2000-04-26 00:29:59 +00:00
PHP_FUNCTION ( substr_count )
{
2005-08-27 19:14:05 +00:00
void * haystack , * needle ;
2005-12-09 13:41:06 +00:00
int haystack_len , needle_len ;
2005-08-27 19:14:05 +00:00
zend_uchar haystack_type , needle_type ;
long offset = 0 , length = 0 ;
2005-06-18 18:23:12 +00:00
int ac = ZEND_NUM_ARGS ( ) ;
2002-10-09 13:37:02 +00:00
int count = 0 ;
2005-08-27 19:14:05 +00:00
void * p , * endp , * tmp ;
2006-07-13 17:55:50 +00:00
int32_t i = 0 , j ;
2005-08-27 19:14:05 +00:00
char cmp ;
if ( zend_parse_parameters ( ac TSRMLS_CC , " TT|ll " ,
& haystack , & haystack_len , & haystack_type ,
& needle , & needle_len , & needle_type ,
& offset , & length ) = = FAILURE ) {
return ;
2000-04-26 00:29:59 +00:00
}
2005-08-27 19:14:05 +00:00
if ( needle_len = = 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Empty substring " ) ;
2000-04-26 00:29:59 +00:00
RETURN_FALSE ;
2002-10-09 13:37:02 +00:00
}
2005-08-27 19:14:05 +00:00
if ( haystack_type = = IS_UNICODE ) {
p = ( UChar * ) haystack ;
endp = ( UChar * ) haystack + haystack_len ;
} else {
p = ( char * ) haystack ;
endp = ( char * ) haystack + haystack_len ;
}
2005-06-18 18:23:12 +00:00
if ( ac > 2 ) {
2005-08-27 19:14:05 +00:00
if ( offset < 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset should be greater than or equal to 0 " ) ;
2005-08-27 19:14:05 +00:00
RETURN_FALSE ;
}
if ( haystack_type = = IS_UNICODE ) {
i = 0 ;
U16_FWD_N ( ( UChar * ) haystack , i , haystack_len , offset ) ;
p = ( UChar * ) haystack + i ;
} else {
p = ( char * ) haystack + offset ;
2005-07-07 15:19:40 +00:00
}
2005-06-18 18:23:12 +00:00
if ( p > endp ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Offset value %ld exceeds string length " , offset ) ;
2005-08-27 19:14:05 +00:00
RETURN_FALSE ;
2005-06-18 18:23:12 +00:00
}
if ( ac = = 4 ) {
2005-08-27 19:14:05 +00:00
if ( length < 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Length should be greater than 0 " ) ;
2005-08-27 19:14:05 +00:00
RETURN_FALSE ;
}
if ( haystack_type = = IS_UNICODE ) {
j = i ;
i = 0 ;
U16_FWD_N ( ( UChar * ) p , i , haystack_len - j , length ) ;
tmp = ( UChar * ) p + i ;
} else {
tmp = ( char * ) p + length ;
2005-07-07 15:19:40 +00:00
}
2005-08-27 19:14:05 +00:00
if ( tmp > endp ) {
2007-06-18 13:39:02 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Length value %ld exceeds string length " , length ) ;
2005-06-18 18:23:12 +00:00
RETURN_FALSE ;
2005-08-27 19:14:05 +00:00
} else {
endp = tmp ;
2005-06-18 18:23:12 +00:00
}
}
}
2005-06-19 16:31:51 +00:00
2005-08-27 19:14:05 +00:00
if ( haystack_type = = IS_UNICODE ) {
while ( ( p = zend_u_memnstr ( ( UChar * ) p , ( UChar * ) needle , needle_len , ( UChar * ) endp ) ) ! = NULL ) {
2005-08-29 06:51:14 +00:00
/*(UChar *)p += needle_len; // GCC 4.0.0 cannot compile this */
2005-09-07 07:00:03 +00:00
p = ( UChar * ) p + needle_len ;
2005-06-19 16:31:51 +00:00
count + + ;
2000-04-26 00:29:59 +00:00
}
} else {
2005-08-27 19:14:05 +00:00
if ( needle_len = = 1 ) {
cmp = ( ( char * ) needle ) [ 0 ] ;
2005-09-05 16:37:45 +00:00
while ( ( p = memchr ( p , cmp , ( char * ) endp - ( char * ) p ) ) ) {
2005-08-27 19:14:05 +00:00
count + + ;
2005-09-05 16:37:45 +00:00
p = ( char * ) p + 1 ;
2005-08-27 19:14:05 +00:00
}
} else {
while ( ( p = php_memnstr ( ( char * ) p , ( char * ) needle , needle_len , ( char * ) endp ) ) ) {
2005-08-29 06:51:14 +00:00
/*(char *)p += needle_len; // GCC 4.0.0 cannot compile this */
2005-09-05 16:37:45 +00:00
p = ( char * ) p + needle_len ;
2005-08-27 19:14:05 +00:00
count + + ;
}
2000-04-26 00:29:59 +00:00
}
}
RETURN_LONG ( count ) ;
}
2006-07-16 15:56:00 +00:00
/* }}} */
2000-06-06 20:42:33 +00:00
2006-03-02 20:37:07 +00:00
/* {{{ proto string str_pad(string input, int pad_length [, string pad_string [, int pad_type]]) U
2000-06-06 20:42:33 +00:00
Returns input string padded on the left or right to specified length with pad_string */
PHP_FUNCTION ( str_pad )
{
2000-07-08 20:38:23 +00:00
/* Input arguments */
2005-09-05 10:55:35 +00:00
void * input ; /* Input string */
2006-03-01 11:19:35 +00:00
long pad_length ; /* Length to pad to, in codepoints for Unicode */
2005-09-05 10:55:35 +00:00
void * padstr ; /* Padding string */
2006-03-01 11:19:35 +00:00
long pad_type ; /* Padding type (left/right/both) */
2005-12-09 13:41:06 +00:00
int input_len , padstr_len ; /* Lengths in code units for Unicode */
2005-09-05 10:55:35 +00:00
zend_uchar input_type , padstr_type ;
2006-07-16 15:56:00 +00:00
2000-07-08 20:38:23 +00:00
/* Helper variables */
2006-03-02 13:12:45 +00:00
int input_codepts ; /* Number of codepts in Unicode input */
int num_pad_chars ; /* Number of padding characters (total - input size) */
2005-09-05 10:55:35 +00:00
void * result = NULL ; /* Resulting string */
int32_t result_len = 0 ; /* Length of the resulting string */
int32_t i , j , left_pad = 0 , right_pad = 0 ;
UChar32 ch ;
2000-06-06 20:42:33 +00:00
2000-07-08 20:38:23 +00:00
2005-09-05 10:55:35 +00:00
if ( ZEND_NUM_ARGS ( ) < 2 | | ZEND_NUM_ARGS ( ) > 4 ) {
2000-06-06 20:42:33 +00:00
WRONG_PARAM_COUNT ;
}
2005-09-05 10:55:35 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " Tl|Tl " ,
& input , & input_len , & input_type , & pad_length ,
& padstr , & padstr_len , & padstr_type , & pad_type ) = = FAILURE ) {
return ;
}
2000-06-06 20:42:33 +00:00
2005-09-05 10:55:35 +00:00
if ( input_type = = IS_UNICODE ) {
/* For Unicode, num_pad_chars/pad_length is number of codepoints */
i = 0 ; input_codepts = 0 ;
2005-09-09 19:07:18 +00:00
input_codepts = u_countChar32 ( ( UChar * ) input , input_len ) ;
2005-09-05 10:55:35 +00:00
num_pad_chars = pad_length - input_codepts ;
} else {
num_pad_chars = pad_length - input_len ;
}
2000-06-06 20:42:33 +00:00
/* If resulting string turns out to be shorter than input string,
we simply copy the input and return . */
2007-07-23 13:27:34 +00:00
if ( pad_length < 0 | | num_pad_chars < 0 ) {
2005-09-05 10:55:35 +00:00
if ( input_type = = IS_UNICODE ) {
RETURN_UNICODEL ( ( UChar * ) input , input_len , 1 ) ;
} else {
RETURN_STRINGL ( ( char * ) input , input_len , 1 ) ;
}
2000-06-06 20:42:33 +00:00
}
2005-09-05 10:55:35 +00:00
/* Setup the padding string values if NOT specified. */
2000-06-06 20:42:33 +00:00
if ( ZEND_NUM_ARGS ( ) > 2 ) {
2005-09-05 10:55:35 +00:00
if ( padstr_len = = 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Padding string cannot be empty " ) ;
2000-06-06 20:42:33 +00:00
return ;
}
2000-07-08 20:38:23 +00:00
if ( ZEND_NUM_ARGS ( ) > 3 ) {
2005-09-05 10:55:35 +00:00
if ( pad_type < STR_PAD_LEFT | | pad_type > STR_PAD_BOTH ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH " ) ;
2000-07-08 20:38:23 +00:00
return ;
}
2005-09-05 10:55:35 +00:00
} else {
pad_type = STR_PAD_RIGHT ;
}
} else {
if ( input_type = = IS_UNICODE ) {
padstr = USTR_MAKE ( " " ) ;
} else {
padstr = " " ;
2000-07-08 20:38:23 +00:00
}
2005-09-05 10:55:35 +00:00
padstr_len = 1 ;
pad_type = STR_PAD_RIGHT ;
2000-06-06 20:42:33 +00:00
}
2005-09-05 10:55:35 +00:00
if ( input_type = = IS_UNICODE ) {
2005-09-09 19:07:18 +00:00
result = eumalloc ( input_len + num_pad_chars * 2 + 1 ) ;
2005-09-05 10:55:35 +00:00
} else {
result = emalloc ( input_len + num_pad_chars + 1 ) ;
}
2000-06-06 20:42:33 +00:00
2000-07-08 20:38:23 +00:00
/* We need to figure out the left/right padding lengths. */
2005-09-05 10:55:35 +00:00
switch ( pad_type ) {
2000-07-08 20:38:23 +00:00
case STR_PAD_RIGHT :
left_pad = 0 ;
right_pad = num_pad_chars ;
break ;
case STR_PAD_LEFT :
left_pad = num_pad_chars ;
right_pad = 0 ;
break ;
case STR_PAD_BOTH :
left_pad = num_pad_chars / 2 ;
right_pad = num_pad_chars - left_pad ;
break ;
2000-06-06 20:42:33 +00:00
}
2005-09-05 10:55:35 +00:00
/* Pad left, copy input, pad right, terminate */
if ( input_type = = IS_UNICODE ) {
j = 0 ;
for ( i = 0 ; i < left_pad ; i + + ) {
if ( j > = padstr_len ) {
j = 0 ;
}
U16_NEXT ( ( UChar * ) padstr , j , padstr_len , ch ) ;
result_len + = zend_codepoint_to_uchar ( ch , ( UChar * ) result + result_len ) ;
}
memcpy ( ( UChar * ) result + result_len , input , UBYTES ( input_len ) ) ;
result_len + = input_len ;
j = 0 ;
for ( i = 0 ; i < right_pad ; i + + ) {
if ( j > = padstr_len ) {
j = 0 ;
}
U16_NEXT ( ( UChar * ) padstr , j , padstr_len , ch ) ;
result_len + = zend_codepoint_to_uchar ( ch , ( UChar * ) result + result_len ) ;
}
* ( ( UChar * ) result + result_len ) = 0 ;
2005-09-09 19:07:18 +00:00
result = eurealloc ( result , result_len + 1 ) ;
2005-09-05 10:55:35 +00:00
} else {
for ( i = 0 ; i < left_pad ; i + + )
* ( ( char * ) result + result_len + + ) = * ( ( char * ) padstr + ( i % padstr_len ) ) ;
2005-09-05 16:37:45 +00:00
memcpy ( ( char * ) result + result_len , input , input_len ) ;
2005-09-05 10:55:35 +00:00
result_len + = input_len ;
for ( i = 0 ; i < right_pad ; i + + )
* ( ( char * ) result + result_len + + ) = * ( ( char * ) padstr + ( i % padstr_len ) ) ;
* ( ( char * ) result + result_len ) = ' \0 ' ;
}
if ( input_type = = IS_UNICODE ) {
if ( ZEND_NUM_ARGS ( ) < 3 ) {
efree ( padstr ) ;
}
RETURN_UNICODEL ( ( UChar * ) result , result_len , 0 ) ;
} else {
RETURN_STRINGL ( ( char * ) result , result_len , 0 ) ;
}
2000-06-06 20:42:33 +00:00
}
2000-06-06 18:58:15 +00:00
/* }}} */
2006-07-16 15:56:00 +00:00
2006-12-26 22:34:05 +00:00
/* {{{ proto mixed sscanf(string str, string format [, string ...]) U
2000-07-09 19:33:19 +00:00
Implements an ANSI C compatible sscanf */
2000-06-06 18:58:15 +00:00
PHP_FUNCTION ( sscanf )
{
2008-08-16 21:16:25 +00:00
zval * * * args = NULL ;
zstr str , format ;
int str_len , format_len , result , num_args = 0 ;
zend_uchar str_type , format_type ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT* " , & str , & str_len , & str_type ,
& format , & format_len , & format_type , & args , & num_args ) = = FAILURE ) {
return ;
2006-12-26 22:34:05 +00:00
}
2008-08-16 21:16:25 +00:00
if ( str_type = = IS_UNICODE ) {
result = php_u_sscanf_internal ( str . u , format . u , num_args , args , 0 , & return_value TSRMLS_CC ) ;
2006-12-26 22:34:05 +00:00
} else {
2008-08-16 21:16:25 +00:00
result = php_sscanf_internal ( str . s , format . s , num_args , args , 0 , & return_value TSRMLS_CC ) ;
}
if ( args ) {
efree ( args ) ;
2006-12-26 22:34:05 +00:00
}
2000-06-06 18:58:15 +00:00
if ( SCAN_ERROR_WRONG_PARAM_COUNT = = result ) {
2000-06-12 16:06:27 +00:00
WRONG_PARAM_COUNT ;
2000-06-06 18:58:15 +00:00
}
}
/* }}} */
2002-08-20 20:47:47 +00:00
static char rot13_from [ ] = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
static char rot13_to [ ] = " nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM " ;
2006-08-14 11:59:07 +00:00
U_STRING_DECL ( u_rot13_from , " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " , sizeof ( rot13_from ) - 1 ) ;
U_STRING_DECL ( u_rot13_to , " nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM " , sizeof ( rot13_to ) - 1 ) ;
2006-08-09 20:03:22 +00:00
/* {{{ proto string str_rot13(string str) U
2001-12-06 19:02:27 +00:00
Perform the rot13 transform on a string */
2001-12-06 21:39:01 +00:00
PHP_FUNCTION ( str_rot13 )
2001-12-06 19:02:27 +00:00
{
2006-08-09 20:03:22 +00:00
static int did_init_strings = FALSE ;
zstr str ;
int str_len ;
zend_uchar str_type ;
2002-07-30 10:51:33 +00:00
2006-08-09 20:03:22 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2001-12-06 19:02:27 +00:00
}
2006-01-28 00:13:13 +00:00
2006-08-09 20:03:22 +00:00
if ( ! did_init_strings ) {
U_STRING_INIT ( u_rot13_from , rot13_from , sizeof ( rot13_from ) - 1 ) ;
U_STRING_INIT ( u_rot13_to , rot13_to , sizeof ( rot13_to ) - 1 ) ;
did_init_strings = TRUE ;
}
2001-12-06 19:02:27 +00:00
2006-08-09 20:03:22 +00:00
if ( str_type = = IS_UNICODE ) {
RETVAL_UNICODEL ( str . u , str_len , 0 ) ;
2006-08-09 20:31:06 +00:00
Z_USTRVAL_P ( return_value ) = php_u_strtr ( Z_USTRVAL_P ( return_value ) , Z_USTRLEN_P ( return_value ) , u_rot13_from , 52 , u_rot13_to , 52 , 52 , & Z_USTRLEN_P ( return_value ) TSRMLS_CC ) ;
2006-08-09 20:03:22 +00:00
} else {
RETVAL_STRINGL ( str . s , str_len , 1 ) ;
php_strtr ( Z_STRVAL_P ( return_value ) , Z_STRLEN_P ( return_value ) , rot13_from , rot13_to , 52 ) ;
}
2001-12-06 19:02:27 +00:00
}
/* }}} */
2007-06-05 13:37:05 +00:00
static void php_string_shuffle ( zstr str , int len , zend_uchar str_type TSRMLS_DC ) /* { { { */
2002-09-25 18:06:05 +00:00
{
2006-08-09 20:19:06 +00:00
int rnd_idx , n_left ;
2002-10-08 09:52:59 +00:00
char temp ;
2006-08-09 20:19:06 +00:00
UChar u_temp ;
2002-10-08 09:52:59 +00:00
/* The implementation is stolen from array_data_shuffle */
/* Thus the characteristics of the randomization are the same */
2006-07-16 15:56:00 +00:00
2006-08-09 20:19:06 +00:00
if ( len < = 1 ) {
2002-10-08 09:52:59 +00:00
return ;
}
2006-08-09 20:19:06 +00:00
n_left = len ;
2006-07-16 15:56:00 +00:00
2002-10-08 09:52:59 +00:00
while ( - - n_left ) {
rnd_idx = php_rand ( TSRMLS_C ) ;
RAND_RANGE ( rnd_idx , 0 , n_left , PHP_RAND_MAX ) ;
2006-08-09 20:19:06 +00:00
if ( str_type = = IS_UNICODE ) {
if ( rnd_idx ! = n_left ) {
u_temp = str . u [ n_left ] ;
str . u [ n_left ] = str . u [ rnd_idx ] ;
str . u [ rnd_idx ] = u_temp ;
}
} else {
if ( rnd_idx ! = n_left ) {
temp = str . s [ n_left ] ;
str . s [ n_left ] = str . s [ rnd_idx ] ;
str . s [ rnd_idx ] = temp ;
}
2002-10-08 09:52:59 +00:00
}
}
2002-09-25 18:06:05 +00:00
}
2007-06-05 13:37:05 +00:00
/* }}} */
2002-10-08 09:52:59 +00:00
2006-08-09 20:19:06 +00:00
/* {{{ proto void str_shuffle(string str) U
2002-09-25 18:06:05 +00:00
Shuffles string . One permutation of all possible is created */
PHP_FUNCTION ( str_shuffle )
{
2006-08-09 20:19:06 +00:00
zstr str ;
int str_len ;
zend_uchar str_type ;
2006-07-16 15:56:00 +00:00
2006-08-09 20:19:06 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t " , & str , & str_len , & str_type ) = = FAILURE ) {
return ;
2002-09-25 18:06:05 +00:00
}
2006-07-16 15:56:00 +00:00
2006-12-19 21:38:59 +00:00
RETVAL_ZSTRL ( str_type , str , str_len , 1 ) ;
2006-08-09 20:19:06 +00:00
if ( Z_UNILEN_P ( return_value ) > 1 ) {
php_string_shuffle ( Z_UNIVAL_P ( return_value ) , Z_UNILEN_P ( return_value ) , Z_TYPE_P ( return_value ) TSRMLS_CC ) ;
2002-10-09 10:33:22 +00:00
}
2002-09-25 18:06:05 +00:00
}
/* }}} */
2006-08-18 18:01:58 +00:00
/* {{{ php_u_str_word_count */
static int php_u_str_word_count ( UChar * str , int str_len , long type , UChar * char_list , int char_list_len , zval * return_value TSRMLS_DC )
2002-10-17 03:27:19 +00:00
{
2006-08-18 18:01:58 +00:00
UChar * s , * buf ;
UChar32 ch ;
int ws , we , tmp , idx , last_idx ;
int word_count = 0 ;
2005-03-12 17:51:19 +00:00
2006-08-18 18:01:58 +00:00
if ( char_list ) {
char_list = eustrndup ( char_list , char_list_len ) ;
php_expand_uchar_range ( & char_list , & char_list_len TSRMLS_CC ) ;
2002-10-17 03:27:19 +00:00
}
2005-03-12 17:51:19 +00:00
2006-08-18 18:01:58 +00:00
ws = idx = 0 ;
/* first character cannot be ' or -, unless explicitly allowed by the user */
if ( ( str [ ws ] = = ( UChar ) 0x27 /*'\''*/ & & ( ! char_list | | ! u_memchr ( char_list , 0x27 /*'\''*/ , char_list_len ) ) ) | |
( str [ ws ] = = ( UChar ) 0x2d /*'-'*/ & & ( ! char_list | | ! u_memchr ( char_list , 0x2d /*'-'*/ , char_list_len ) ) ) ) {
ws + + ;
idx + + ;
}
/* last character cannot be -, unless explicitly allowed by the user */
2006-10-11 13:14:08 +00:00
if ( str_len & & str [ str_len - 1 ] = = ( UChar ) 0x2d /*'-'*/ & &
2006-08-18 18:01:58 +00:00
( ! char_list | | ! u_memchr ( char_list , 0x2d /*'-'*/ , char_list_len ) ) ) {
str_len - - ;
}
last_idx = idx ;
tmp = we = ws ;
while ( we < str_len ) {
s = str + ws ;
while ( we < str_len ) {
U16_NEXT ( str , tmp , str_len , ch ) ;
idx + + ;
if ( ! ( u_isalpha ( ch ) | | ( char_list & & u_memchr32 ( char_list , ch , char_list_len ) ) | |
ch = = ( UChar32 ) 0x27 /*'\''*/ | | ch = = ( UChar32 ) 0x2d /*'-'*/ ) ) {
break ;
}
we = tmp ;
}
if ( we > ws ) {
switch ( type )
{
case 1 :
buf = eustrndup ( s , ( we - ws ) ) ;
add_next_index_unicodel ( return_value , buf , ( we - ws ) , 0 ) ;
break ;
case 2 :
buf = eustrndup ( s , ( we - ws ) ) ;
add_index_unicodel ( return_value , last_idx , buf , we - ws , 0 ) ;
break ;
default :
word_count + + ;
break ;
}
}
ws = we = tmp ;
last_idx = idx ;
}
if ( char_list ) {
efree ( char_list ) ;
}
return word_count ;
}
/* }}} */
/* {{{ php_str_word_count */
2006-08-22 04:54:00 +00:00
static int php_str_word_count ( char * str , int str_len , long type , char * char_list , int char_list_len , zval * return_value TSRMLS_DC )
2006-08-18 18:01:58 +00:00
{
char ch [ 256 ] , * p , * e , * s , * buf ;
int word_count = 0 ;
2005-03-12 17:51:19 +00:00
if ( char_list ) {
2006-03-02 13:12:45 +00:00
php_charmask ( ( unsigned char * ) char_list , char_list_len , ch TSRMLS_CC ) ;
2005-03-12 17:51:19 +00:00
}
2006-07-16 15:56:00 +00:00
2005-03-12 17:51:19 +00:00
p = str ;
e = str + str_len ;
2006-07-16 15:56:00 +00:00
2005-11-29 16:14:47 +00:00
/* first character cannot be ' or -, unless explicitly allowed by the user */
if ( ( * p = = ' \' ' & & ( ! char_list | | ! ch [ ' \' ' ] ) ) | | ( * p = = ' - ' & & ( ! char_list | | ! ch [ ' - ' ] ) ) ) {
p + + ;
}
/* last character cannot be -, unless explicitly allowed by the user */
2006-10-11 13:14:08 +00:00
if ( str_len & & * ( e - 1 ) = = ' - ' & & ( ! char_list | | ! ch [ ' - ' ] ) ) {
2005-11-29 16:14:47 +00:00
e - - ;
}
2002-10-17 03:27:19 +00:00
while ( p < e ) {
2005-11-29 16:14:47 +00:00
s = p ;
2008-01-16 08:34:06 +00:00
while ( p < e & & ( isalpha ( ( unsigned char ) * p ) | | ( char_list & & ch [ ( unsigned char ) * p ] ) | | * p = = ' \' ' | | * p = = ' - ' ) ) {
2005-11-29 16:14:47 +00:00
p + + ;
}
if ( p > s ) {
2002-10-17 03:27:19 +00:00
switch ( type )
{
case 1 :
buf = estrndup ( s , ( p - s ) ) ;
2005-11-29 16:14:47 +00:00
add_next_index_stringl ( return_value , buf , ( p - s ) , 0 ) ;
2002-10-17 03:27:19 +00:00
break ;
case 2 :
buf = estrndup ( s , ( p - s ) ) ;
2005-11-29 16:14:47 +00:00
add_index_stringl ( return_value , ( s - str ) , buf , p - s , 0 ) ;
2002-10-17 03:27:19 +00:00
break ;
default :
word_count + + ;
2006-07-16 15:56:00 +00:00
break ;
2002-10-17 03:27:19 +00:00
}
2005-07-23 19:44:13 +00:00
}
2005-11-29 16:14:47 +00:00
p + + ;
2002-10-17 03:27:19 +00:00
}
2006-07-16 15:56:00 +00:00
2006-08-18 18:01:58 +00:00
return word_count ;
}
/* }}} */
/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]]) U
Counts the number of words inside a string . If format of 1 is specified ,
then the function will return an array containing all the words
found inside the string . If format of 2 is specified , then the function
will return an associated array where the position of the word is the key
and the word itself is the value .
For the purpose of this function , ' word ' is defined as a locale dependent
string containing alphabetic characters , which also may contain , but not start
with " ' " and " - " characters .
*/
PHP_FUNCTION ( str_word_count )
{
zstr str , char_list = NULL_ZSTR ;
2008-10-21 22:06:49 +00:00
int str_len , char_list_len = 0 , word_count = 0 ;
2006-08-18 18:01:58 +00:00
zend_uchar str_type ;
long type = 0 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " T|lT " , & str , & str_len ,
& str_type , & type , & char_list , & char_list_len , & str_type ) = = FAILURE ) {
return ;
}
2006-10-11 13:14:08 +00:00
switch ( type ) {
2006-10-11 14:30:50 +00:00
case 1 :
case 2 :
array_init ( return_value ) ;
if ( ! str_len ) {
return ;
}
break ;
case 0 :
if ( ! str_len ) {
RETURN_LONG ( 0 ) ;
}
break ;
default :
2006-10-11 13:14:08 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid format value %ld " , type ) ;
RETURN_FALSE ;
2006-10-11 14:30:50 +00:00
break ;
2006-08-18 18:01:58 +00:00
}
if ( str_type = = IS_UNICODE ) {
word_count = php_u_str_word_count ( str . u , str_len , type , char_list . u , char_list_len , return_value TSRMLS_CC ) ;
} else {
2006-08-22 04:54:00 +00:00
word_count = php_str_word_count ( str . s , str_len , type , char_list . s , char_list_len , return_value TSRMLS_CC ) ;
2006-08-18 18:01:58 +00:00
}
2002-10-17 03:27:19 +00:00
if ( ! type ) {
2006-07-16 15:56:00 +00:00
RETURN_LONG ( word_count ) ;
2002-10-17 03:27:19 +00:00
}
}
/* }}} */
2002-09-25 18:06:05 +00:00
2002-08-02 10:08:53 +00:00
# if HAVE_STRFMON
2006-09-22 18:24:12 +00:00
/* {{{ proto string money_format(string format , float value) U
2002-08-02 10:08:53 +00:00
Convert monetary value ( s ) to string */
2003-02-08 15:26:17 +00:00
PHP_FUNCTION ( money_format )
{
2002-08-21 13:14:57 +00:00
int format_len = 0 , str_len ;
2007-06-06 20:06:43 +00:00
char * format , * str , * p , * e ;
2002-08-02 10:08:53 +00:00
double value ;
2007-06-06 20:06:43 +00:00
zend_bool check = 0 ;
2002-08-02 10:08:53 +00:00
2003-02-08 15:26:17 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " sd " , & format , & format_len , & value ) = = FAILURE ) {
2002-08-02 10:08:53 +00:00
return ;
}
2007-06-06 20:06:43 +00:00
p = format ;
e = p + format_len ;
while ( ( p = memchr ( p , ' % ' , ( e - p ) ) ) ) {
if ( * ( p + 1 ) = = ' % ' ) {
p + = 2 ;
} else if ( ! check ) {
check = 1 ;
p + + ;
} else {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Only a single %%i or %%n token can be used " ) ;
RETURN_FALSE ;
}
}
2002-08-21 13:14:57 +00:00
str_len = format_len + 1024 ;
str = emalloc ( str_len ) ;
2003-04-16 01:07:03 +00:00
if ( ( str_len = strfmon ( str , str_len , format , value ) ) < 0 ) {
efree ( str ) ;
RETURN_FALSE ;
}
2002-08-21 13:14:57 +00:00
str [ str_len ] = 0 ;
2002-08-02 10:08:53 +00:00
2008-07-29 16:51:21 +00:00
RETURN_RT_STRINGL ( erealloc ( str , str_len + 1 ) , str_len , ZSTR_AUTOFREE ) ;
2002-08-02 10:08:53 +00:00
}
/* }}} */
# endif
2006-08-14 21:04:50 +00:00
/* {{{ proto array str_split(string str [, int split_length]) U
2003-02-07 21:36:18 +00:00
Convert a string to an array . If split_length is specified , break the string down into chunks each split_length characters long . */
2003-02-08 15:26:17 +00:00
PHP_FUNCTION ( str_split )
{
2006-08-14 21:04:50 +00:00
zstr str ;
2003-02-07 21:36:18 +00:00
int str_len ;
long split_length = 1 ;
char * p ;
2006-08-14 21:04:50 +00:00
zend_uchar str_type ;
2003-02-07 21:36:18 +00:00
int n_reg_segments ;
2006-08-14 21:04:50 +00:00
int charsize = 1 ;
2006-07-16 15:56:00 +00:00
2006-08-14 21:04:50 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " t|l " , & str , & str_len , & str_type , & split_length ) = = FAILURE ) {
2003-02-07 21:36:18 +00:00
return ;
}
if ( split_length < = 0 ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The length of each segment must be greater than zero " ) ;
2003-02-07 21:36:18 +00:00
RETURN_FALSE ;
}
2008-05-27 10:28:25 +00:00
array_init_size ( return_value , ( ( str_len - 1 ) / split_length ) + 1 ) ;
2003-02-07 21:36:18 +00:00
2004-10-20 22:44:43 +00:00
if ( split_length > = str_len ) {
2006-09-19 10:38:31 +00:00
add_next_index_zstrl ( return_value , str_type , str , str_len , 1 ) ;
2004-10-20 22:44:43 +00:00
return ;
}
2008-05-27 10:28:25 +00:00
n_reg_segments = str_len / split_length ;
2006-08-14 21:04:50 +00:00
p = str . s ;
if ( str_type = = IS_UNICODE ) {
charsize = 2 ;
}
2003-02-07 21:36:18 +00:00
while ( n_reg_segments - - > 0 ) {
2006-09-19 10:38:31 +00:00
add_next_index_zstrl ( return_value , str_type , ZSTR ( p ) , split_length , 1 ) ;
2006-08-14 21:04:50 +00:00
p + = split_length * charsize ;
2003-02-07 21:36:18 +00:00
}
2006-08-14 21:04:50 +00:00
if ( p ! = ( str . s + str_len * charsize ) ) {
2007-11-21 02:27:07 +00:00
add_next_index_zstrl ( return_value , str_type , ZSTR ( p ) , ( str . s + str_len * charsize - p ) / charsize , 1 ) ;
2003-02-07 21:36:18 +00:00
}
}
/* }}} */
2006-03-02 20:37:07 +00:00
/* {{{ proto array strpbrk(string haystack, string char_list) U
2003-02-11 22:47:26 +00:00
Search a string for any of a set of characters */
PHP_FUNCTION ( strpbrk )
{
2005-10-22 13:25:00 +00:00
void * haystack , * char_list ;
2005-12-09 13:41:06 +00:00
int haystack_len , char_list_len ;
2005-10-22 13:25:00 +00:00
zend_uchar haystack_type , char_list_type ;
void * p = NULL ;
2006-07-16 15:56:00 +00:00
2005-10-22 13:25:00 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TT " ,
& haystack , & haystack_len , & haystack_type ,
& char_list , & char_list_len , & char_list_type ) = = FAILURE ) {
2003-02-11 22:47:26 +00:00
RETURN_FALSE ;
}
if ( ! char_list_len ) {
2006-10-08 13:34:24 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The character list cannot be empty " ) ;
2006-07-16 15:56:00 +00:00
RETURN_FALSE ;
2003-02-11 22:47:26 +00:00
}
2005-10-22 13:25:00 +00:00
if ( haystack_type = = IS_UNICODE ) {
int32_t i , j ;
2006-07-13 17:55:50 +00:00
UChar32 ch1 , ch2 = 0 ;
2005-10-22 13:25:00 +00:00
for ( i = 0 ; i < haystack_len ; ) {
U16_NEXT ( ( UChar * ) haystack , i , haystack_len , ch1 ) ;
for ( j = 0 ; j < char_list_len ; ) {
U16_NEXT ( ( UChar * ) char_list , j , char_list_len , ch2 ) ;
if ( ch1 = = ch2 ) {
U16_BACK_1 ( ( UChar * ) haystack , 0 , i ) ;
p = ( UChar * ) haystack + i ;
break ;
}
}
if ( ch1 = = ch2 ) {
break ;
}
}
} else {
p = strpbrk ( ( char * ) haystack , ( char * ) char_list ) ;
}
if ( p ) {
if ( haystack_type = = IS_UNICODE ) {
RETURN_UNICODEL ( ( UChar * ) p , ( ( UChar * ) haystack + haystack_len - ( UChar * ) p ) , 1 ) ;
} else {
RETURN_STRINGL ( ( char * ) p , ( ( char * ) haystack + haystack_len - ( char * ) p ) , 1 ) ;
}
2003-02-11 22:47:26 +00:00
} else {
RETURN_FALSE ;
}
}
/* }}} */
2003-02-07 21:36:18 +00:00
2006-10-04 17:25:12 +00:00
/* {{{ proto int substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]]) U
2003-10-30 00:49:33 +00:00
Binary safe optionally case insensitive comparison of 2 strings from an offset , up to length characters */
PHP_FUNCTION ( substr_compare )
{
2006-10-04 17:25:12 +00:00
zstr s1 , s2 ;
2003-10-30 00:49:33 +00:00
int s1_len , s2_len ;
2006-10-04 17:25:12 +00:00
zend_uchar str_type ;
long offset , start_offset , end_offset , len = 0 ;
2003-10-30 00:49:33 +00:00
zend_bool cs = 0 ;
uint cmp_len ;
2006-10-04 17:25:12 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " TTl|lb " , & s1 , & s1_len ,
& str_type , & s2 , & s2_len , & str_type , & offset , & len , & cs ) = = FAILURE ) {
2003-10-30 00:49:33 +00:00
RETURN_FALSE ;
}
2006-04-25 12:49:04 +00:00
if ( ZEND_NUM_ARGS ( ) > = 4 & & len < = 0 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The length must be greater than zero " ) ;
RETURN_FALSE ;
}
2006-10-04 17:25:12 +00:00
if ( str_type = = IS_UNICODE ) {
/* calculate starting offset of the segment */
if ( offset < 0 ) {
if ( - offset > s1_len ) {
start_offset = 0 ;
} else {
start_offset = s1_len ;
U16_BACK_N ( s1 . u , 0 , start_offset , - offset ) ;
}
} else {
start_offset = 0 ;
U16_FWD_N ( s1 . u , start_offset , s1_len , offset ) ;
}
2005-09-26 23:08:10 +00:00
2006-10-04 17:25:12 +00:00
/* calculate ending offset of the segment */
if ( len ) {
end_offset = start_offset ;
while ( len > 0 & & end_offset < s1_len ) {
U16_FWD_1_UNSAFE ( s1 . u , end_offset ) ;
- - len ;
}
} else {
end_offset = s1_len ;
}
2003-10-30 00:49:33 +00:00
2006-10-04 17:25:12 +00:00
cmp_len = MAX ( s2_len , ( end_offset - start_offset ) ) ;
2003-10-30 00:49:33 +00:00
2006-10-04 17:25:12 +00:00
if ( ! cs ) {
RETURN_LONG ( zend_u_binary_strncmp ( s1 . u + start_offset , ( s1_len - start_offset ) , s2 . u , s2_len , cmp_len ) ) ;
} else {
RETURN_LONG ( zend_u_binary_strncasecmp ( s1 . u + start_offset , ( s1_len - start_offset ) , s2 . u , s2_len , cmp_len ) ) ;
}
2003-10-30 00:49:33 +00:00
} else {
2006-10-04 17:25:12 +00:00
if ( offset < 0 ) {
offset = s1_len + offset ;
offset = ( offset < 0 ) ? 0 : offset ;
}
2008-02-13 16:59:56 +00:00
if ( offset > = s1_len ) {
2007-06-18 13:39:02 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " The start position cannot exceed initial string length " ) ;
RETURN_FALSE ;
}
2007-10-01 13:41:57 +00:00
if ( len > s1_len - offset ) {
2008-02-13 16:59:56 +00:00
len = s1_len - offset ;
2006-10-04 17:25:12 +00:00
}
cmp_len = ( uint ) ( len ? len : MAX ( s2_len , ( s1_len - offset ) ) ) ;
if ( ! cs ) {
RETURN_LONG ( zend_binary_strncmp ( s1 . s + offset , ( s1_len - offset ) , s2 . s , s2_len , cmp_len ) ) ;
} else {
RETURN_LONG ( zend_binary_strncasecmp ( s1 . s + offset , ( s1_len - offset ) , s2 . s , s2_len , cmp_len ) ) ;
}
2003-10-30 00:49:33 +00:00
}
}
/* }}} */
2000-06-01 10:07:44 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 12:55:48 +00:00
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
2000-06-01 10:07:44 +00:00
*/