strrpos関数とmb_strrpos関数の挙動の違い
詳しくはコレから始まるスレッドを参照して頂きたいのですが。
(PHP5では)mbstring.func_overloadでstrrpos関数をオーバーロードすると、(状況によっては)マヅイ事になりそうです。
ただでさえ海外の人からは不評な機能なのに(更に)拍車がかかりそう。
という訳で、逃げの一手。。。。のタコさんパッチ。
mb_strrpos関数の引数仕様をstrrpos関数の引数仕様に合わせてみました。
encoding引数は普段から使っていないので(個人的には)特に問題ナッシング。
--- php-5.1.2,orig/ext/mbstring/mbstring.c 2006-01-01 21:50:08.000000000 +0900 +++ php-5.1.2/ext/mbstring/mbstring.c 2006-02-27 11:17:53.000000000 +0900 @@ -1612,11 +1612,12 @@ } /* }}} */ -/* {{{ proto int mb_strrpos(string haystack, string needle [, string encoding]) +/* {{{ proto int mb_strrpos(string haystack, string needle [, int offset [, string encoding]]) Find the last occurrence of a character in a string within another */ PHP_FUNCTION(mb_strrpos) { int n; + long offset; mbfl_string haystack, needle; char *enc_name = NULL; int enc_name_len; @@ -1627,8 +1628,9 @@ haystack.no_encoding = MBSTRG(current_internal_encoding); needle.no_language = MBSTRG(current_language); needle.no_encoding = MBSTRG(current_internal_encoding); + offset = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &enc_name, &enc_name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &offset, &enc_name, &enc_name_len) == FAILURE) { RETURN_FALSE; } @@ -1648,7 +1650,17 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Empty needle"); RETURN_FALSE; } - n = mbfl_strpos(&haystack, &needle, 0, 1); + if (offset < 0) { + offset = haystack.len + offset; + if (offset < 0) { + RETURN_FALSE; + } + haystack.len = offset + needle.len; + offset = 0; + } else if (offset > haystack.len) { + RETURN_FALSE; + } + n = mbfl_strpos(&haystack, &needle, offset, 1); if (n >= 0) { RETVAL_LONG(n); } else {
うーん。offsetの負の指定は仕様が訳ワカメ。。。これ、本当に必要なのか?
気になるのが「if (offset > haystack.len)」の部分。
文字数として比較してなくて、バイト数として比較しています。
この比較は、mb_strpos関数(内部の処理)でも行なっていますが、これって本当は、
n = mbfl_strlen(&haystack); if (offset > n) { RETURN_FALSE; }
こんな感じで比較しないのと駄目なのかなぁ。。。という気がしています。
マルチバイト対応関数なんだから、offsetの意味合いもバイト数ではなくて文字数なのでは。。。って事です。
この辺が(いまいち)よく分かってないので、負の計算は適当です。
っていうか「mbstring.func_overload」はPHP3(i18n)互換モードとして「1」にしか設定してないから全然関係ないんだけどね。
bytelen関数が無さげなので(やはり)strlen関数は必要なんです。
メール送信にしても専用の関数を作ってるしなぁ。オリジナルのmail関数(mb_send_mail)関数は使いづらい。