Make strtolower() and strtoupper() do ASCII case conversion (#7506)

Implement RFC https://wiki.php.net/rfc/strtolower-ascii
This commit is contained in:
Tim Starling 2021-12-16 00:38:35 +11:00 committed by GitHub
parent faa143ca1b
commit 8eee0d6130
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 319 additions and 866 deletions

View File

@ -19,6 +19,14 @@ PHP 8.2 UPGRADE NOTES
1. Backward Incompatible Changes 1. Backward Incompatible Changes
======================================== ========================================
- Standard:
. strtolower() and strtoupper() are no longer locale-sensitive. They now
perform ASCII case conversion, as if the locale were "C". Use
mb_strtolower() if you want localized case conversion. Similarly, stristr,
stripos, strripos, lcfirst, ucfirst, ucwords, str_ireplace,
array_change_key_case and sorting with SORT_FLAG_CASE use ASCII case
conversion.
======================================== ========================================
2. New Features 2. New Features
======================================== ========================================

View File

@ -9,17 +9,30 @@ LC_CTYPE=de_DE
--FILE-- --FILE--
<?php <?php
var_dump(setlocale(LC_CTYPE, "0")); echo "inherited\n";
var_dump(bin2hex(strtoupper("\xe4"))); echo 'ctype_lower(\xe4): ' . (ctype_lower("\xe4") ? 'y' : 'n') . "\n";
echo 'preg_match(\w, \xe4): ';
var_dump(preg_match('/\w/', "\xe4")); var_dump(preg_match('/\w/', "\xe4"));
var_dump(setlocale(LC_CTYPE, "0"));
echo 'ctype_lower(\xe4): ' . (ctype_lower("\xe4") ? 'y' : 'n') . "\n";
echo 'preg_match(\w, \xe4): ';
var_dump(preg_match('/\w/', "\xe4"));
echo "de_DE\n";
var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false); var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false);
var_dump(bin2hex(strtoupper("\xe4"))); echo 'ctype_lower(\xe4): ' . (ctype_lower("\xe4") ? 'y' : 'n') . "\n";
echo 'preg_match(\w, \xe4): ';
var_dump(preg_match('/\w/', "\xe4")); var_dump(preg_match('/\w/', "\xe4"));
?> ?>
--EXPECTF-- --EXPECTF--
inherited
ctype_lower(\xe4): n
preg_match(\w, \xe4): int(0)
string(%d) "C%r(\.UTF-8)?%r" string(%d) "C%r(\.UTF-8)?%r"
string(2) "e4" ctype_lower(\xe4): n
int(0) preg_match(\w, \xe4): int(0)
de_DE
bool(true) bool(true)
string(2) "c4" ctype_lower(\xe4): y
int(1) preg_match(\w, \xe4): int(1)

View File

@ -126,9 +126,9 @@ ZEND_API const unsigned char zend_toupper_map[256] = {
* Functions using locale lowercase: * Functions using locale lowercase:
zend_binary_strncasecmp_l zend_binary_strncasecmp_l
zend_binary_strcasecmp_l zend_binary_strcasecmp_l
* Functions using ascii lowercase:
string_compare_function_ex string_compare_function_ex
string_case_compare_function string_case_compare_function
* Functions using ascii lowercase:
zend_str_tolower_copy zend_str_tolower_copy
zend_str_tolower_dup zend_str_tolower_dup
zend_str_tolower zend_str_tolower
@ -1997,7 +1997,7 @@ ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool
int ret; int ret;
if (case_insensitive) { if (case_insensitive) {
ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1)); ret = zend_binary_strcasecmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
} else { } else {
ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2)); ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
} }
@ -2037,13 +2037,13 @@ ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /*
if (Z_STR_P(op1) == Z_STR_P(op2)) { if (Z_STR_P(op1) == Z_STR_P(op2)) {
return 0; return 0;
} else { } else {
return zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); return zend_binary_strcasecmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
} }
} else { } else {
zend_string *tmp_str1, *tmp_str2; zend_string *tmp_str1, *tmp_str2;
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1); zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2); zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
int ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1)); int ret = zend_binary_strcasecmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
zend_tmp_string_release(tmp_str1); zend_tmp_string_release(tmp_str1);
zend_tmp_string_release(tmp_str2); zend_tmp_string_release(tmp_str2);

View File

@ -21,7 +21,6 @@
#include "php.h" #include "php.h"
#include "php_ini.h" #include "php_ini.h"
#include "ext/standard/php_string.h"
#include "ext/standard/info.h" #include "ext/standard/info.h"
#include "pdo/php_pdo.h" #include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h" #include "pdo/php_pdo_driver.h"

View File

@ -1346,16 +1346,7 @@ return_false:
/* {{{ php_strtoupper */ /* {{{ php_strtoupper */
PHPAPI char *php_strtoupper(char *s, size_t len) PHPAPI char *php_strtoupper(char *s, size_t len)
{ {
unsigned char *c; zend_str_toupper(s, len);
const unsigned char *e;
c = (unsigned char *)s;
e = (unsigned char *)c+len;
while (c < e) {
*c = toupper(*c);
c++;
}
return s; return s;
} }
/* }}} */ /* }}} */
@ -1363,35 +1354,7 @@ PHPAPI char *php_strtoupper(char *s, size_t len)
/* {{{ php_string_toupper */ /* {{{ php_string_toupper */
PHPAPI zend_string *php_string_toupper(zend_string *s) PHPAPI zend_string *php_string_toupper(zend_string *s)
{ {
unsigned char *c; return zend_string_toupper(s);
const unsigned char *e;
if (EXPECTED(!BG(ctype_string))) {
return zend_string_toupper(s);
}
c = (unsigned char *)ZSTR_VAL(s);
e = c + ZSTR_LEN(s);
while (c < e) {
if (islower(*c)) {
unsigned char *r;
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
if (c != (unsigned char*)ZSTR_VAL(s)) {
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
}
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
while (c < e) {
*r = toupper(*c);
r++;
c++;
}
*r = '\0';
return res;
}
c++;
}
return zend_string_copy(s);
} }
/* }}} */ /* }}} */
@ -1404,23 +1367,14 @@ PHP_FUNCTION(strtoupper)
Z_PARAM_STR(arg) Z_PARAM_STR(arg)
ZEND_PARSE_PARAMETERS_END(); ZEND_PARSE_PARAMETERS_END();
RETURN_STR(php_string_toupper(arg)); RETURN_STR(zend_string_toupper(arg));
} }
/* }}} */ /* }}} */
/* {{{ php_strtolower */ /* {{{ php_strtolower */
PHPAPI char *php_strtolower(char *s, size_t len) PHPAPI char *php_strtolower(char *s, size_t len)
{ {
unsigned char *c; zend_str_tolower(s, len);
const unsigned char *e;
c = (unsigned char *)s;
e = c+len;
while (c < e) {
*c = tolower(*c);
c++;
}
return s; return s;
} }
/* }}} */ /* }}} */
@ -1428,32 +1382,7 @@ PHPAPI char *php_strtolower(char *s, size_t len)
/* {{{ php_string_tolower */ /* {{{ php_string_tolower */
PHPAPI zend_string *php_string_tolower(zend_string *s) PHPAPI zend_string *php_string_tolower(zend_string *s)
{ {
if (EXPECTED(!BG(ctype_string))) { return zend_string_tolower(s);
return zend_string_tolower(s);
}
unsigned char *c = (unsigned char *)ZSTR_VAL(s);
const unsigned char *e = c + ZSTR_LEN(s);
while (c < e) {
if (isupper(*c)) {
unsigned char *r;
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
if (c != (unsigned char*)ZSTR_VAL(s)) {
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
}
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
while (c < e) {
*r = tolower(*c);
r++;
c++;
}
*r = '\0';
return res;
}
c++;
}
return zend_string_copy(s);
} }
/* }}} */ /* }}} */
@ -1466,7 +1395,7 @@ PHP_FUNCTION(strtolower)
Z_PARAM_STR(str) Z_PARAM_STR(str)
ZEND_PARSE_PARAMETERS_END(); ZEND_PARSE_PARAMETERS_END();
RETURN_STR(php_string_tolower(str)); RETURN_STR(zend_string_tolower(str));
} }
/* }}} */ /* }}} */
@ -1758,8 +1687,8 @@ PHP_FUNCTION(pathinfo)
case insensitive strstr */ case insensitive strstr */
PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len) PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
{ {
php_strtolower(s, s_len); zend_str_tolower(s, s_len);
php_strtolower(t, t_len); zend_str_tolower(t, t_len);
return (char*)php_memnstr(s, t, t_len, s + s_len); return (char*)php_memnstr(s, t, t_len, s + s_len);
} }
/* }}} */ /* }}} */
@ -1982,8 +1911,8 @@ PHP_FUNCTION(stripos)
RETURN_FALSE; RETURN_FALSE;
} }
haystack_dup = php_string_tolower(haystack); haystack_dup = zend_string_tolower(haystack);
needle_dup = php_string_tolower(needle); needle_dup = zend_string_tolower(needle);
found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
@ -2077,10 +2006,9 @@ PHP_FUNCTION(strripos)
} }
e = ZSTR_VAL(haystack) + (ZSTR_LEN(haystack) + (size_t)offset); e = ZSTR_VAL(haystack) + (ZSTR_LEN(haystack) + (size_t)offset);
} }
/* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */ lowered = zend_tolower_ascii(*ZSTR_VAL(needle));
lowered = tolower(*ZSTR_VAL(needle));
while (e >= p) { while (e >= p) {
if (tolower(*e) == lowered) { if (zend_tolower_ascii(*e) == lowered) {
RETURN_LONG(e - p + (offset > 0 ? offset : 0)); RETURN_LONG(e - p + (offset > 0 ? offset : 0));
} }
e--; e--;
@ -2088,7 +2016,7 @@ PHP_FUNCTION(strripos)
RETURN_FALSE; RETURN_FALSE;
} }
haystack_dup = php_string_tolower(haystack); haystack_dup = zend_string_tolower(haystack);
if (offset >= 0) { if (offset >= 0) {
if ((size_t)offset > ZSTR_LEN(haystack)) { if ((size_t)offset > ZSTR_LEN(haystack)) {
zend_string_release_ex(haystack_dup, 0); zend_string_release_ex(haystack_dup, 0);
@ -2112,7 +2040,7 @@ PHP_FUNCTION(strripos)
} }
} }
needle_dup = php_string_tolower(needle); needle_dup = zend_string_tolower(needle);
if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) { if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) {
RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
zend_string_release_ex(needle_dup, 0); zend_string_release_ex(needle_dup, 0);
@ -2647,7 +2575,7 @@ PHP_FUNCTION(chr)
static zend_string* php_ucfirst(zend_string *str) static zend_string* php_ucfirst(zend_string *str)
{ {
const unsigned char ch = ZSTR_VAL(str)[0]; const unsigned char ch = ZSTR_VAL(str)[0];
unsigned char r = toupper(ch); unsigned char r = zend_toupper_ascii(ch);
if (r == ch) { if (r == ch) {
return zend_string_copy(str); return zend_string_copy(str);
} else { } else {
@ -2679,7 +2607,7 @@ PHP_FUNCTION(ucfirst)
Lowercase the first character of the word in a native string */ Lowercase the first character of the word in a native string */
static zend_string* php_lcfirst(zend_string *str) static zend_string* php_lcfirst(zend_string *str)
{ {
unsigned char r = tolower(ZSTR_VAL(str)[0]); unsigned char r = zend_tolower_ascii(ZSTR_VAL(str)[0]);
if (r == ZSTR_VAL(str)[0]) { if (r == ZSTR_VAL(str)[0]) {
return zend_string_copy(str); return zend_string_copy(str);
} else { } else {
@ -2732,10 +2660,10 @@ PHP_FUNCTION(ucwords)
ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str)); ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
r = Z_STRVAL_P(return_value); r = Z_STRVAL_P(return_value);
*r = toupper((unsigned char) *r); *r = zend_toupper_ascii((unsigned char) *r);
for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) { for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
if (mask[(unsigned char)*r++]) { if (mask[(unsigned char)*r++]) {
*r = toupper((unsigned char) *r); *r = zend_toupper_ascii((unsigned char) *r);
} }
} }
} }
@ -3067,11 +2995,11 @@ static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, si
if (case_sensitivity) { if (case_sensitivity) {
char_count = count_chars(ZSTR_VAL(str), ZSTR_LEN(str), from); char_count = count_chars(ZSTR_VAL(str), ZSTR_LEN(str), from);
} else { } else {
lc_from = tolower(from);
char_count = 0; char_count = 0;
lc_from = zend_tolower_ascii(from);
source_end = ZSTR_VAL(str) + ZSTR_LEN(str); source_end = ZSTR_VAL(str) + ZSTR_LEN(str);
for (source = ZSTR_VAL(str); source < source_end; source++) { for (source = ZSTR_VAL(str); source < source_end; source++) {
if (tolower(*source) == lc_from) { if (zend_tolower_ascii(*source) == lc_from) {
char_count++; char_count++;
} }
} }
@ -3111,7 +3039,7 @@ static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, si
} else { } else {
source_end = ZSTR_VAL(str) + ZSTR_LEN(str); source_end = ZSTR_VAL(str) + ZSTR_LEN(str);
for (source = ZSTR_VAL(str); source < source_end; source++) { for (source = ZSTR_VAL(str); source < source_end; source++) {
if (tolower(*source) == lc_from) { if (zend_tolower_ascii(*source) == lc_from) {
memcpy(target, to, to_len); memcpy(target, to, to_len);
target += to_len; target += to_len;
} else { } else {
@ -4345,7 +4273,7 @@ static zend_long php_str_replace_in_subject(
zend_long old_replace_count = replace_count; zend_long old_replace_count = replace_count;
if (!lc_subject_str) { if (!lc_subject_str) {
lc_subject_str = php_string_tolower(subject_str); lc_subject_str = zend_string_tolower(subject_str);
} }
tmp_result = php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str), tmp_result = php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
search_str, replace_value, replace_len, &replace_count); search_str, replace_value, replace_len, &replace_count);
@ -4398,7 +4326,7 @@ static zend_long php_str_replace_in_subject(
ZSTR_VAL(search_str), ZSTR_LEN(search_str), ZSTR_VAL(search_str), ZSTR_LEN(search_str),
ZSTR_VAL(replace_str), ZSTR_LEN(replace_str), &replace_count)); ZSTR_VAL(replace_str), ZSTR_LEN(replace_str), &replace_count));
} else { } else {
lc_subject_str = php_string_tolower(subject_str); lc_subject_str = zend_string_tolower(subject_str);
ZVAL_STR(result, php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str), ZVAL_STR(result, php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
search_str, ZSTR_VAL(replace_str), ZSTR_LEN(replace_str), &replace_count)); search_str, ZSTR_VAL(replace_str), ZSTR_LEN(replace_str), &replace_count));
zend_string_release_ex(lc_subject_str, 0); zend_string_release_ex(lc_subject_str, 0);
@ -4941,7 +4869,7 @@ int php_tag_find(char *tag, size_t len, const char *set) {
n = norm; n = norm;
t = tag; t = tag;
c = tolower(*t); c = zend_tolower_ascii(*t);
/* /*
normalize the tag removing leading and trailing whitespace normalize the tag removing leading and trailing whitespace
and turn any <a whatever...> into just <a> and any </tag> and turn any <a whatever...> into just <a> and any </tag>
@ -4969,7 +4897,7 @@ int php_tag_find(char *tag, size_t len, const char *set) {
} }
break; break;
} }
c = tolower(*(++t)); c = zend_tolower_ascii(*(++t));
} }
*(n++) = '>'; *(n++) = '>';
*n = '\0'; *n = '\0';

View File

@ -1,13 +0,0 @@
--TEST--
Bug #79986 (str_ireplace bug with diacritics characters)
--SKIPIF--
<?php
if (!setlocale(LC_ALL, 'de_DE.ISO-8859-1', 'de-DE')) die('skip German locale not available');
?>
--FILE--
<?php
setlocale(LC_ALL, 'de_DE.ISO-8859-1', 'de-DE');
echo str_ireplace(["\xE4", "\xF6", "\xFC"], ['1', '2', '3'], "\xE4\xC4 \xF6\xD6 \xFC\xDC") . PHP_EOL;
?>
--EXPECT--
11 22 33

View File

@ -1,340 +0,0 @@
--TEST--
Test strtolower() function
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) != "WIN" || !setlocale(LC_CTYPE, "English_United States.1252"))
die('skip Run only on Windows with locale "English_United States.1252" available');
?>
--FILE--
<?php
setlocale(LC_CTYPE, "English_United States.1252");
echo "*** Testing strtolower() with all 256 chars ***\n";
for ($i=0; $i<=255; $i++){
$char = chr($i);
print(bin2hex($char))." => ".(bin2hex(strtolower("$char")))."\n";
}
echo "*** Testing strlower() with basic strings ***\n";
$str = "Mary Had A liTTle LAmb and ShE loveD IT So\n";
var_dump(strtolower($str));
echo "\n*** Testing strtolower() with various strings ***";
/* strings to pass strtolower() */
$strings = array (
"",
"string",
"stRINg0234",
"1.233.344StrinG12333",
"$$$$$$!!!!@@@@@@@ ABCDEF !!!***",
"ABCD\0abcdABCD",
TRUE,
FALSE,
);
$count = 0;
/* loop through to check possible variations */
foreach ($strings as $string) {
echo "\n-- Iteration $count --\n";
var_dump( strtolower($string) );
$count++;
}
echo "\n*** Testing strtolower() with two different case strings ***\n";
if (strtolower("HeLLo woRLd") === strtolower("hEllo WORLD"))
echo "strings are same, with Case Insensitive\n";
else
echo "strings are not same\n";
echo "*** Done ***";
?>
--EXPECTF--
*** Testing strtolower() with all 256 chars ***
00 => 00
01 => 01
02 => 02
03 => 03
04 => 04
05 => 05
06 => 06
07 => 07
08 => 08
09 => 09
0a => 0a
0b => 0b
0c => 0c
0d => 0d
0e => 0e
0f => 0f
10 => 10
11 => 11
12 => 12
13 => 13
14 => 14
15 => 15
16 => 16
17 => 17
18 => 18
19 => 19
1a => 1a
1b => 1b
1c => 1c
1d => 1d
1e => 1e
1f => 1f
20 => 20
21 => 21
22 => 22
23 => 23
24 => 24
25 => 25
26 => 26
27 => 27
28 => 28
29 => 29
2a => 2a
2b => 2b
2c => 2c
2d => 2d
2e => 2e
2f => 2f
30 => 30
31 => 31
32 => 32
33 => 33
34 => 34
35 => 35
36 => 36
37 => 37
38 => 38
39 => 39
3a => 3a
3b => 3b
3c => 3c
3d => 3d
3e => 3e
3f => 3f
40 => 40
41 => 61
42 => 62
43 => 63
44 => 64
45 => 65
46 => 66
47 => 67
48 => 68
49 => 69
4a => 6a
4b => 6b
4c => 6c
4d => 6d
4e => 6e
4f => 6f
50 => 70
51 => 71
52 => 72
53 => 73
54 => 74
55 => 75
56 => 76
57 => 77
58 => 78
59 => 79
5a => 7a
5b => 5b
5c => 5c
5d => 5d
5e => 5e
5f => 5f
60 => 60
61 => 61
62 => 62
63 => 63
64 => 64
65 => 65
66 => 66
67 => 67
68 => 68
69 => 69
6a => 6a
6b => 6b
6c => 6c
6d => 6d
6e => 6e
6f => 6f
70 => 70
71 => 71
72 => 72
73 => 73
74 => 74
75 => 75
76 => 76
77 => 77
78 => 78
79 => 79
7a => 7a
7b => 7b
7c => 7c
7d => 7d
7e => 7e
7f => 7f
80 => 80
81 => 81
82 => 82
83 => 83
84 => 84
85 => 85
86 => 86
87 => 87
88 => 88
89 => 89
8a => 9a
8b => 8b
8c => 9c
8d => 8d
8e => 9e
8f => 8f
90 => 90
91 => 91
92 => 92
93 => 93
94 => 94
95 => 95
96 => 96
97 => 97
98 => 98
99 => 99
9a => 9a
9b => 9b
9c => 9c
9d => 9d
9e => 9e
9f => ff
a0 => a0
a1 => a1
a2 => a2
a3 => a3
a4 => a4
a5 => a5
a6 => a6
a7 => a7
a8 => a8
a9 => a9
aa => aa
ab => ab
ac => ac
ad => ad
ae => ae
af => af
b0 => b0
b1 => b1
b2 => b2
b3 => b3
b4 => b4
b5 => b5
b6 => b6
b7 => b7
b8 => b8
b9 => b9
ba => ba
bb => bb
bc => bc
bd => bd
be => be
bf => bf
c0 => e0
c1 => e1
c2 => e2
c3 => e3
c4 => e4
c5 => e5
c6 => e6
c7 => e7
c8 => e8
c9 => e9
ca => ea
cb => eb
cc => ec
cd => ed
ce => ee
cf => ef
d0 => f0
d1 => f1
d2 => f2
d3 => f3
d4 => f4
d5 => f5
d6 => f6
d7 => d7
d8 => f8
d9 => f9
da => fa
db => fb
dc => fc
dd => fd
de => fe
df => df
e0 => e0
e1 => e1
e2 => e2
e3 => e3
e4 => e4
e5 => e5
e6 => e6
e7 => e7
e8 => e8
e9 => e9
ea => ea
eb => eb
ec => ec
ed => ed
ee => ee
ef => ef
f0 => f0
f1 => f1
f2 => f2
f3 => f3
f4 => f4
f5 => f5
f6 => f6
f7 => f7
f8 => f8
f9 => f9
fa => fa
fb => fb
fc => fc
fd => fd
fe => fe
ff => ff
*** Testing strlower() with basic strings ***
string(43) "mary had a little lamb and she loved it so
"
*** Testing strtolower() with various strings ***
-- Iteration 0 --
string(0) ""
-- Iteration 1 --
string(6) "string"
-- Iteration 2 --
string(10) "string0234"
-- Iteration 3 --
string(20) "1.233.344string12333"
-- Iteration 4 --
string(31) "$$$$$$!!!!@@@@@@@ abcdef !!!***"
-- Iteration 5 --
string(13) "abcd%0abcdabcd"
-- Iteration 6 --
string(1) "1"
-- Iteration 7 --
string(0) ""
*** Testing strtolower() with two different case strings ***
strings are same, with Case Insensitive
*** Done ***

View File

@ -1,27 +1,10 @@
--TEST-- --TEST--
Test strtolower() function Test strtolower() function
--SKIPIF--
<?php
if( substr(PHP_OS, 0, 3) == 'WIN') {
if (!setlocale(LC_ALL, 'C')) {
die('skip need "C" locale (this windows is broken)');
}
} else {
if (!setlocale(LC_ALL, 'en_US.UTF-8', 'en')) {
die('skip need "en_US.UTF-8" locale');
}
}
?>
--FILE-- --FILE--
<?php <?php
if( substr(PHP_OS, 0, 3) == 'WIN') {
setlocale(LC_ALL, 'C');
} else {
setlocale(LC_ALL, 'en_US.UTF-8');
}
echo "*** Testing strtolower() with 128 chars ***\n"; echo "*** Testing strtolower() with 256 chars ***\n";
for ($i=0; $i<=127; $i++){ for ($i=0; $i<=255; $i++){
$char = chr($i); $char = chr($i);
print(bin2hex($char))." => ".(bin2hex(strtolower("$char")))."\n"; print(bin2hex($char))." => ".(bin2hex(strtolower("$char")))."\n";
} }
@ -66,7 +49,7 @@ else
echo "*** Done ***"; echo "*** Done ***";
?> ?>
--EXPECTF-- --EXPECTF--
*** Testing strtolower() with 128 chars *** *** Testing strtolower() with 256 chars ***
00 => 00 00 => 00
01 => 01 01 => 01
02 => 02 02 => 02
@ -195,6 +178,134 @@ echo "*** Done ***";
7d => 7d 7d => 7d
7e => 7e 7e => 7e
7f => 7f 7f => 7f
80 => 80
81 => 81
82 => 82
83 => 83
84 => 84
85 => 85
86 => 86
87 => 87
88 => 88
89 => 89
8a => 8a
8b => 8b
8c => 8c
8d => 8d
8e => 8e
8f => 8f
90 => 90
91 => 91
92 => 92
93 => 93
94 => 94
95 => 95
96 => 96
97 => 97
98 => 98
99 => 99
9a => 9a
9b => 9b
9c => 9c
9d => 9d
9e => 9e
9f => 9f
a0 => a0
a1 => a1
a2 => a2
a3 => a3
a4 => a4
a5 => a5
a6 => a6
a7 => a7
a8 => a8
a9 => a9
aa => aa
ab => ab
ac => ac
ad => ad
ae => ae
af => af
b0 => b0
b1 => b1
b2 => b2
b3 => b3
b4 => b4
b5 => b5
b6 => b6
b7 => b7
b8 => b8
b9 => b9
ba => ba
bb => bb
bc => bc
bd => bd
be => be
bf => bf
c0 => c0
c1 => c1
c2 => c2
c3 => c3
c4 => c4
c5 => c5
c6 => c6
c7 => c7
c8 => c8
c9 => c9
ca => ca
cb => cb
cc => cc
cd => cd
ce => ce
cf => cf
d0 => d0
d1 => d1
d2 => d2
d3 => d3
d4 => d4
d5 => d5
d6 => d6
d7 => d7
d8 => d8
d9 => d9
da => da
db => db
dc => dc
dd => dd
de => de
df => df
e0 => e0
e1 => e1
e2 => e2
e3 => e3
e4 => e4
e5 => e5
e6 => e6
e7 => e7
e8 => e8
e9 => e9
ea => ea
eb => eb
ec => ec
ed => ed
ee => ee
ef => ef
f0 => f0
f1 => f1
f2 => f2
f3 => f3
f4 => f4
f5 => f5
f6 => f6
f7 => f7
f8 => f8
f9 => f9
fa => fa
fb => fb
fc => fc
fd => fd
fe => fe
ff => ff
*** Testing strlower() with basic strings *** *** Testing strlower() with basic strings ***
string(43) "mary had a little lamb and she loved it so string(43) "mary had a little lamb and she loved it so
" "

View File

@ -1,20 +0,0 @@
--TEST--
Test strtoupper on non-ASCII characters
--SKIPIF--
<?php
if (!setlocale(LC_CTYPE, "de_DE", "de", "german", "ge", "de_DE.ISO8859-1", "ISO8859-1")) {
die("skip locale needed for this test is not supported on this platform");
}
?>
--FILE--
<?php
$chars = "äöü";
// Not sure which is most portable. BSD's answer to
// this one. A small array based on PHP_OS should
// cover a majority of systems and makes the problem
// of locales transparent for the end user.
setlocale(LC_CTYPE, "de_DE", "de", "german", "ge", "de_DE.ISO8859-1", "ISO8859-1");
echo strtoupper($chars)."\n";
?>
--EXPECT--
ÄÖÜ

View File

@ -1,342 +0,0 @@
--TEST--
Test strtoupper() function
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) != "WIN" || !setlocale(LC_CTYPE, "English_United States.1252"))
die('skip Run only on Windows with locale "English_United States.1252" available');
?>
--FILE--
<?php
setlocale(LC_CTYPE, "English_United States.1252");
echo "*** Testing strtoupper() with all 256 chars ***\n";
for ($i=0; $i<=255; $i++){
$char = chr($i);
print(bin2hex($char))." => ".(bin2hex(strtoupper("$char")))."\n";
}
echo "\n*** Testing strtoupper() with basic strings ***\n";
$str = "Mary Had A liTTle LAmb and ShE loveD IT So\n";
var_dump(strtoupper($str));
echo "\n*** Testing strtoupper() with various strings ***";
/* strings to pass strtoupper() */
$strings = array (
"",
"string",
"stRINg0234",
"1.233.344StrinG12333",
"$$$$$$!!!!@@@@@@@ ABCDEF !!!***",
"ABCD\0abcdABCD",
TRUE,
FALSE,
);
$count = 0;
/* loop through to check possible variations */
foreach ($strings as $string) {
echo "\n-- Iteration $count --\n";
var_dump( strtoupper($string) );
$count++;
}
echo "\n*** Testing strtoupper() with two different case strings ***\n";
if (strtoupper("HeLLo woRLd") === strtoupper("hEllo WORLD"))
echo "strings are same, with Case Insensitive\n";
else
echo "strings are not same\n";
echo "*** Done ***";
?>
--EXPECTF--
*** Testing strtoupper() with all 256 chars ***
00 => 00
01 => 01
02 => 02
03 => 03
04 => 04
05 => 05
06 => 06
07 => 07
08 => 08
09 => 09
0a => 0a
0b => 0b
0c => 0c
0d => 0d
0e => 0e
0f => 0f
10 => 10
11 => 11
12 => 12
13 => 13
14 => 14
15 => 15
16 => 16
17 => 17
18 => 18
19 => 19
1a => 1a
1b => 1b
1c => 1c
1d => 1d
1e => 1e
1f => 1f
20 => 20
21 => 21
22 => 22
23 => 23
24 => 24
25 => 25
26 => 26
27 => 27
28 => 28
29 => 29
2a => 2a
2b => 2b
2c => 2c
2d => 2d
2e => 2e
2f => 2f
30 => 30
31 => 31
32 => 32
33 => 33
34 => 34
35 => 35
36 => 36
37 => 37
38 => 38
39 => 39
3a => 3a
3b => 3b
3c => 3c
3d => 3d
3e => 3e
3f => 3f
40 => 40
41 => 41
42 => 42
43 => 43
44 => 44
45 => 45
46 => 46
47 => 47
48 => 48
49 => 49
4a => 4a
4b => 4b
4c => 4c
4d => 4d
4e => 4e
4f => 4f
50 => 50
51 => 51
52 => 52
53 => 53
54 => 54
55 => 55
56 => 56
57 => 57
58 => 58
59 => 59
5a => 5a
5b => 5b
5c => 5c
5d => 5d
5e => 5e
5f => 5f
60 => 60
61 => 41
62 => 42
63 => 43
64 => 44
65 => 45
66 => 46
67 => 47
68 => 48
69 => 49
6a => 4a
6b => 4b
6c => 4c
6d => 4d
6e => 4e
6f => 4f
70 => 50
71 => 51
72 => 52
73 => 53
74 => 54
75 => 55
76 => 56
77 => 57
78 => 58
79 => 59
7a => 5a
7b => 7b
7c => 7c
7d => 7d
7e => 7e
7f => 7f
80 => 80
81 => 81
82 => 82
83 => 83
84 => 84
85 => 85
86 => 86
87 => 87
88 => 88
89 => 89
8a => 8a
8b => 8b
8c => 8c
8d => 8d
8e => 8e
8f => 8f
90 => 90
91 => 91
92 => 92
93 => 93
94 => 94
95 => 95
96 => 96
97 => 97
98 => 98
99 => 99
9a => 8a
9b => 9b
9c => 8c
9d => 9d
9e => 8e
9f => 9f
a0 => a0
a1 => a1
a2 => a2
a3 => a3
a4 => a4
a5 => a5
a6 => a6
a7 => a7
a8 => a8
a9 => a9
aa => aa
ab => ab
ac => ac
ad => ad
ae => ae
af => af
b0 => b0
b1 => b1
b2 => b2
b3 => b3
b4 => b4
b5 => b5
b6 => b6
b7 => b7
b8 => b8
b9 => b9
ba => ba
bb => bb
bc => bc
bd => bd
be => be
bf => bf
c0 => c0
c1 => c1
c2 => c2
c3 => c3
c4 => c4
c5 => c5
c6 => c6
c7 => c7
c8 => c8
c9 => c9
ca => ca
cb => cb
cc => cc
cd => cd
ce => ce
cf => cf
d0 => d0
d1 => d1
d2 => d2
d3 => d3
d4 => d4
d5 => d5
d6 => d6
d7 => d7
d8 => d8
d9 => d9
da => da
db => db
dc => dc
dd => dd
de => de
df => df
e0 => c0
e1 => c1
e2 => c2
e3 => c3
e4 => c4
e5 => c5
e6 => c6
e7 => c7
e8 => c8
e9 => c9
ea => ca
eb => cb
ec => cc
ed => cd
ee => ce
ef => cf
f0 => d0
f1 => d1
f2 => d2
f3 => d3
f4 => d4
f5 => d5
f6 => d6
f7 => f7
f8 => d8
f9 => d9
fa => da
fb => db
fc => dc
fd => dd
fe => de
ff => 9f
*** Testing strtoupper() with basic strings ***
string(43) "MARY HAD A LITTLE LAMB AND SHE LOVED IT SO
"
*** Testing strtoupper() with various strings ***
-- Iteration 0 --
string(0) ""
-- Iteration 1 --
string(6) "STRING"
-- Iteration 2 --
string(10) "STRING0234"
-- Iteration 3 --
string(20) "1.233.344STRING12333"
-- Iteration 4 --
string(31) "$$$$$$!!!!@@@@@@@ ABCDEF !!!***"
-- Iteration 5 --
string(13) "ABCD%0ABCDABCD"
-- Iteration 6 --
string(1) "1"
-- Iteration 7 --
string(0) ""
*** Testing strtoupper() with two different case strings ***
strings are same, with Case Insensitive
*** Done ***

View File

@ -1,27 +1,9 @@
--TEST-- --TEST--
Test strtoupper() function Test strtoupper() function
--SKIPIF--
<?php
if( substr(PHP_OS, 0, 3) == 'WIN') {
if (!setlocale(LC_ALL, 'C')) {
die('skip need "C" locale (this windows is broken)');
}
} else {
if (!setlocale(LC_ALL, 'en_US.UTF-8', 'en')) {
die('skip need "en_US.UTF-8" locale');
}
}
?>
--FILE-- --FILE--
<?php <?php
if( substr(PHP_OS, 0, 3) == 'WIN') { echo "*** Testing strtoupper() with 256 chars ***\n";
setlocale(LC_ALL, 'C'); for ($i=0; $i<=255; $i++){
} else {
setlocale(LC_ALL, 'en_US.UTF-8');
}
echo "*** Testing strtoupper() with 128 chars ***\n";
for ($i=0; $i<=127; $i++){
$char = chr($i); $char = chr($i);
print(bin2hex($char))." => ".(bin2hex(strtoupper("$char")))."\n"; print(bin2hex($char))." => ".(bin2hex(strtoupper("$char")))."\n";
} }
@ -65,7 +47,7 @@ else
echo "*** Done ***"; echo "*** Done ***";
?> ?>
--EXPECTF-- --EXPECTF--
*** Testing strtoupper() with 128 chars *** *** Testing strtoupper() with 256 chars ***
00 => 00 00 => 00
01 => 01 01 => 01
02 => 02 02 => 02
@ -194,6 +176,134 @@ echo "*** Done ***";
7d => 7d 7d => 7d
7e => 7e 7e => 7e
7f => 7f 7f => 7f
80 => 80
81 => 81
82 => 82
83 => 83
84 => 84
85 => 85
86 => 86
87 => 87
88 => 88
89 => 89
8a => 8a
8b => 8b
8c => 8c
8d => 8d
8e => 8e
8f => 8f
90 => 90
91 => 91
92 => 92
93 => 93
94 => 94
95 => 95
96 => 96
97 => 97
98 => 98
99 => 99
9a => 9a
9b => 9b
9c => 9c
9d => 9d
9e => 9e
9f => 9f
a0 => a0
a1 => a1
a2 => a2
a3 => a3
a4 => a4
a5 => a5
a6 => a6
a7 => a7
a8 => a8
a9 => a9
aa => aa
ab => ab
ac => ac
ad => ad
ae => ae
af => af
b0 => b0
b1 => b1
b2 => b2
b3 => b3
b4 => b4
b5 => b5
b6 => b6
b7 => b7
b8 => b8
b9 => b9
ba => ba
bb => bb
bc => bc
bd => bd
be => be
bf => bf
c0 => c0
c1 => c1
c2 => c2
c3 => c3
c4 => c4
c5 => c5
c6 => c6
c7 => c7
c8 => c8
c9 => c9
ca => ca
cb => cb
cc => cc
cd => cd
ce => ce
cf => cf
d0 => d0
d1 => d1
d2 => d2
d3 => d3
d4 => d4
d5 => d5
d6 => d6
d7 => d7
d8 => d8
d9 => d9
da => da
db => db
dc => dc
dd => dd
de => de
df => df
e0 => e0
e1 => e1
e2 => e2
e3 => e3
e4 => e4
e5 => e5
e6 => e6
e7 => e7
e8 => e8
e9 => e9
ea => ea
eb => eb
ec => ec
ed => ed
ee => ee
ef => ef
f0 => f0
f1 => f1
f2 => f2
f3 => f3
f4 => f4
f5 => f5
f6 => f6
f7 => f7
f8 => f8
f9 => f9
fa => fa
fb => fb
fc => fc
fd => fd
fe => fe
ff => ff
*** Testing strtoupper() with basic strings *** *** Testing strtoupper() with basic strings ***
string(43) "MARY HAD A LITTLE LAMB AND SHE LOVED IT SO string(43) "MARY HAD A LITTLE LAMB AND SHE LOVED IT SO

View File

@ -23,7 +23,6 @@
#include "php.h" #include "php.h"
#include "zend_variables.h" #include "zend_variables.h"
#include "ext/standard/php_string.h"
#include "ext/standard/info.h" #include "ext/standard/info.h"
#include "ext/standard/html.h" #include "ext/standard/html.h"