ホームページ > バックエンド開発 > PHPチュートリアル > PHP ソース コード爆発の使用説明_PHP チュートリアル

PHP ソース コード爆発の使用説明_PHP チュートリアル

WBOY
リリース: 2016-07-21 15:25:49
オリジナル
833 人が閲覧しました

特定の文字または文字列に基づいて配列を配列に分割する必要がある場合、explode は非常に便利に使用できますが、~explode の仕組みをご存知ですか~~
まず第一に、explode がスペースも割り当てることは確実です。間違いない。

コードをコピーします コードは次のとおりです:

//ファイル1: ext/standard/string.c
//最初にexplodeのソースコードを見てみましょう
PHP_FUNCTION(explode)
{
char *str, * delim;
int str_len = 0, delim_len = 0; /* 制限なし */
zval zdelim, zstr; l", &delim, &delim_len, &str, &str_len, &limit) == FAILURE) {
return;
}
if (delim_len == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "空の区切り文字");
RETURN_FALSE;
}
//ここで分割データを格納するための配列が開かれます
array_init(return_value);
//このため、explode('|', '') が有効になります
if (str_len == 0) {
if (limit >= 0) {
add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
}
}
//次の 2 つは両方の元の文字列から構築されます。と区切り文字を _zval_struct 構造体に追加すると、
//ZVAL_STRINGL がスペースを割り当てます~~ソースコードは後で投稿します
ZVAL_STRINGL(&zstr, str, str_len, 0); /limit 値は、explode で渡すことができるexplodeの3番目のパラメータで、正と負を許可します
if (limit > 1) {
php_explode(&zdelim, &zstr, return_value, limit); else if (limit); < 0) {
php_explode_negative_limit (&zdelim, &zstr, return_value, limit);
add_index_stringl(return_value, 0, str, str_len, 1);





コード

コードは次のとおりです:

// ZVAL_STRINGL のソース コード:
//ファイル 2: zend/zend_API.c
#define ZVAL_STRINGL(z, s, l, dedicated) { const char *__s=(s) ; int __l=l; Z_STRLEN_P(z) = __l; Z_STRVAL_P(z) = (重複?estrndup(__s, __l):(char*)__s); .. //estrndup がメインコースです:
//ファイル 3: zend/zend_alloc.h
#define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
....
/ /_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 = (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); // スペースを確保
p[length] = 0;
// , substr と strrchr strstr で使用される ZVAL_STRING も使用されます アピールの実装


以下は、explode の 3 番目のパラメータ制限に基づいて呼び出しを分析するものです: 条件は、explode の最後の 3 行に対応します。制限条件
注: 制限がデフォルトになっている (渡されていない) 場合、そのデフォルト値は LONG_MAX であり、これはブランチ 1 の場合です
1、limit > 1:
ext/standard にもある php_explode メソッドを呼び出します/string.c で、explode が表示されるすぐ上に実装されています (この関数でこのファイルからメソッドを検索するときに非常に便利です。ほとんどすべてのメソッドが関数のすぐ上にあります^_^)。



をコピーします。コード

コードは次のとおりです:

PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
{
char *p1, *p2, *endp;
//最初に取得するのは、 source string
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
//レコード開始位置
p1 = Z_STRVAL_P(str); 以下は str 内の区切り文字の位置を取得するものです。 strrpos と strpos にもあります。このメソッドは
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); を見つけるために使用されます。 、explore( '|', 'abc'); を呼び出すと、結果は array(0 => 'abc')
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1); になります。 else {
//次の区切り文字の位置を最後まで取得するシーケンスループ
do {
//取得される部分文字列(前の位置からこの位置までの中間部分、前の位置が初めて始まります
add_next_index_stringl(return_value, p1 , p2 - p1, 1);
//区切り文字の位置 p2 + 区切り文字の長さを見つけます
//たとえば、区切り文字 = '|'、元の文字列 = 'ab |c'、p2 = 2、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 > ;
//最後の区切り文字の後の文字列を結果の array
//explode('|', 'avc|sdf'); > 'avc' , 1= >



コードをコピーします

コードは次のとおりです:


PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, long limit)
{
# EXPLODE_ALLOC_STEP 64 を定義します
char *p1, *p2, * endp ;
p1 = Z_STRVAL_P(str);
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim); Z_STRLEN_P(delim), endp); if (p2 = = NULL) { //ここで処理されない場合、explore('|', 'abc', -1) は不正となり、値を取得できません/* limit <= -1 なので何もしません。したがって、チャンクが 1 つだけの場合 - 1 + (limit) <= 0
何もしないと空の配列が返されます
*/
} else {
int assign = EXPLODE_ALLOC_STEP, found = 0 ;
long i, to_return;
char * *positions = emalloc(allocated * sizeof(char *));
//この配列は、すべての部分文字列の読み取り位置を保存するために使用されます。 [found++] = p1; //もちろん、開始位置を保存する必要があります
//次の 2 つのループ、最初のループは、文字列内に出現するすべての区切り文字の位置をループし、次の部分文字列の読み取り位置を保存します
do {
if (found >=割り当てられました) {
allocated = found + EXPLODE_ALLOC_STEP;/* 十分なメモリがあることを確認します */
positions = erealloc(positions, allowed*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);返された結果は配列から取得されます 文字列の読み取りが開始されます
to_return = limit + found;
/* 限界は少なくとも -1 であるため、境界チェックの必要はありません : i は常に found より小さくなります */
for (i = 0) ;i < to_return;i++) { /* これは to_return > 0 もチェックします */
add_next_index_stringl(return_value, 位置[i],
(位置[i+1] - Z_STRLEN_P(delim)) - 位置[i] ,
1
);
}
efree(positions);//非常に重要です、メモリを解放します
}
#undef EXPLODE_ALLOC_STEP
}


3. 最初と 2 番目の条件がすべて満たされている場合満たされていない場合は、Return array(0 => 'avc|sd'); のこのブランチを入力します。



コードをコピー

コードは次のとおりです:


//add_index_stringl ソース コード
//ファイル 4: zend/zend_API.c
ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int dedicated) /* {{{ */
{
MAKE_STD_ZVAL(tmp);
ZVAL_STRINGL(tmp, str、長さ、重複);
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 ///長すぎます~~~~もう投稿しません
それはわかります(割り当てられたスペースを除く)、
limit>1の場合、効率はO(N) [Nは限界値]、
limitlimit=1 または limit=0 の場合、効率は O(1)

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/324052.html技術記事特定の文字または文字列に基づいて配列を配列に分割する必要がある場合、explode を使用すると非常に便利ですが、知っていますか~explode の仕組み~~ まず最初に、確信してください...
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート