1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

[RFC] Add mb_ucfirst and mb_lcfirst functions (#13161)

This commit is contained in:
tekimen
2024-03-21 01:25:19 +09:00
committed by GitHub
parent 5430ecd3db
commit 4d51bfa270
6 changed files with 168 additions and 1 deletions

1
NEWS
View File

@@ -90,6 +90,7 @@ PHP NEWS
- MBString:
. Added mb_trim, mb_ltrim and mb_rtrim. (Yuya Hamada)
. Added mb_ucfirst and mb_lcfirst. (Yuya Hamada)
- MySQLnd:
. Fixed bug GH-13440 (PDO quote bottleneck). (nielsdos)

View File

@@ -431,6 +431,8 @@ PHP 8.4 UPGRADE NOTES
- 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

View File

@@ -2951,6 +2951,50 @@ PHP_FUNCTION(mb_strtolower)
RETURN_STR(mbstring_convert_case(PHP_UNICODE_CASE_LOWER, ZSTR_VAL(str), ZSTR_LEN(str), enc));
}
static void php_mb_ulcfirst(INTERNAL_FUNCTION_PARAMETERS, php_case_mode mode)
{
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();
}
zend_string *first = mb_get_substr(str, 0, 1, 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);
RETURN_STR(zend_string_copy(str));
}
zend_string *second = mb_get_substr(str, 1, MBFL_SUBSTR_UNTIL_END, enc);
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);
RETVAL_STR(retval);
}
PHP_FUNCTION(mb_ucfirst)
{
php_mb_ulcfirst(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_UNICODE_CASE_TITLE);
}
PHP_FUNCTION(mb_lcfirst)
{
php_mb_ulcfirst(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_UNICODE_CASE_LOWER);
}
typedef enum {
MB_LTRIM = 1,
MB_RTRIM = 2,

View File

@@ -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 {}

View File

@@ -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   …\"")
@@ -348,6 +352,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);
@@ -445,6 +451,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)

View File

@@ -0,0 +1,108 @@
--TEST--
mb_ucfirst(), mb_lcfirst functions tests
--EXTENSIONS--
mbstring
--FILE--
<?php
mb_internal_encoding("UTF-8");
function test_ascii_mb_ucfirst() {
for ($i = 0; $i < 128; $i++) {
if ($i >= 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(""));
var_dump(mb_ucfirst(""));
var_dump(mb_ucfirst("đắt quá!"));
var_dump(mb_ucfirst("აბგ"));
var_dump(mb_ucfirst("lj"));
echo "== mb_lcfirst ==\n";
var_dump(mb_lcfirst(""));
var_dump(mb_lcfirst("Xin chào"));
var_dump(mb_lcfirst("Đẹp quá!"));
echo "== SJIS ==\n";
var_dump(bin2hex(mb_ucfirst(mb_convert_encoding("", "SJIS", "UTF-8"), "SJIS")));
var_dump(bin2hex(mb_lcfirst(mb_convert_encoding("", "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));
?>
--EXPECT--
== Empty String ==
string(0) ""
string(0) ""
== ASCII ==
Done mb_ucfirst
Done mb_lcfirst
== mb_ucfirst ==
string(6) ""
string(9) ""
string(12) "Đắt quá!"
string(9) "აბგ"
string(2) "Lj"
== mb_lcfirst ==
string(9) ""
string(9) "xin chào"
string(12) "đẹp quá!"
== SJIS ==
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)