From 959f9f52466d3968e4b9bb4ae8e05d292abc7bb4 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Tue, 16 Jan 2024 11:58:15 +0900 Subject: [PATCH 01/15] Add mb_ucfirst and mb_lcfirst functions --- ext/mbstring/mbstring.c | 66 ++++++++++++++++++++++ ext/mbstring/mbstring.stub.php | 4 ++ ext/mbstring/mbstring_arginfo.h | 10 +++- ext/mbstring/tests/mb_ucfirst_lcfirst.phpt | 31 ++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 ext/mbstring/tests/mb_ucfirst_lcfirst.phpt diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index ac48f8ad32f59..5b1c5e3861408 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2953,6 +2953,72 @@ PHP_FUNCTION(mb_strtolower) RETURN_STR(mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(str), ZSTR_LEN(str), enc)); } +static zend_string* php_mb_ucfirst(zend_string *str, const mbfl_encoding *enc) +{ + zend_string *first, *second, *head; + first = mb_get_substr(str, 0, 1, enc); + second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); + head = mbstring_convert_case(PHP_UNICODE_CASE_UPPER, ZSTR_VAL(first), ZSTR_LEN(first), enc); + zend_string_release(first); + + zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); + zend_string_release(head); + zend_string_release(second); + + return retval; +} + +PHP_FUNCTION(mb_ucfirst) +{ + zend_string *str, *from_encoding = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(str) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(from_encoding) + ZEND_PARSE_PARAMETERS_END(); + + const mbfl_encoding *enc = php_mb_get_encoding(from_encoding, 2); + if (!enc) { + RETURN_THROWS(); + } + + RETVAL_STR(php_mb_ucfirst(str, enc)); +} + +static zend_string* php_mb_lcfirst(zend_string *str, const mbfl_encoding *enc) +{ + zend_string *first, *second, *head; + first = mb_get_substr(str, 0, 1, enc); + second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); + head = mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(first), ZSTR_LEN(first), enc); + zend_string_release(first); + + zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); + zend_string_release(head); + zend_string_release(second); + + return retval; +} + +PHP_FUNCTION(mb_lcfirst) +{ + zend_string *str, *from_encoding = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(str) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(from_encoding) + ZEND_PARSE_PARAMETERS_END(); + + const mbfl_encoding *enc = php_mb_get_encoding(from_encoding, 2); + if (!enc) { + RETURN_THROWS(); + } + + RETVAL_STR(php_mb_lcfirst(str, enc)); +} + typedef enum { MB_LTRIM = 1, MB_RTRIM = 2, diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php index dc9fa907ce059..6eb041bf1eba2 100644 --- a/ext/mbstring/mbstring.stub.php +++ b/ext/mbstring/mbstring.stub.php @@ -135,6 +135,10 @@ function mb_strtoupper(string $string, ?string $encoding = null): string {} /** @refcount 1 */ function mb_strtolower(string $string, ?string $encoding = null): string {} +function mb_ucfirst(string $string, ?string $encoding = null): string {} + +function mb_lcfirst(string $string, ?string $encoding = null): string {} + function mb_trim(string $string, string $characters = " \f\n\r\t\v\x00\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}", ?string $encoding = null): string {} function mb_ltrim(string $string, string $characters = " \f\n\r\t\v\x00\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}", ?string $encoding = null): string {} diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h index 3c3f1bf242907..be3aacf78f35d 100644 --- a/ext/mbstring/mbstring_arginfo.h +++ b/ext/mbstring/mbstring_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0fe7418224f3a0ab65a06bf215ebcb09ce632488 */ + * Stub hash: ea642b9010bc38a3b13710662fef48663d4385e1 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_language, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, language, IS_STRING, 1, "null") @@ -118,6 +118,10 @@ ZEND_END_ARG_INFO() #define arginfo_mb_strtolower arginfo_mb_strtoupper +#define arginfo_mb_ucfirst arginfo_mb_strtoupper + +#define arginfo_mb_lcfirst arginfo_mb_strtoupper + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mb_trim, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, characters, IS_STRING, 0, "\" \\f\\n\\r\\t\\v\\x00             

   …᠎\"") @@ -349,6 +353,8 @@ ZEND_FUNCTION(mb_convert_encoding); ZEND_FUNCTION(mb_convert_case); ZEND_FUNCTION(mb_strtoupper); ZEND_FUNCTION(mb_strtolower); +ZEND_FUNCTION(mb_ucfirst); +ZEND_FUNCTION(mb_lcfirst); ZEND_FUNCTION(mb_trim); ZEND_FUNCTION(mb_ltrim); ZEND_FUNCTION(mb_rtrim); @@ -447,6 +453,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(mb_convert_case, arginfo_mb_convert_case) ZEND_FE(mb_strtoupper, arginfo_mb_strtoupper) ZEND_FE(mb_strtolower, arginfo_mb_strtolower) + ZEND_FE(mb_ucfirst, arginfo_mb_ucfirst) + ZEND_FE(mb_lcfirst, arginfo_mb_lcfirst) ZEND_FE(mb_trim, arginfo_mb_trim) ZEND_FE(mb_ltrim, arginfo_mb_ltrim) ZEND_FE(mb_rtrim, arginfo_mb_rtrim) diff --git a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt new file mode 100644 index 0000000000000..629b37aa32349 --- /dev/null +++ b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt @@ -0,0 +1,31 @@ +--TEST-- +mb_ucfirst(), mb_lcfirst functions tests +--EXTENSIONS-- +mbstring +--FILE-- + +--EXPECT-- +== Empty String == +string(0) "" +string(0) "" +== mb_ucfirst == +string(6) "Ab" +string(9) "ABS" +string(12) "Đắt quá!" +== mb_lcfirst == +string(9) "aBS" +string(9) "xin chào" +string(12) "đẹp quá!" From d10721caa94603a8c0aa9ce94555a68cfcce25f2 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Wed, 17 Jan 2024 16:45:40 +0900 Subject: [PATCH 02/15] merge functions --- ext/mbstring/mbstring.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 5b1c5e3861408..3d87ca8b8dcf6 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2953,12 +2953,12 @@ PHP_FUNCTION(mb_strtolower) RETURN_STR(mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(str), ZSTR_LEN(str), enc)); } -static zend_string* php_mb_ucfirst(zend_string *str, const mbfl_encoding *enc) +static zend_string* php_mb_ulcfirst(zend_string *str, php_case_mode mode, const mbfl_encoding *enc) { zend_string *first, *second, *head; first = mb_get_substr(str, 0, 1, enc); second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); - head = mbstring_convert_case(PHP_UNICODE_CASE_UPPER, ZSTR_VAL(first), ZSTR_LEN(first), enc); + head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); zend_string_release(first); zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); @@ -2983,22 +2983,7 @@ PHP_FUNCTION(mb_ucfirst) RETURN_THROWS(); } - RETVAL_STR(php_mb_ucfirst(str, enc)); -} - -static zend_string* php_mb_lcfirst(zend_string *str, const mbfl_encoding *enc) -{ - zend_string *first, *second, *head; - first = mb_get_substr(str, 0, 1, enc); - second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); - head = mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(first), ZSTR_LEN(first), enc); - zend_string_release(first); - - zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); - zend_string_release(head); - zend_string_release(second); - - return retval; + RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_UPPER, enc)); } PHP_FUNCTION(mb_lcfirst) @@ -3016,7 +3001,7 @@ PHP_FUNCTION(mb_lcfirst) RETURN_THROWS(); } - RETVAL_STR(php_mb_lcfirst(str, enc)); + RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_LOWER, enc)); } typedef enum { From 09a3f9b2d4c1b9ee6c0b1ccf45d3098b5c415159 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Wed, 17 Jan 2024 16:47:53 +0900 Subject: [PATCH 03/15] Change from zend_string_release to zend_string_release_ex --- ext/mbstring/mbstring.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 3d87ca8b8dcf6..af1ec1742c2b5 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2959,11 +2959,11 @@ static zend_string* php_mb_ulcfirst(zend_string *str, php_case_mode mode, const first = mb_get_substr(str, 0, 1, enc); second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); - zend_string_release(first); + zend_string_release_ex(first, false); zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); - zend_string_release(head); - zend_string_release(second); + zend_string_release_ex(head, false); + zend_string_release_ex(second, false); return retval; } From 55d7de5f0e9c713c7b3737ab464c27f426185ec9 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Fri, 2 Feb 2024 21:08:59 +0900 Subject: [PATCH 04/15] Fix mb_ucfirst from MB_CASE_UPPER to MB_CASE_TITLE --- ext/mbstring/mbstring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index af1ec1742c2b5..57c06b48ade6a 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2983,7 +2983,7 @@ PHP_FUNCTION(mb_ucfirst) RETURN_THROWS(); } - RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_UPPER, enc)); + RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_TITLE, enc)); } PHP_FUNCTION(mb_lcfirst) From 861209f0c8c61374a3c0d4712f1fd3f5df2c7e8d Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 8 Feb 2024 16:59:37 +0900 Subject: [PATCH 05/15] Add test case to Georgian word to mb_ucfirst --- ext/mbstring/tests/mb_ucfirst_lcfirst.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt index 629b37aa32349..54e178fb1c8da 100644 --- a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt +++ b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt @@ -12,6 +12,8 @@ echo "== mb_ucfirst ==\n"; var_dump(mb_ucfirst("ab")); var_dump(mb_ucfirst("ABS")); var_dump(mb_ucfirst("đắt quá!")); +var_dump(mb_ucfirst("აბგ")); +var_dump(mb_ucfirst("lj")); echo "== mb_lcfirst ==\n"; var_dump(mb_lcfirst("ABS")); var_dump(mb_lcfirst("Xin chào")); @@ -25,6 +27,8 @@ string(0) "" string(6) "Ab" string(9) "ABS" string(12) "Đắt quá!" +string(9) "აბგ" +string(2) "Lj" == mb_lcfirst == string(9) "aBS" string(9) "xin chào" From 555eb203f641d73ca119930afa0facbe34993325 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 7 Mar 2024 10:58:08 +0900 Subject: [PATCH 06/15] Add NEWS and UPGRADING --- NEWS | 1 + UPGRADING | 2 ++ 2 files changed, 3 insertions(+) diff --git a/NEWS b/NEWS index a403e6a6a48db..fa64b9842ec34 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,7 @@ Intl: MBString: . Added mb_trim, mb_ltrim and mb_rtrim. (Yuya Hamada) + . Added mb_ucfirst and mb_lcfirst. (Yuya Hamada) Opcache: . Added large shared segments support for FreeBSD. (David Carlier) diff --git a/UPGRADING b/UPGRADING index a9e6df8919bef..df9240d69ce4d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -331,6 +331,8 @@ PDO_SQLITE: - MBString: . Added mb_trim, mb_ltrim and mb_rtrim functions. RFC: https://wiki.php.net/rfc/mb_trim + . Added mb_ucfirst and mb_lcfirst functions. + RFC: https://wiki.php.net/rfc/mb_ucfirst - Opcache: . If JIT is enabled, PHP will now exit with a fatal error on startup in case From 8a007f038d4104661a17855645dfac0c3723a7b1 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Fri, 8 Mar 2024 05:39:51 +0900 Subject: [PATCH 07/15] Refactor php_mb_ulcfirst --- ext/mbstring/mbstring.c | 48 +++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 57c06b48ade6a..ce1f89aa026a8 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2953,22 +2953,7 @@ PHP_FUNCTION(mb_strtolower) RETURN_STR(mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(str), ZSTR_LEN(str), enc)); } -static zend_string* php_mb_ulcfirst(zend_string *str, php_case_mode mode, const mbfl_encoding *enc) -{ - zend_string *first, *second, *head; - first = mb_get_substr(str, 0, 1, enc); - second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); - head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); - zend_string_release_ex(first, false); - - zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); - zend_string_release_ex(head, false); - zend_string_release_ex(second, false); - - return retval; -} - -PHP_FUNCTION(mb_ucfirst) +static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) { zend_string *str, *from_encoding = NULL; @@ -2983,25 +2968,26 @@ PHP_FUNCTION(mb_ucfirst) RETURN_THROWS(); } - RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_TITLE, enc)); -} + zend_string *first = mb_get_substr(str, 0, 1, enc); + zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); + zend_string *head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); + zend_string_release_ex(first, false); -PHP_FUNCTION(mb_lcfirst) -{ - zend_string *str, *from_encoding = NULL; + zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); + zend_string_release_ex(head, false); + zend_string_release_ex(second, false); - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(str) - Z_PARAM_OPTIONAL - Z_PARAM_STR_OR_NULL(from_encoding) - ZEND_PARSE_PARAMETERS_END(); + RETVAL_STR(retval); +} - const mbfl_encoding *enc = php_mb_get_encoding(from_encoding, 2); - if (!enc) { - RETURN_THROWS(); - } +PHP_FUNCTION(mb_ucfirst) +{ + php_mb_ulcfirst(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_UNICODE_CASE_TITLE); +} - RETVAL_STR(php_mb_ulcfirst(str, PHP_UNICODE_CASE_LOWER, enc)); +PHP_FUNCTION(mb_lcfirst) +{ + php_mb_ulcfirst(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_UNICODE_CASE_LOWER); } typedef enum { From 778657102be48293e61437cd8f56284973740794 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Fri, 8 Mar 2024 05:58:40 +0900 Subject: [PATCH 08/15] If is not need convert, use zend_string_copy. --- ext/mbstring/mbstring.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index ce1f89aa026a8..4721c3a18733b 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2973,6 +2973,10 @@ static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) zend_string *head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); zend_string_release_ex(first, false); + if (zend_string_equals(first, head)) { + RETVAL_STR(zend_string_copy(str)); + } + zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); zend_string_release_ex(head, false); zend_string_release_ex(second, false); From 31c662015ae8d74e6fd8f379f2fb7ca79c0f8b9b Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 7 Mar 2024 21:39:48 +0000 Subject: [PATCH 09/15] Fix zend_string_release --- ext/mbstring/mbstring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 4721c3a18733b..8889b1e86c769 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2971,12 +2971,12 @@ static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) zend_string *first = mb_get_substr(str, 0, 1, enc); zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); zend_string *head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); - zend_string_release_ex(first, false); if (zend_string_equals(first, head)) { RETVAL_STR(zend_string_copy(str)); } + zend_string_release_ex(first, false); zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); zend_string_release_ex(head, false); zend_string_release_ex(second, false); From 4472ef166e906d0b816f4627c18330e7c9284d2a Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 7 Mar 2024 22:20:56 +0000 Subject: [PATCH 10/15] Fix RETURN_STR instead of RETVAL_STR --- ext/mbstring/mbstring.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 8889b1e86c769..d35a4542fa04b 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2973,7 +2973,10 @@ static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) zend_string *head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); if (zend_string_equals(first, head)) { - RETVAL_STR(zend_string_copy(str)); + zend_string_release_ex(first, false); + zend_string_release_ex(head, false); + zend_string_release_ex(second, false); + RETURN_STR(zend_string_copy(str)); } zend_string_release_ex(first, false); From e6cc1e24f71642742efc38b74bb8e028ffc5c13a Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 7 Mar 2024 22:30:14 +0000 Subject: [PATCH 11/15] Improve and optimize variable second move after if statement --- ext/mbstring/mbstring.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index d35a4542fa04b..62682883b5aea 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2969,16 +2969,15 @@ static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) } zend_string *first = mb_get_substr(str, 0, 1, enc); - zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); zend_string *head = mbstring_convert_case(mode, ZSTR_VAL(first), ZSTR_LEN(first), enc); if (zend_string_equals(first, head)) { zend_string_release_ex(first, false); zend_string_release_ex(head, false); - zend_string_release_ex(second, false); RETURN_STR(zend_string_copy(str)); } + zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); zend_string_release_ex(first, false); zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); zend_string_release_ex(head, false); From aa58c7fa1801f2a8f1ac47d6f2f9009fc15bedad Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Fri, 8 Mar 2024 01:39:04 +0000 Subject: [PATCH 12/15] fix a nit --- ext/mbstring/mbstring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 62682883b5aea..fcce0ca670b97 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2978,8 +2978,9 @@ static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode) } zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc); - zend_string_release_ex(first, false); zend_string *retval = zend_string_concat2(ZSTR_VAL(head), ZSTR_LEN(head), ZSTR_VAL(second), ZSTR_LEN(second)); + + zend_string_release_ex(first, false); zend_string_release_ex(head, false); zend_string_release_ex(second, false); From c55d7b2d1fec4a2dc190e8f6aa2cacac27cdd175 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 14 Mar 2024 09:55:23 +0900 Subject: [PATCH 13/15] Add test case for ASCII and SJIS (other encoding) --- ext/mbstring/tests/mb_ucfirst_lcfirst.phpt | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt index 54e178fb1c8da..342c218f2f4f5 100644 --- a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt +++ b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt @@ -5,9 +5,45 @@ mbstring --FILE-- = 97 && $i <= 122) { /* a to z */ + if (mb_ucfirst(chr($i)) !== chr($i - (97 - 65))) { + echo "mb_ucfirst compare failed: " . chr($i) . "\n"; + } + } else { + if (mb_ucfirst(chr($i)) !== chr($i)) { + echo "mb_ucfirst compare failed: " . chr($i) . "\n"; + } + } + } + echo "Done mb_ucfirst\n"; +} + +function test_ascii_mb_lcfirst() { + for ($i = 0; $i < 128; $i++) { + if ($i >= 65 && $i <= 90) { /* A to Z */ + if (mb_lcfirst(chr($i)) !== chr($i + (97 - 65))) { + echo "mb_lcfirst compare failed: " . chr($i) . "\n"; + return; + } + } else { + if (mb_lcfirst(chr($i)) !== chr($i)) { + echo "mb_lcfirst compare failed: " . chr($i) . "\n"; + return; + } + } + } + echo "Done mb_lcfirst\n"; +} + echo "== Empty String ==\n"; var_dump(mb_ucfirst("")); var_dump(mb_lcfirst("")); +echo "== ASCII ==\n"; +test_ascii_mb_ucfirst(); +test_ascii_mb_lcfirst(); echo "== mb_ucfirst ==\n"; var_dump(mb_ucfirst("ab")); var_dump(mb_ucfirst("ABS")); @@ -18,11 +54,19 @@ echo "== mb_lcfirst ==\n"; var_dump(mb_lcfirst("ABS")); var_dump(mb_lcfirst("Xin chào")); var_dump(mb_lcfirst("Đẹp quá!")); +echo "== SJIS ==\n"; +var_dump(bin2hex(mb_ucfirst(mb_convert_encoding("ebi", "SJIS", "UTF-8"), "SJIS"))); +var_dump(bin2hex(mb_lcfirst(mb_convert_encoding("EBI", "SJIS", "UTF-8"), "SJIS"))); +var_dump(bin2hex(mb_ucfirst(hex2bin("8471"), "SJIS"))); /* б */ +var_dump(bin2hex(mb_lcfirst(hex2bin("8441"), "SJIS"))); /* Б */ ?> --EXPECT-- == Empty String == string(0) "" string(0) "" +== ASCII == +Done mb_ucfirst +Done mb_lcfirst == mb_ucfirst == string(6) "Ab" string(9) "ABS" @@ -33,3 +77,8 @@ string(2) "Lj" string(9) "aBS" string(9) "xin chào" string(12) "đẹp quá!" +== SJIS == +string(12) "826482828289" +string(12) "828582618268" +string(4) "8441" +string(4) "8471" From 216e104bef70f4e664d5f85e6c79be130a1915ce Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Thu, 14 Mar 2024 10:00:51 +0900 Subject: [PATCH 14/15] Add test case for longer strings --- ext/mbstring/tests/mb_ucfirst_lcfirst.phpt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt index 342c218f2f4f5..12a0a539747b9 100644 --- a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt +++ b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt @@ -59,6 +59,9 @@ var_dump(bin2hex(mb_ucfirst(mb_convert_encoding("ebi", "SJIS", "UTF-8"), " var_dump(bin2hex(mb_lcfirst(mb_convert_encoding("EBI", "SJIS", "UTF-8"), "SJIS"))); var_dump(bin2hex(mb_ucfirst(hex2bin("8471"), "SJIS"))); /* б */ var_dump(bin2hex(mb_lcfirst(hex2bin("8441"), "SJIS"))); /* Б */ +echo "== Longer strings ==\n"; +var_dump(mb_ucfirst("э" . str_repeat("A", 65536)) === "Э" . str_repeat("A", 65536)); +var_dump(mb_lcfirst("Э" . str_repeat("A", 65536)) === "э" . str_repeat("A", 65536)); ?> --EXPECT-- == Empty String == @@ -82,3 +85,6 @@ string(12) "826482828289" string(12) "828582618268" string(4) "8441" string(4) "8471" +== Longer strings == +bool(true) +bool(true) From 723196910f4500518aa060e64dd89f9f453dc468 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Sun, 17 Mar 2024 13:59:05 +0000 Subject: [PATCH 15/15] Add test case for EUC-JP --- ext/mbstring/tests/mb_ucfirst_lcfirst.phpt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt index 12a0a539747b9..d133d03270f8c 100644 --- a/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt +++ b/ext/mbstring/tests/mb_ucfirst_lcfirst.phpt @@ -59,6 +59,15 @@ var_dump(bin2hex(mb_ucfirst(mb_convert_encoding("ebi", "SJIS", "UTF-8"), " var_dump(bin2hex(mb_lcfirst(mb_convert_encoding("EBI", "SJIS", "UTF-8"), "SJIS"))); var_dump(bin2hex(mb_ucfirst(hex2bin("8471"), "SJIS"))); /* б */ var_dump(bin2hex(mb_lcfirst(hex2bin("8441"), "SJIS"))); /* Б */ +var_dump(bin2hex(mb_ucfirst(hex2bin("83bf"), "SJIS"))); /* α */ +var_dump(bin2hex(mb_lcfirst(hex2bin("839f"), "SJIS"))); /* Α */ +var_dump(bin2hex(mb_lcfirst(hex2bin("82a0"), "SJIS"))); /* あ */ +var_dump(bin2hex(mb_ucfirst(hex2bin("83bf8471"), "SJIS"))); +var_dump(bin2hex(mb_lcfirst(hex2bin("839f8441"), "SJIS"))); +echo "== EUC-JP ==\n"; +var_dump(bin2hex(mb_ucfirst(hex2bin("a6d8"), "EUC-JP"))); /* Ω */ +var_dump(bin2hex(mb_lcfirst(hex2bin("a6b8"), "EUC-JP"))); /* ω */ +var_dump(bin2hex(mb_ucfirst(hex2bin("a4a2a4a2"), "EUC-JP"))); /* あ */ echo "== Longer strings ==\n"; var_dump(mb_ucfirst("э" . str_repeat("A", 65536)) === "Э" . str_repeat("A", 65536)); var_dump(mb_lcfirst("Э" . str_repeat("A", 65536)) === "э" . str_repeat("A", 65536)); @@ -85,6 +94,15 @@ string(12) "826482828289" string(12) "828582618268" string(4) "8441" string(4) "8471" +string(4) "839f" +string(4) "83bf" +string(4) "82a0" +string(8) "839f8471" +string(8) "83bf8441" +== EUC-JP == +string(4) "a6b8" +string(4) "a6d8" +string(8) "a4a2a4a2" == Longer strings == bool(true) bool(true)