📄 string.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | 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. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | | Stig S鎡her Bakken <ssb@fast.no> | | Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ *//* $Id: string.c,v 1.333.2.52.2.11 2007/03/26 10:28:28 tony2001 Exp $ *//* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */#include <stdio.h>#include "php.h"#include "reg.h"#include "php_rand.h"#include "php_string.h"#include "php_variables.h"#ifdef HAVE_LOCALE_H# include <locale.h>#endif#ifdef HAVE_LANGINFO_H# include <langinfo.h>#endif#ifdef HAVE_MONETARY_H# include <monetary.h>#endif#ifdef HAVE_LIBINTL# include <libintl.h> /* for LC_MESSAGES */#endif#include "scanf.h"#include "zend_API.h"#include "zend_execute.h"#include "php_globals.h"#include "basic_functions.h"#include "php_smart_str.h"#ifdef ZTS#include "TSRM.h"#endif#define STR_PAD_LEFT 0#define STR_PAD_RIGHT 1#define STR_PAD_BOTH 2#define PHP_PATHINFO_DIRNAME 1#define PHP_PATHINFO_BASENAME 2#define PHP_PATHINFO_EXTENSION 4#define PHP_PATHINFO_ALL (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION)#define STR_STRSPN 0#define STR_STRCSPN 1/* {{{ register_string_constants */void register_string_constants(INIT_FUNC_ARGS){ 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); REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);#ifdef HAVE_LOCALECONV /* If last members of struct lconv equal CHAR_MAX, no grouping is done */ /* 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#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);# ifdef LC_MESSAGES REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);# endif#endif }/* }}} */int php_tag_find(char *tag, int len, char *set);/* this is read-only, so it's ok */static char hexconvtab[] = "0123456789abcdef";/* localeconv mutex */#ifdef ZTSstatic MUTEX_T locale_mutex = NULL;#endif/* {{{ php_bin2hex */static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *newlen){ register unsigned char *result = NULL; size_t i, j; result = safe_emalloc(sizeof(char), oldlen * 2, 1); for (i = j = 0; i < oldlen; i++) { result[j++] = hexconvtab[old[i] >> 4]; result[j++] = hexconvtab[old[i] & 15]; } result[j] = '\0'; if (newlen) *newlen = oldlen * 2 * sizeof(char); return result;}/* }}} */#ifdef HAVE_LOCALECONV/* {{{ localeconv_r * glibc's localeconv is not reentrant, so lets make it so ... sorta */PHPAPI struct lconv *localeconv_r(struct lconv *out){ 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;}/* }}} */# ifdef ZTS/* {{{ PHP_MINIT_FUNCTION */PHP_MINIT_FUNCTION(localeconv){ locale_mutex = tsrm_mutex_alloc(); return SUCCESS;}/* }}} *//* {{{ PHP_MSHUTDOWN_FUNCTION */PHP_MSHUTDOWN_FUNCTION(localeconv){ tsrm_mutex_free( locale_mutex ); locale_mutex = NULL; return SUCCESS;}/* }}} */# endif#endif/* {{{ proto string bin2hex(string data) Converts the binary representation of data to hex */PHP_FUNCTION(bin2hex){ zval **data; char *result; size_t newlen; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &data) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(data); result = php_bin2hex(Z_STRVAL_PP(data), Z_STRLEN_PP(data), &newlen); if (!result) { RETURN_FALSE; } RETURN_STRINGL(result, newlen, 0);}/* }}} */static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior){ char *s11, *s22; int len1, len2; long start = 0, len = 0; unsigned char match[256] = {0}; char *rs, *s, *e; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &s11, &len1, &s22, &len2, &start, &len) == FAILURE) { return; } if (ZEND_NUM_ARGS() < 4) { len = len1; } /* look at substr() function for more information */ if (start < 0) { start += len1; if (start < 0) { start = 0; } } else if (start > len1) { RETURN_FALSE; } if (len < 0) { len += (len1 - start); if (len < 0) { len = 0; } } if (((unsigned) start + (unsigned) len) > len1) { len = len1 - start; } s = s22; e = s22 + len2; while (s < e) { match[(int)(unsigned char)*s++] = 1; } rs = s = s11 + start; e = s11 + start + len; while (s <= e && match[(int)(unsigned char)*s++] != behavior); RETURN_LONG((s - rs) < 1 ? 0 : s - rs - 1);}/* {{{ proto int strspn(string str, string mask [, start [, len]]) 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);}/* }}} *//* {{{ proto int strcspn(string str, string mask [, start [, len]]) 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) */PHP_FUNCTION(strcspn){ php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRCSPN);}/* }}} *//* {{{ PHP_MINIT_FUNCTION(nl_langinfo) */#if HAVE_NL_LANGINFOPHP_MINIT_FUNCTION(nl_langinfo){#define REGISTER_NL_LANGINFO_CONSTANT(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)#ifdef ABDAY_1 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);#endif#ifdef DAY_1 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);#endif#ifdef ABMON_1 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);#endif#ifdef MON_1 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);#endif#ifdef AM_STR REGISTER_NL_LANGINFO_CONSTANT(AM_STR);#endif#ifdef PM_STR REGISTER_NL_LANGINFO_CONSTANT(PM_STR);#endif#ifdef D_T_FMT REGISTER_NL_LANGINFO_CONSTANT(D_T_FMT);#endif#ifdef D_FMT REGISTER_NL_LANGINFO_CONSTANT(D_FMT);#endif#ifdef T_FMT REGISTER_NL_LANGINFO_CONSTANT(T_FMT);#endif#ifdef T_FMT_AMPM REGISTER_NL_LANGINFO_CONSTANT(T_FMT_AMPM);#endif#ifdef ERA REGISTER_NL_LANGINFO_CONSTANT(ERA);#endif#ifdef ERA_YEAR REGISTER_NL_LANGINFO_CONSTANT(ERA_YEAR);#endif#ifdef ERA_D_T_FMT REGISTER_NL_LANGINFO_CONSTANT(ERA_D_T_FMT);#endif#ifdef ERA_D_FMT REGISTER_NL_LANGINFO_CONSTANT(ERA_D_FMT);#endif#ifdef ERA_T_FMT REGISTER_NL_LANGINFO_CONSTANT(ERA_T_FMT);#endif#ifdef ALT_DIGITS REGISTER_NL_LANGINFO_CONSTANT(ALT_DIGITS);#endif#ifdef INT_CURR_SYMBOL REGISTER_NL_LANGINFO_CONSTANT(INT_CURR_SYMBOL);#endif#ifdef CURRENCY_SYMBOL REGISTER_NL_LANGINFO_CONSTANT(CURRENCY_SYMBOL);#endif#ifdef CRNCYSTR REGISTER_NL_LANGINFO_CONSTANT(CRNCYSTR);#endif#ifdef MON_DECIMAL_POINT REGISTER_NL_LANGINFO_CONSTANT(MON_DECIMAL_POINT);#endif#ifdef MON_THOUSANDS_SEP REGISTER_NL_LANGINFO_CONSTANT(MON_THOUSANDS_SEP);#endif#ifdef MON_GROUPING REGISTER_NL_LANGINFO_CONSTANT(MON_GROUPING);#endif#ifdef POSITIVE_SIGN REGISTER_NL_LANGINFO_CONSTANT(POSITIVE_SIGN);#endif#ifdef NEGATIVE_SIGN REGISTER_NL_LANGINFO_CONSTANT(NEGATIVE_SIGN);#endif#ifdef INT_FRAC_DIGITS REGISTER_NL_LANGINFO_CONSTANT(INT_FRAC_DIGITS);#endif#ifdef FRAC_DIGITS REGISTER_NL_LANGINFO_CONSTANT(FRAC_DIGITS);#endif#ifdef P_CS_PRECEDES REGISTER_NL_LANGINFO_CONSTANT(P_CS_PRECEDES);#endif#ifdef P_SEP_BY_SPACE REGISTER_NL_LANGINFO_CONSTANT(P_SEP_BY_SPACE);#endif#ifdef N_CS_PRECEDES REGISTER_NL_LANGINFO_CONSTANT(N_CS_PRECEDES);#endif#ifdef N_SEP_BY_SPACE REGISTER_NL_LANGINFO_CONSTANT(N_SEP_BY_SPACE);#endif#ifdef P_SIGN_POSN REGISTER_NL_LANGINFO_CONSTANT(P_SIGN_POSN);#endif#ifdef N_SIGN_POSN REGISTER_NL_LANGINFO_CONSTANT(N_SIGN_POSN);#endif#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#ifdef GROUPING REGISTER_NL_LANGINFO_CONSTANT(GROUPING);#endif#ifdef YESEXPR REGISTER_NL_LANGINFO_CONSTANT(YESEXPR);#endif#ifdef NOEXPR REGISTER_NL_LANGINFO_CONSTANT(NOEXPR);#endif#ifdef YESSTR REGISTER_NL_LANGINFO_CONSTANT(YESSTR);#endif#ifdef NOSTR REGISTER_NL_LANGINFO_CONSTANT(NOSTR);#endif#ifdef CODESET REGISTER_NL_LANGINFO_CONSTANT(CODESET);#endif#undef REGISTER_NL_LANGINFO_CONSTANT return SUCCESS;}/* }}} *//* {{{ proto string nl_langinfo(int item) Query language and locale information */PHP_FUNCTION(nl_langinfo){ zval **item; char *value; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &item) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(item); value = nl_langinfo(Z_LVAL_PP(item)); if (value == NULL) { RETURN_FALSE; } else { RETURN_STRING(value, 1); }}#endif/* }}} */#ifdef HAVE_STRCOLL/* {{{ proto int strcoll(string str1, string str2) Compares two strings using the current locale */PHP_FUNCTION(strcoll){ zval **s1, **s2; if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &s1, &s2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(s1); convert_to_string_ex(s2); RETURN_LONG(strcoll((const char *) Z_STRVAL_PP(s1), (const char *) Z_STRVAL_PP(s2)));}/* }}} */#endif/* {{{ php_charmask * Fills a 256-byte bytemask with input. You can specify a range like 'a..z', * it needs to be incrementing. * Returns: FAILURE/SUCCESS wether the input was correct (i.e. no range errors) */static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_DC){ unsigned char *end; unsigned char c; int result = SUCCESS; memset(mask, 0, 256); for (end = input+len; input < end; input++) { c=*input; if ((input+3 < end) && input[1] == '.' && input[2] == '.' && input[3] >= c) { memset(mask+c, 1, input[3] - c + 1); input+=3; } 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 was 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 { mask[c]=1; } } return result;}/* }}} *//* {{{ 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') */PHPAPI char *php_trim(char *c, int len, char *what, int what_len, zval *return_value, int mode TSRMLS_DC){ register int i; int trimmed = 0; char mask[256]; if (what) { php_charmask(what, what_len, mask TSRMLS_CC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -