官方手册中:

类似函数还有两个: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"

即:(unsigned char)c[i] <= ' ' && (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')

存在参数二时,会去除参数二中指定的字符。

其中函数 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()的更多相关文章

  1. map内置函数分析所得到的思路

    map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...

  2. php内置函数分析之array_diff_assoc()

    static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...

  3. php内置函数分析之array_combine()

    PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...

  4. php内置函数分析之ucwords()

    PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...

  5. php内置函数分析之strtoupper()、strtolower()

    strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...

  6. php内置函数分析之ucfirst()、lcfirst()

    ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...

  7. php内置函数分析之str_pad()

    PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...

  8. php内置函数分析之array_fill_keys()

    PHP_FUNCTION(array_fill_keys) { zval *keys, *val, *entry; if (zend_parse_parameters(ZEND_NUM_ARGS(), ...

  9. php内置函数分析range()

    PHP_FUNCTION(range) { zval *zlow, *zhigh, *zstep = NULL, tmp; , is_step_double = ; double step = 1.0 ...

随机推荐

  1. 笨办法学Python(learn python the hard way)--练习程序41

    下面是练习41,基于python3 #ex41.py 1 #打印文档字符串 print(函数名.__doc__) 2 from sys import exit 3 from random import ...

  2. Xcode磁盘空间清理

    http://www.iwangke.me/2013/09/09/clean-xcode-to-free-up-disk-space/#jtss-tsina 这个目录下面的文件也可以隔一段儿时间清理一 ...

  3. Unity各版本差异

    Unity各版本差异 version unity 5.x 4.x  2017 差异 特点  首先放出unity的下载地址,然后再慢慢分析各个版本.再者unity可以多个版本共存,只要不放在同一目录下. ...

  4. leetcode-mid-Linked list-328 Odd Even Linked List-NO

    mycode # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # sel ...

  5. python监控ip攻击,服务器防火墙

    '''写一个程序,监控nginx的日志,如果有人攻击就加入黑名单 把ip加入黑名单的策略是,1分钟之内,如果同一个ip请求超过200次,那就加入黑名单''' '''分析:1.打开文件 2.循环读取 3 ...

  6. 使用GOGS搭建自己的Git托管

    大家在开发中一般使用的git服务都是公司搭建好的,或者就是直接用gayhub提供的免费的仓库 如果想搭建一个自己的仓库的话怎么弄,这里给大家安利一款开箱即用的git托管服务:gogs. gogs是基于 ...

  7. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_09 序列化流_1_序列化和反序列化的概述

  8. Numpy 基础函数

    日后用的着的时候再说,存下来.方便日后查看 NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环).用数组表达式代替循环的做法,通常被称为矢量化. 原来一直不明白什么叫矢 ...

  9. PCB布线设计-模拟和数字布线的异同(转)

    工程领域中的数字设计人员和数字电路板设计专家在不断增加,这反映了行业的发展趋势.尽管对数字设计的重视带来了电子产品的重大发展,但仍然存在,而且还会一直存在一部分与模拟或现实环境接口的电路设计.模拟和数 ...

  10. 【GTS】关于GtsTetheringTestCases模块的几个失败项

    GTS---关于GtsTetheringTestCases模块的几个失败项 1.run gts -m GtsTetheringTestCases -t com.google.android.tethe ...