Improve StringUtil::trim()
authorTim Düsterhus <duesterhus@woltlab.com>
Thu, 17 Nov 2016 16:46:14 +0000 (17:46 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 17 Nov 2016 16:48:04 +0000 (17:48 +0100)
The previous regular expression for trim at the end
(introduced in 73d8b58f6a2ed1c9f49684e867d2b42a8cd82920) show bad
performance for huge strings containing little amounts of white space.
The version before that one blew the C stack for huge strings containing
huge amounts of contiguous white space.

Matching for the Unicode property of being a whitespace is both faster
(less backtracking for alternations) *and* more correct (because it
matches many more types of white space).

win-win

wcfsetup/install/files/lib/util/StringUtil.class.php

index dbf98564c6834a4402699fc75523b9edf45a574d..904b7bf8a4c189e985ebcf6934fb452a29204155 100644 (file)
@@ -70,16 +70,21 @@ final class StringUtil {
        }
        
        /**
-        * Swallowes whitespace from beginning and end of the string.
+        * Removes Unicode whitespace characters from the beginning
+        * and ending of the given string.
         * 
         * @param       string          $text
         * @return      string
         */
        public static function trim($text) {
-               // Whitespace + (narrow) non breaking spaces.
-               // No one can triforce now.
-               $text = preg_replace('/^(\s|'.chr(226).chr(128).chr(175).'|'.chr(194).chr(160).')+/', '', $text);
-               $text = preg_replace('/([^\s'.chr(226).chr(194).']++)(?:\s|'.chr(226).chr(128).chr(175).'|'.chr(194).chr(160).')++$/', '\\1', $text);
+               // These regular expressions use character properties
+               // to find characters defined as space in the unicode
+               // specification.
+               // Do not merge the expressions, they are seperated for
+               // performance reasons.
+               
+               $text = preg_replace('/^\p{Zs}+/u', '', $text);
+               $text = preg_replace('/\p{Zs}+$/u', '', $text);
                return $text;
        }