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

Reply via email to