PHP源码阅读笔记一
一、explode和implode函数
array explode ( string separator, string string [, int limit] )
此函数返回由字符串组成的数组,每个元素都是 string 的一个子串,它们被字符串 separator 作为边界点分割出来。如果设置了 limit 参数,则返回的数组包含最多 limit 个元素,而最后那个元素将包含 string 的剩余部分。

此函数的时间复杂度应该是O(strlen(separator) * strlen(string))
其实现过程基本上是遍历字符串string,将它与separator比较,如果相同,则写入hash表,并将string的指针移到新的位置(即每一个separator的右边);

另外,对于limit小于0的情况有特殊处理
本函数实现主要是依赖于php_memnstr函数,在php.h文件中我们可以看到它的定义,
#define php_memnstr zend_memnstr
其真正的函数是zend_memnstr,在Zend/zend_operators.h文件的217行,可以看到它的定义,其实现主要是一个while循环和两个C语言的函数memchr和memcmp

php源代码如下:

PHP_FUNCTION(explode)
{
char *str, *delim;
int str_len = 0, delim_len = 0;
long limit = LONG_MAX; /* No limit */
zval zdelim, zstr;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &delim, &delim_len, &str, &str_len, &limit) == FAILURE) {
return;
}

if (delim_len == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
RETURN_FALSE;
}

array_init(return_value);

if (str_len == 0) {
if (limit >= 0) {
add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
}
return;
}

ZVAL_STRINGL(&zstr, str, str_len, 0);
ZVAL_STRINGL(&zdelim, delim, delim_len, 0);
if (limit > 1) {
php_explode(&zdelim, &zstr, return_value, limit);
} else if (limit < 0) {
php_explode_negative_limit(&zdelim, &zstr, return_value, limit);
} else {
add_index_stringl(return_value, 0, str, str_len, 1);
}
}

string implode ( string glue, array pieces )
此函数返回一个以glue字符串连接的pieces数组的各元素的字符串。
此函数可以是以一个数组为参数,可以是以一个数组和一个字符串为参数,并且字符串和数组的顺序可以改变,这些在程序中都有针对每种情况的特殊处理,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
              if (argc == 1) {
if (Z_TYPE_PP(arg1) != IS_ARRAY) { // 只有一个参数并且还不是数组
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument must be an array");
return;
}
 
MAKE_STD_ZVAL(delim);
#define _IMPL_EMPTY ""
ZVAL_STRINGL(delim, _IMPL_EMPTY, sizeof(_IMPL_EMPTY) - 1, 0);
 
SEPARATE_ZVAL(arg1);
arr = *arg1;
} else { // 两个参数
if (Z_TYPE_PP(arg1) == IS_ARRAY) { // 如果每一个参数是数组
arr = *arg1;
convert_to_string_ex(arg2);
delim = *arg2;
} else if (Z_TYPE_PP(arg2) == IS_ARRAY) { // 如果第二个参数是数组
arr = *arg2;
convert_to_string_ex(arg1);
delim = *arg1;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments passed");
return;
}
}

最后数组都会赋值给arr,分隔字符串赋值给delim,没有的置为””

就是一个遍历数组,并连接字符串的过程,只是这个过程中使用了smart_str相关函数(更多相关请移步 ),针对不同的类型作了不同的连接操作(如果是数字还需要将数字转化成字符串,这些在smart_str中都有相关函数处理)

本文地址:PHP源码阅读笔记一:explode和implode函数    文章出处:PHP源码阅读,PHP设计模式,PHP学习笔记,项目管理-胖胖的空间

转载请以链接形式注明原始出处和作者,谢绝不尊重版权者抄袭!

PHP源码阅读笔记一(explode和implode函数分析)的更多相关文章

  1. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

  2. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

  3. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  4. CI框架源码阅读笔记2 一切的入口 index.php

    上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...

  5. 源码阅读笔记 - 1 MSVC2015中的std::sort

    大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...

  6. Three.js源码阅读笔记-5

    Core::Ray 该类用来表示空间中的“射线”,主要用来进行碰撞检测. THREE.Ray = function ( origin, direction ) { this.origin = ( or ...

  7. AQS源码阅读笔记(一)

    AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node { //表示当前节点以共享模式等待锁 static final Node S ...

  8. libevent源码阅读笔记(一):libevent对epoll的封装

    title: libevent源码阅读笔记(一):libevent对epoll的封装 最近开始阅读网络库libevent的源码,阅读源码之前,大致看了张亮写的几篇博文(libevent源码深度剖析 h ...

  9. Mina源码阅读笔记(四)—Mina的连接IoConnector2

    接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...

随机推荐

  1. NSUInteger和NSInteger和int

    int和NSInteger其实是差不多的,但更推荐使用NSInteger,因为使用NSInteger,这样就不用考虑设备是32位还是64位了. NSUInteger是无符号的,即没有负数,NSInte ...

  2. Log4j配置具体解释

    #配置Logger #--log4j.rootLogger=[level], appenderName1, appenderName2, ... #level分为: # FATAL : 0 # ERR ...

  3. MySQL对于datetime 源码分析

    http://tsecer.blog.163.com/blog/static/150181720160117355684/   一.时间比较的语法分析 在mysql中,通常时间是一个必不可少的类型,而 ...

  4. 下载好一个android软件之后,怎样自动提示安装?

    最近在做毕设,里面牵涉到版本更新,当有新版本时可以下载新版本,下载完成之后提示安装.那么怎么实现下载完成之后提示安装呢? 直接上代码吧: File mFile = new File(Environme ...

  5. javascript笔记09:javascript的下拉式导航菜单

    <!DOCTYPE html> <html> <body> <script> function hideAll() { for(i=0;i<odi ...

  6. C#读取Exeal文件

    今天写一个读取Exeal的时候遇到一个问题就是引用了Mircosotf.Office.Interop.Exeal类库的时候没有办法读取到 纠结了好久百度了一下发现别人是这样写的using Exeal= ...

  7. iOS之应用内跳转系统设置相关界面

    在iOS开发中,有时会有跳转系统设置界面的需求,例如提示用户打开蓝牙或者WIFI,提醒用户打开推送或者位置权限等.在iOS6之后,第三方应用需要跳转系统设置界面,需要在URL type中添加一个pre ...

  8. docker image export or import

    docker save <image-name> docker load <  <bak>.tar

  9. 删除主目录下的.ssh目录下文件对boot2docker启动影响

    现象: 1) boot2docker ssh需要输入密码 2) boot2docker start 或 up 需要输入密码 解决方法: 1)删除 /Users/sunzhaoyu/.boot2dock ...

  10. 构建本地yum源之rpmbuild问题汇总

    - check-rpaths的问题 今天在编译varnish的时候,遇到几个问题,其中一个就是出现如下错误: ...+ /usr/lib/rpm/check-rpaths /usr/lib/rpm/c ...