Explode Analysis of PHP source code

Source: Internet
Author: User

Introduction: This is a detailed page of explode Analysis of PHP source code. It introduces PHP, related knowledge, skills, experience, and some PHP source code.

Class = 'pingjiaf' frameborder = '0' src = 'HTTP: // biancheng.dnbc?info/pingjia.php? Id = 342850 'rolling = 'no'>

Recently, I have been thinking about the efficiency of string operations. The interception of strings will not avoid the consumption of Space re-allocation. I also read the source code of the explode function, take out your own analysis and share it with ^_^.

When we need to split an array into arrays based on a character or string, explode is very happy, but you know ~ How does explode work ~~

First of all, it is certain that explode will also allocate space, without a doubt.

1 // file 1: EXT/standard/string. c
2 // first, let's look at Source code
3 php_function (explode)
4 {
5 char * STR, * delim;
6 int str_len = 0, delim_len = 0;
7 long limit = long_max;/* No limit */
8 zval zdelim, zstr;
9
10 if (zend_parse_parameters (zend_num_args () tsrmls_cc, "SS | L", & delim, & delim_len, & STR, & str_len, & limit) = failure ){
11 return;
12}
13
14 if (delim_len = 0 ){
15 php_error_docref (null tsrmls_cc, e_warning, "EMPTY delimiter ");
16 return_false;
17}
18
19 // an array is opened to store the split data.
20 array_init (return_value );
21
22 // because of this, we use explode ('| ', '');
23 if (str_len = 0 ){
24 if (Limit> = 0 ){
25 add_next_index_stringl (return_value, "", sizeof ("")-1, 1 );
26}
27 return;
28}
29
30 // The following two construct the _ zval_struct structure for both the original string and delimiter,
31 // zval_stringl will allocate space ~~ Source Code Post
32 zval_stringl (& zstr, STR, str_len, 0 );
33 zval_stringl (& zdelim, delim, delim_len, 0 );
34 // The limit value is the third parameter of the explode that can be passed in explode, which allows positive and negative
35 if (Limit> 1 ){
36 php_explode (& zdelim, & zstr, return_value, limit );
37} else if (Limit <0 ){
38 php_explode_negative_limit (& zdelim, & zstr, return_value, limit );
39} else {
40 add_index_stringl (return_value, 0, STR, str_len, 1 );
41}
42}
1 // source code of zval_stringl:
2 // file 2: Zend/zend_api.c
3 # define zval_stringl (z, S, L, duplicate ){\
4 const char * _ S = (s); int _ L = L ;\
5 z_strlen_p (z) = _ L ;\
6 z_strval_p (z) = (duplicate? Estrndup (_ s, _ L) :( char *) _ s );\
7 z_type_p (z) = is_string ;\
8}
9 ....
10 // estrndup is the main course:
11 // file 3: Zend/zend_alloc.h
12 # define estrndup (S, length) _ estrndup (s), (length) zend_file_line_cc zend_file_line_empty_cc)
13 ....
14 // _ Implementation of estrndup: Zend/zend_alloc.c
15 zend_api char * _ estrndup (const char * s, uint length zend_file_line_dc zend_file_line_orig_dc)
16 {
17 char * P;
18 P = (char *) _ emalloc (Length + 1 zend_file_line_relay_cc zend_file_line_orig_relay_cc );
19 if (unexpected (P = NULL )){
20 return P;
21}
22 memcpy (P, S, length); // allocate space
23 p [length] = 0;
24 return P;
25}
26 // In addition, zval_string used in substr and strrchr strstr also uses the implementation of appeal.

The following is called based on the third parameter limit of explode: The condition corresponds to the last three rows in explode, and the limit condition is different.

Note: The default value of limit is long_max, which belongs to branch 1.

1. Limit> 1:

Call the php_explode method, which can also be in ext/standard/string. found in C, and appears immediately after the explode implementation (so it is very convenient to call methods from this file in the search function, almost none of the columns are on the top of the function. ^_^ ),

1 phpapi void php_explode (zval * delim, zval * STR, zval * return_value, long limit)
2 {
3 char * P1, * P2, * endp;
4 // obtain the pointer at the end of the source string.
5 endp = z_strval_p (STR) + z_strlen_p (STR );
6 // record start position
7 p1 = z_strval_p (STR );
8 // The following figure shows the position of the delimiter in str. We can see that this method is also used to locate the delimiter in strrpos and strpos.
9 P2 = php_memnstr (z_strval_p (STR), z_strval_p (delim), z_strlen_p (delim), endp );
10
11 if (P2 = NULL ){
12 // because of this, when we call explode ('|', 'abc'); it is legal, and the output is array (0 => 'abc ')
13 add_next_index_stringl (return_value, P1, z_strlen_p (STR), 1 );
14} else {
15 // cyclically obtain the location of the next separator until the end
16 do {
17 // obtain the sub-string (from the last position to the middle of this position, the first time the last position is the start
18 add_next_index_stringl (return_value, P1, P2-P1, 1 );
19 // locate the separator position p2 + the length of the separator
20 // For example, separator = '|', original string = 'AB | C', P2 = 2, then p1 = 2 + 1 = 3
21 p1 = P2 + z_strlen_p (delim );
22} while (P2 = php_memnstr (P1, z_strval_p (delim), z_strlen_p (delim), endp ))! = NULL &&
23 -- limit> 1 );
24 // put the string following the last separator into the result Array
25 // explode ('|', 'avc | SDF '); => array (0 => 'avc', 1 => 'sdf ')
26 if (P1 <= endp)
27 add_next_index_stringl (return_value, P1, endp-p1, 1 );
28}
29}

2. Limit <0:

Call the php_explode_negative_limit Method

1 phpapi void php_explode_negative_limit (zval * delim, zval * STR, zval * return_value, long limit)
2 {
3 # define explode_alloc_step 64
4 char * P1, * P2, * endp;
5
6 endp = z_strval_p (STR) + z_strlen_p (STR );
7
8 p1 = z_strval_p (STR );
9 P2 = php_memnstr (z_strval_p (STR), z_strval_p (delim), z_strlen_p (delim), endp );
10
11 if (P2 = NULL ){
12 // It is not processed here, So explode ('|', 'abc',-1) becomes invalid and no value can be obtained.
13 /*
14 do nothing since limit <=-1, thus if only one chunk-1 + (Limit) <= 0
15 by doing nothing we return empty array
16 */
17} else {
18 int allocated = explode_alloc_step, found = 0;
19 long I, to_return;
20 char ** positions = emalloc (allocated * sizeof (char *));
21 // note the positions declaration here. This array is used to save the reading position of all sub-strings.
22 positions [found ++] = p1; // Of course, the start position still needs to be saved
23 // The following two loops. The first one is to loop all the separators that appear in the string, and save the reading position of the next substring.
24 do {
25 if (found> = allocated ){
26 allocated = found + explode_alloc_step;/* Make sure we have enough memory */
27 positions = erealloc (positions, allocated * sizeof (char *));
28}
29 positions [found ++] = p1 = P2 + z_strlen_p (delim );
30} while (P2 = php_memnstr (P1, z_strval_p (delim), z_strlen_p (delim), endp ))! = NULL );
31 // This is the substring from which the returned results will be read from the array.
32 to_return = Limit + found;
33/* limit is at least-1 therefore no need of bounds checking: I will be always less than found */
34 For (I = 0; I <to_return; I ++) {/* This checks also for to_return> 0 */
35 add_next_index_stringl (return_value, positions [I],
36 (positions [I + 1]-z_strlen_p (delim)-positions [I],
37 1
38 );
39}
40 efree (positions); // very important, release the memory
41}
42 # UNDEF explode_alloc_step
43}

3. Limit = 1 or limit = 0:

When all the first and second conditions are not met, the Branch is entered. This branch is very easy to put the source string in the output array.,Explode ('|', 'avc | sd', 1) or explode ('|', 'avc | sd', 0) will return array (0 => 'avc | sd ');


1 // add_index_stringl source code
2 // file 4: Zend/zend_api.c
3 zend_api int add_next_index_stringl (zval * Arg, const char * STR, uint length, int duplicate )/*{{{*/
4 {
5 zval * TMP;
6
7 make_std_zval (TMP );
8 zval_stringl (TMP, STR, length, duplicate );
9
10 return zend_hash_next_index_insert (z_arrval_p (ARG), & TMP, sizeof (zval *), null );
11}
12
13 // zend_hash_next_index_insert
14 // Zend/zend_hash.h
15 # define zend_hash_next_index_insert (HT, pdata, ndatasize, pdest )\
16 _ zend_hash_index_update_or_next_insert (HT, 0, pdata, ndatasize, pdest, hash_next_insert zend_file_line_cc)
17 // Zend/zend_hash.c
18 // It's too long ~~~~ No more

Visible (excluding allocated space ),

When the limit value is greater than 1, the efficiency is O (n) [n is the limit value ],

When limit is <0, the efficiency is O (n + M) [n is the limit value, M is the number of times the delimiter appears ],

When limit = 1 or limit = 0, the efficiency is O (1)

Love J2EE follow Java Michael Jackson video station JSON online tools

Http://biancheng.dnbcw.info/php/342850.html pageno: 6.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.