ます’s Blog - どうでもいい記事100選

どうでもいい記事100選

マルチバイト対応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)