Attached you'll find a patch against PHP_5_3 that implements two new string functions:
str_startswith(haystack, needle [, case_sensitivity]) checks if haystack starts with needle. The check is performed case-insensitively, but this can be overridden by passing TRUE as the value for the third parameter. The second function str_endswith(haystack, needle [, case_sensitivity]) checks if haystack ends with needle and has the same semantics regarding case-sensitivity. I admit that both functions can be easily implemented in userland with already existing functions. At the same time I like them because they make the common tasks of prefix and suffix checks easy and convenient. I won't mind if you guys don't like the idea (I did it mainly for personal entertainment and learning about PHP internals), but if you are interested I'll happily provide a patch for HEAD, too. Also since this is my first foray into PHP internals, comments and corrections are more then appreciated. Martin
Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.725.2.31.2.64.2.37 diff -u -r1.725.2.31.2.64.2.37 basic_functions.c --- ext/standard/basic_functions.c 17 Jul 2008 19:29:34 -0000 1.725.2.31.2.64.2.37 +++ ext/standard/basic_functions.c 19 Jul 2008 12:33:12 -0000 @@ -2827,6 +2827,18 @@ ZEND_ARG_INFO(0, length) ZEND_ARG_INFO(0, case_sensitivity) ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_str_startswith, 0, 0, 2) + ZEND_ARG_INFO(0, haystack) + ZEND_ARG_INFO(0, needle) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_str_endswith, 0, 0, 2) + ZEND_ARG_INFO(0, haystack) + ZEND_ARG_INFO(0, needle) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ syslog.c */ #ifdef HAVE_SYSLOG_H @@ -3146,6 +3158,8 @@ PHP_FE(str_split, arginfo_str_split) PHP_FE(strpbrk, arginfo_strpbrk) PHP_FE(substr_compare, arginfo_substr_compare) + PHP_FE(str_startswith, arginfo_str_startswith) + PHP_FE(str_endswith, arginfo_str_endswith) #ifdef HAVE_STRCOLL PHP_FE(strcoll, arginfo_strcoll) Index: ext/standard/php_string.h =================================================================== RCS file: /repository/php-src/ext/standard/php_string.h,v retrieving revision 1.87.2.2.2.3.2.2 diff -u -r1.87.2.2.2.3.2.2 php_string.h --- ext/standard/php_string.h 19 Jan 2008 19:27:21 -0000 1.87.2.2.2.3.2.2 +++ ext/standard/php_string.h 19 Jul 2008 12:33:12 -0000 @@ -91,6 +91,8 @@ PHP_FUNCTION(str_split); PHP_FUNCTION(strpbrk); PHP_FUNCTION(substr_compare); +PHP_FUNCTION(str_startswith); +PHP_FUNCTION(str_endswith); #ifdef HAVE_STRCOLL PHP_FUNCTION(strcoll); #endif Index: ext/standard/string.c =================================================================== RCS file: /repository/php-src/ext/standard/string.c,v retrieving revision 1.445.2.14.2.69.2.31 diff -u -r1.445.2.14.2.69.2.31 string.c --- ext/standard/string.c 15 Jul 2008 14:46:11 -0000 1.445.2.14.2.69.2.31 +++ ext/standard/string.c 19 Jul 2008 12:33:13 -0000 @@ -5170,6 +5170,58 @@ } /* }}} */ +/* {{{ proto bool str_startswith(string haystack, string needle [, bool case_sensitivity]) + Binary safe optionally case sensitive check if haystack starts with needle */ +PHP_FUNCTION(str_startswith) +{ + char *needle, *haystack; + int needle_len, haystack_len, retval; + zend_bool cs = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &haystack, &haystack_len, &needle, &needle_len, &cs) == FAILURE) { + RETURN_FALSE; + } + + if (needle_len > haystack_len) { + RETURN_FALSE; + } + + if (cs) { + retval = zend_binary_strncmp(needle, needle_len, haystack, haystack_len, needle_len); + } else { + retval = zend_binary_strncasecmp(needle, needle_len, haystack, haystack_len, needle_len); + } + + RETURN_BOOL(retval == 0); +} +/* }}} */ + +/* {{{ proto bool str_endswith(string haystack, string needle [, bool case_sensitivity]) + Binary safe optionally case sensitive check if haystack ends with needle */ +PHP_FUNCTION(str_endswith) +{ + char *needle, *haystack; + int needle_len, haystack_len, retval; + zend_bool cs = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &haystack, &haystack_len, &needle, &needle_len, &cs) == FAILURE) { + RETURN_FALSE; + } + + if (needle_len > haystack_len) { + RETURN_FALSE; + } + + if (cs) { + retval = zend_binary_strncmp(needle, needle_len, haystack + (haystack_len - needle_len), needle_len, needle_len); + } else { + retval = zend_binary_strncasecmp(needle, needle_len, haystack + (haystack_len - needle_len), needle_len, needle_len); + } + + RETURN_BOOL(retval == 0); +} +/* }}} */ + /* * Local variables: * tab-width: 4 Index: ext/standard/tests/strings/str_endswith.phpt =================================================================== RCS file: ext/standard/tests/strings/str_endswith.phpt diff -N ext/standard/tests/strings/str_endswith.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/strings/str_endswith.phpt 19 Jul 2008 12:33:14 -0000 @@ -0,0 +1,27 @@ +--TEST-- +str_endswith() function +--FILE-- +<?php +var_dump(str_endswith("a", "a")); +var_dump(str_endswith("", "")); +var_dump(str_endswith("ab", "b")); +var_dump(str_endswith("a", "ab")); +var_dump(str_endswith(-1, 1)); +var_dump(str_endswith("abc", "abc")); +var_dump(str_endswith("hello", "la")); +var_dump(str_endswith("ABCd", "D")); +var_dump(str_endswith("ABCd", "D", true)); +var_dump(str_endswith("Hellö", "ö")); +var_dump(str_endswith("abc", "")); +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) Index: ext/standard/tests/strings/str_startswith.phpt =================================================================== RCS file: ext/standard/tests/strings/str_startswith.phpt diff -N ext/standard/tests/strings/str_startswith.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/standard/tests/strings/str_startswith.phpt 19 Jul 2008 12:33:14 -0000 @@ -0,0 +1,27 @@ +--TEST-- +str_startswith() function +--FILE-- +<?php +var_dump(str_startswith("a", "a")); +var_dump(str_startswith("", "")); +var_dump(str_startswith("ab", "b")); +var_dump(str_startswith("a", "ab")); +var_dump(str_startswith(-1, 1)); +var_dump(str_startswith("a", null)); +var_dump(str_startswith("abc", "abc")); +var_dump(str_startswith("Ä", "Ä")); +var_dump(str_startswith("A", "a")); +var_dump(str_startswith("A", "a", true)); +var_dump(str_startswith("a", "A")); +--EXPECT-- +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(true)
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php