php内置函数分析之trim()
官方手册中:

类似函数还有两个:ltrim() 和 rtrim()。分别处理字符串的左侧、右侧。
trim()的具体实现位于:ext/standard/string.c
/* {{{ proto string trim(string str [, string character_mask])
Strips whitespace from the beginning and end of a string */
PHP_FUNCTION(trim)
{
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, );
}
/* }}} */
/* {{{ php_do_trim
* Base for trim(), rtrim() and ltrim() functions.
*/
static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
zend_string *str;
zend_string *what = NULL;
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_STR(str)
Z_PARAM_OPTIONAL
Z_PARAM_STR(what)
ZEND_PARSE_PARAMETERS_END();
ZVAL_STR(return_value, php_trim(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : ), mode));
}
/* }}} */
具体实现:
/* {{{ 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 zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)
{
const char *c = ZSTR_VAL(str);
size_t len = ZSTR_LEN(str);
register size_t i;
size_t trimmed = ;
char mask[];
if (what) {
if (what_len == ) {
char p = *what;
if (mode & ) {
for (i = ; i < len; i++) {
if (c[i] == p) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & ) {
if (len > ) {
i = len - ;
do {
if (c[i] == p) {
len--;
} else {
break;
}
} while (i-- != );
}
}
} else {
php_charmask((unsigned char*)what, what_len, mask);
if (mode & ) {
for (i = ; i < len; i++) {
if (mask[(unsigned char)c[i]]) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & ) {
if (len > ) {
i = len - ;
do {
if (mask[(unsigned char)c[i]]) {
len--;
} else {
break;
}
} while (i-- != );
}
}
}
} else {
if (mode & ) {
for (i = ; i < len; i++) {
if ((unsigned char)c[i] <= ' ' &&
(c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & ) {
if (len > ) {
i = len - ;
do {
if ((unsigned char)c[i] <= ' ' &&
(c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
len--;
} else {
break;
}
} while (i-- != );
}
}
}
if (ZSTR_LEN(str) == len) {
return zend_string_copy(str);
} else {
return zend_string_init(c, len, );
}
}
/* }}} */
ltrim()、rtrim() 或 trim()的参数二(what)存在时进入15行处的分支,参数二不存在时进入68行处的分支。
没有参数二时,会去除空格、"\t"、"\n"、"\r"、"\0"、"\v"
存在参数二时,会去除参数二中指定的字符。
其中函数 php_charmask() 用于处理 trim("abc123456fjsklsf", "a..z") 中 字符范围 a...z
static inline int php_charmask(unsigned char *input, size_t len, char *mask)
{
unsigned char *end;
unsigned char c;
int result = SUCCESS; memset(mask, , );
for (end = input+len; input < end; input++) {
c=*input;
if ((input+ < end) && input[] == '.' && input[] == '.'
&& input[] >= c) {
memset(mask+c, , input[] - c + );
input+=;
} else if ((input+ < end) && input[] == '.' && input[] == '.') {
/* 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, E_WARNING, "Invalid '..'-range, no character to the left of '..'");
result = FAILURE;
continue;
}
if (input+ >= end) { /* there is no 'right' char */
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'");
result = FAILURE;
continue;
}
if (input[-] > input[]) { /* wrong order */
php_error_docref(NULL, 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, E_WARNING, "Invalid '..'-range");
result = FAILURE;
continue;
} else {
mask[c]=;
}
}
return result;
}
第二个参数是字符范围的时候,源码中并没有严格限制成 a..z 这样的格式。
总的流程就是,待处理的字符串左侧(或右侧)逐字符去匹配是否在将要去除的字符中(第二个参数设置的字符 或者 默认的那6个字符),
如果字符匹配到则进行下一个比较,否则中断匹配查找。返回余下字符串。
php内置函数分析之trim()的更多相关文章
- map内置函数分析所得到的思路
map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...
- php内置函数分析之array_diff_assoc()
static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...
- php内置函数分析之array_combine()
PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...
- php内置函数分析之ucwords()
PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...
- php内置函数分析之strtoupper()、strtolower()
strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...
- php内置函数分析之ucfirst()、lcfirst()
ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...
- php内置函数分析之str_pad()
PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...
- php内置函数分析之array_fill_keys()
PHP_FUNCTION(array_fill_keys) { zval *keys, *val, *entry; if (zend_parse_parameters(ZEND_NUM_ARGS(), ...
- php内置函数分析range()
PHP_FUNCTION(range) { zval *zlow, *zhigh, *zstep = NULL, tmp; , is_step_double = ; double step = 1.0 ...
随机推荐
- 后端PHP框架laravel学习踩的各种坑
安装完laravel的ventor目录后出现“Whoops, looks like something went wrong.”这样的错误信息 打开config/app.php,打开debug为tru ...
- 《SQL Server 2012 T-SQL基础》读书笔记 - 2.单表查询
Chapter 2 Single-Table Queries GROUP BY之后的阶段的操作对象就是组(可以把一组想象成很多行组成的)了,HAVING负责过滤掉一些组.分组后的COUNT(*)表示每 ...
- C++返回栈上的数组(局部变量)问题探索
char* teststr() { char s[] = "hello"; return s; } void main() { char* str = teststr(); ]; ...
- 架构-数据库访问-SQL语言进行连接数据库服务器-OLE:OLE
ylbtech-架构-数据库访问-SQL语言进行连接数据库服务器-OLE:OLE Object Linking and Embedding,对象连接与嵌入,简称OLE技术.OLE 不仅是桌面应用程序集 ...
- FutureTask的用法以及两种常用的使用场景
参考博客:https://blog.csdn.net/linchunquan/article/details/22382487 FutureTask可用于异步获取执行结果或取消执行任务的场景.通过传入 ...
- 修改JAVA_HOME失效
在修改JDK的安装目录的情况下会出现失效的时候,因为jdk在安装的时候自己在path中添加了 C:\ProgramData\Oracle\Java\javapath 这个路径. 解决: 删除 path ...
- ecshop 实现“精品、新品、热销”板块出现选项卡效果的方法
最近做一个网络商城,直接使用ecshop的免费模板,懒得重新做,ecshop建站多日了,一直想在主页的板块中建网页选项卡鼠标经过自动切换效果,百度搜索这方面的内容也没找到合适的,今天一实验,成功了,所 ...
- 查询SQL Server数据库所有表字段备注
SELECT 表名 = case when a.colorder=1 then d.name else '' end, 表说明 = case when a.colorder=1 then isnull ...
- 100 IncDec序列
IncDec序列 Description 给定一个长度为 n 的数列 a1,a2,-,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一. 求至少需要多少次操作才能使数列中 ...
- 应用安全-Web安全-XSS(跨站攻击)攻防整理
分类 反射型 存储型 DOM型 XSF(Flash XSS) PDFXSS MHTML协议跨站(MHTML,data) 字符编码(UTF-7 XSS) 富文本编辑器测试 - 输入框 <img S ...