PHP source code Explode use instructions _php tips

Source: Internet
Author: User
Tags explode php source code zend
When we need to divide an array by a character or string, explode is very happy, but do you know how ~explode works?
The first thing to be sure is that explode will also allocate space, no doubt.
Copy Code code as follows:

File 1:ext/standard/string.c
Let's take a look at explode's source.
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;
}
This will open up an array of data to store the split
Array_init (Return_value);
Because of this, we use explode (' | ', ') ' to be a legitimate
if (Str_len = = 0) {
if (limit >= 0) {
Add_next_index_stringl (Return_value, "", sizeof ("")-1, 1);
}
Return
}
The following two are constructs of the original string and the delimiter into the _zval_struct structure,
ZVAL_STRINGL will allocate space Oh ~ ~ Source code then posted
Zval_stringl (&zstr, str, str_len, 0);
Zval_stringl (&zdelim, Delim, Delim_len, 0);
The limit value is the third parameter of the explode that is allowed to be passed in explode, allowing positive and negative
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);
}
}

Copy Code code as follows:

Zval_stringl's source code:
File 2:zend/zend_api.c
#define ZVAL_STRINGL (z, S, l, duplicate) {\
const char *__s= (s); int __l=l; \
Z_strlen_p (z) = __l; \
Z_strval_p (z) = (duplicate?estrndup (__s, __l):(char*) __s); \
Z_type_p (z) = is_string; \
}
....
Estrndup is the main course:
File 3:zend/zend_alloc.h
#define ESTRNDUP (S, length) _estrndup ((s), (length) zend_file_line_cc zend_file_line_empty_cc)
....
Implementation of _estrndup: ZEND/ZEND_ALLOC.C
ZEND_API Char *_estrndup (const char *s, UINT length zend_file_line_dc zend_file_line_orig_dc)
{
Char *p;
p = (char *) _emalloc (length+1 zend_file_line_relay_cc zend_file_line_orig_relay_cc);
if (unexpected (p = = NULL)) {
return p;
}
memcpy (p, s, length); Allocate space
P[length] = 0;
return p;
}
In addition, the zval_string used in substr and STRRCHR Strstr is also the implementation of the appeal

The following is based on explode's third parameter limit to parse the call: The condition corresponds to the last three rows in the explode, and the limit conditions are different
Note: Limit at default (no delivery), his default is Long_max, which is part of branch 1
1, limit > 1:
Call the Php_explode method, which can also be used in the ext/standard/ Found in String.c, and is immediately above the explode implementation (so it is convenient to look up the method from this file in this function, and almost none of them are on top of the function immediately ^_^),
Copy Code code as follows:

Phpapi void Php_explode (Zval *delim, Zval *str, Zval *return_value, long limit)
{
Char *p1, *P2, *ENDP;
The pointer to the end position of the source string is obtained first
ENDP = z_strval_p (str) + z_strlen_p (str);
Record start position
P1 = z_strval_p (str);
Here's how to get the position of the delimiter in STR, which you can see in Strrpos and Strpos to locate
P2 = php_memnstr (z_strval_p (str), z_strval_p (Delim), Z_strlen_p (Delim), ENDP);
if (P2 = = NULL) {
Because of this, so when we call explode (' | ', ' abc '); it's legal, it's the array (0 => ' abc ').
Add_next_index_stringl (Return_value, p1, Z_strlen_p (str), 1);
} else {
Loop to get the next separator position until the end
do {
The substring to be obtained (the last position in the middle of the position, the first time the last position is the beginning)
Add_next_index_stringl (Return_value, p1, P2-P1, 1);
Position to the length of the p2+ separator at the separator position
For example, the delimiter = ' | ', the original string = ' Ab|c ', p2 = 2, then p1=2+1=3
P1 = p2 + z_strlen_p (delim);
while (P2 = Php_memnstr (P1, Z_strval_p (Delim), Z_strlen_p (Delim), ENDP))!= NULL &&
--limit > 1);
Place the string following the last delimiter in the result array
Explode (' | ', ' AVC|SDF '); => Array (0 => ' AVC ', 1= > ' SDF ')
if (P1 <= ENDP)
Add_next_index_stringl (Return_value, p1, ENDP-P1, 1);
}
}

2, limit < 0:
Calling the Php_explode_negative_limit method
Copy Code code as follows:

Phpapi void Php_explode_negative_limit (Zval *delim, Zval *str, Zval *return_value, long limit)
{
#define EXPLODE_ALLOC_STEP 64
Char *p1, *P2, *ENDP;
ENDP = z_strval_p (str) + z_strlen_p (str);
P1 = z_strval_p (str);
P2 = php_memnstr (z_strval_p (str), z_strval_p (Delim), Z_strlen_p (Delim), ENDP);
if (P2 = = NULL) {
It is not handled here, that explode (' | ', ' abc ',-1) becomes illegal, and cannot get any value.
/*
Do no since limit <=-1, thus if only one chunk-1 + (limit) <= 0
By doing no we return empty array
*/
} else {
int allocated = Explode_alloc_step, found = 0;
Long I, To_return;
Char **positions = emalloc (Allocated * sizeof (char *));
Notice the positions declaration here, this array is used to hold the read location of all substrings
positions[found++] = p1; Of course, the starting position still needs to be saved.
The following two loops, the first one is to loop all the separator positions that appear in the string and save the next substring read position
do {
If (found >= allocated) {
Allocated = found + explode_alloc_step;/* Make sure we have enough memory * *
positions = Erealloc (positions, allocated*sizeof (char *));
}
positions[found++] = P1 = p2 + z_strlen_p (delim);
while (P2 = Php_memnstr (P1, Z_strval_p (Delim), Z_strlen_p (Delim), ENDP))!= NULL);
This is starting from the array to get the results of the returned from which substring to read
To_return = limit + found;
/* limit is at least-1 therefore no need of bounds checking:i'll be always less than found * *
for (i = 0;i < to_return;i++) {/* This checks also for To_return > 0 * *
Add_next_index_stringl (Return_value, Positions[i],
(Positions[i+1]-z_strlen_p (Delim))-positions[i],
1
);
}
Efree (positions);//Very important, free memory
}
#undef Explode_alloc_step
}

3, limit = 1 or limit = 0:
When all the first and second conditions are not satisfied, in this branch, this branch is very simple to put the source string into the output array, explode (' | ', ' AVC|SD ', 1) or explode (' | ', ' AVC|SD ', 0) will return Array (0 = > ' AVC|SD ');
Copy Code code as follows:

Add_index_stringl Source Code
File 4:zend/zend_api.c
Zend_api int Add_next_index_stringl (zval *arg, const char *STR, UINT length, int duplicate)/* {{* * *
{
Zval *tmp;
Make_std_zval (TMP);
ZVAL_STRINGL (TMP, str, length, duplicate);
Return Zend_hash_next_index_insert (Z_arrval_p (ARG), &tmp, sizeof (Zval *), NULL);
}
Zend_hash_next_index_insert
Zend/zend_hash.h
#define ZEND_HASH_NEXT_INDEX_INSERT (HT, PData, ndatasize, pdest) \
_zend_hash_index_update_or_next_insert (HT, 0, PData, ndatasize, Pdest, Hash_next_insert zend_file_line_cc)
Zend/zend_hash.c
It's too long ~ ~ ~ ~ ~ ~ ~

Visible (does not contain allocation space for these),
When limit>1, the efficiency is O (n) "N is limit value",
When limit<0, the efficiency is O (n+m) "N is limit value, M is the number of separator occurrences",
When Limit=1 or limit=0, the efficiency is O (1)

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.