マルチバイト対応strstr
無いのが昔から気になってました。
mb_strpos関数とmb_subtr関数を使ったチョイ関数作ってゴマかしてるんだけど。。。ね。
という訳でダメ駄目パッチ(その2)を作ってみた。切った張ったしてるだけなのが安っぽくてステキすぎ。
千里の道も一歩から〜♪という事で。Solaris8(sparc64bit)とRedHat Linix9(32bit)でしか確認してません。
今更mbstringを拡張する。。。ってのはサテオキ。mb_strrstr関数はオマケ。
--- php-4.4.0,orig/ext/mbstring/mbstring.h 2005-07-12 21:53:20.000000000 +0900 +++ php-4.4.0/ext/mbstring/mbstring.h 2005-07-12 21:53:20.000000000 +0900 @@ -102,6 +102,8 @@ PHP_FUNCTION(mb_strlen); PHP_FUNCTION(mb_strpos); PHP_FUNCTION(mb_strrpos); +PHP_FUNCTION(mb_strstr); +PHP_FUNCTION(mb_strrstr); PHP_FUNCTION(mb_substr_count); PHP_FUNCTION(mb_substr); PHP_FUNCTION(mb_strcut); --- php-4.4.0,orig/ext/mbstring/mbstring.c 2005-07-12 21:53:20.000000000 +0900 +++ php-4.4.0/ext/mbstring/mbstring.c 2005-07-12 21:53:20.000000000 +0900 @@ -186,6 +186,7 @@ {MB_OVERLOAD_STRING, "strlen", "mb_strlen", "mb_orig_strlen"}, {MB_OVERLOAD_STRING, "strpos", "mb_strpos", "mb_orig_strpos"}, {MB_OVERLOAD_STRING, "strrpos", "mb_strrpos", "mb_orig_strrpos"}, + {MB_OVERLOAD_STRING, "strstr", "mb_strstr", "mb_orig_strstr"}, {MB_OVERLOAD_STRING, "substr", "mb_substr", "mb_orig_substr"}, {MB_OVERLOAD_STRING, "strtolower", "mb_strtolower", "mb_orig_strtolower"}, {MB_OVERLOAD_STRING, "strtoupper", "mb_strtoupper", "mb_orig_strtoupper"}, @@ -237,6 +238,8 @@ PHP_FE(mb_strlen, NULL) PHP_FE(mb_strpos, NULL) PHP_FE(mb_strrpos, NULL) + PHP_FE(mb_strstr, NULL) + PHP_FE(mb_strrstr, NULL) PHP_FE(mb_substr_count, NULL) PHP_FE(mb_substr, NULL) PHP_FE(mb_strcut, NULL) @@ -2270,6 +2273,164 @@ } /* }}} */ +/* {{{ proto string mb_strstr(string haystack, string needle [, int offset [, string encoding]]) + Find position of first occurrence of a string within another */ +PHP_FUNCTION(mb_strstr) +{ + pval **arg1, **arg2, **arg3, **arg4; + int offset, n, reverse = 0, len, mblen; + mbfl_string haystack, needle, result, *ret = NULL; + + mbfl_string_init(&haystack); + mbfl_string_init(&needle); + haystack.no_language = MBSTRG(current_language); + haystack.no_encoding = MBSTRG(current_internal_encoding); + needle.no_language = MBSTRG(current_language); + needle.no_encoding = MBSTRG(current_internal_encoding); + offset = 0; + switch (ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(arg3); + offset = Z_LVAL_PP(arg3); + break; + case 4: + if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(arg3); + offset = Z_LVAL_PP(arg3); + convert_to_string_ex(arg4); + haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4)); + if (haystack.no_encoding == mbfl_no_encoding_invalid) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg4)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + convert_to_string_ex(arg2); + + if (offset < 0 || offset > Z_STRLEN_PP(arg1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is out of range"); + RETURN_FALSE; + } + if (Z_STRLEN_PP(arg2) == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty needle"); + RETURN_FALSE; + } + haystack.val = (unsigned char *)Z_STRVAL_PP(arg1); + haystack.len = Z_STRLEN_PP(arg1); + needle.val = Z_STRVAL_PP(arg2); + needle.len = Z_STRLEN_PP(arg2); + + n = mbfl_strpos(&haystack, &needle, offset, reverse); + if (n >= 0) { + mblen = mbfl_strlen(&haystack); + len = (mblen - n); + ret = mbfl_substr(&haystack, &result, n, len); + if (ret != NULL) { + RETVAL_STRINGL((char *)ret->val, ret->len, 0); + } else { + RETVAL_FALSE; + } + } else { + switch (-n) { + case 1: + break; + case 2: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Needle has not positive length."); + break; + case 4: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding or conversion error."); + break; + case 8: + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is empty."); + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error in mb_strstr."); + break; + } + RETVAL_FALSE; + } +} +/* }}} */ + +/* {{{ proto string mb_strrstr(string haystack, string needle [, string encoding]) + Find the last occurrence of a character in a string within another */ +PHP_FUNCTION(mb_strrstr) +{ + pval **arg1, **arg2, **arg3; + int n, len, mblen; + mbfl_string haystack, needle, result, *ret = NULL; + + mbfl_string_init(&haystack); + mbfl_string_init(&needle); + haystack.no_language = MBSTRG(current_language); + haystack.no_encoding = MBSTRG(current_internal_encoding); + needle.no_language = MBSTRG(current_language); + needle.no_encoding = MBSTRG(current_internal_encoding); + switch (ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg3); + haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg3)); + if (haystack.no_encoding == mbfl_no_encoding_invalid) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg3)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + convert_to_string_ex(arg2); + if (Z_STRLEN_PP(arg1) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty haystack"); + RETURN_FALSE; + } + if (Z_STRLEN_PP(arg2) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Empty needle"); + RETURN_FALSE; + } + haystack.val = (unsigned char *)Z_STRVAL_PP(arg1); + haystack.len = Z_STRLEN_PP(arg1); + needle.val = (unsigned char *)Z_STRVAL_PP(arg2); + needle.len = Z_STRLEN_PP(arg2); + n = mbfl_strpos(&haystack, &needle, 0, 1); + if (n >= 0) { + mblen = mbfl_strlen(&haystack); + len = (mblen - n); + ret = mbfl_substr(&haystack, &result, n, len); + if (ret != NULL) { + RETVAL_STRINGL((char *)ret->val, ret->len, 0); + } else { + RETVAL_FALSE; + } + } else { + RETVAL_FALSE; + } +} +/* }}} */ + /* {{{ proto int mb_substr_count(string haystack, string needle [, string encoding]) Count the number of substring occurrences */ PHP_FUNCTION(mb_substr_count)