Re: cvs: php4 /ext/standard string.c

From: Date: Wed, 26 Sep 2001 19:28:45 +0000
Subject: Re: cvs: php4 /ext/standard string.c
References: 1  Groups: php.cvs 
Request: Send a blank email to php-cvs+get-7574@lists.php.net to get a copy of this message
Another possibility would be to emalloc() the maximum size and then erealloc() to a smaller size in the end. It would make the function nicer IMO or do you feel the short memory burst will be too much? I don't think strings longer than a couple of K are ever passed to this function so it should be fine. Andi At 07:34 PM 9/26/2001 +0000, Derick Rethans wrote:
derick          Wed Sep 26 15:34:47 2001 EDT
Modified files:
    /php4/ext/standard  string.c
Log: - nl2br now handles different styles of line endings in one string. (Patch
    by Boian Bonev <boian@bonev.com>)
@- nl2br now handles all styles of line-endings in one string. (Boian, @ Derick) Index: php4/ext/standard/string.c diff -u php4/ext/standard/string.c:1.246 php4/ext/standard/string.c:1.247
--- php4/ext/standard/string.c:1.246    Tue Sep 25 18:48:43 2001
+++ php4/ext/standard/string.c Wed Sep 26 15:34:46 2001 @@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
*/ -/* $Id: string.c,v 1.246 2001/09/25 22:48:43 jeroen Exp $ */ +/* $Id: string.c,v 1.247 2001/09/26 19:34:46 derick Exp $ */ /* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */ @@ -2976,38 +2976,110 @@ } /* }}} */ + /* {{{ proto string nl2br(string str)
    Converts newlines to HTML line breaks */
+ +/* maybe const, but will it break some archaic compiler? */ +static int jumps[3][3]={
+       {0,2,1,},
+       {0,0,1,},
+       {0,2,0,},
+}; +static int acts[3][3]={
+       {0,0,0,},
+       {1,3,1,},
+       {2,2,4,},
+}; +static char *strs[4]={"\n","\r","\n\r","\r\n",}; + PHP_FUNCTION(nl2br) {
-       zval **str;
-       char* tmp;
-       int new_length;
-
-       if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &str)==FAILURE) {
+       /* in brief this inserts <br /> before matched regexp \n\r?|\r\n? */
+       zval **zstr;
+       char  *tmp, *str;
+       int    new_length, length;
+       char  *p, *end, *target;
+       int    repl_cnt = 0;
+
+       int    state = 0;
+       /* 0 - initial; 1 - \r found; 2 - \n found; */
+
+       int action;
+       /* actions:
+          0 - do nothing;   1 - replace \n;   2 - replace \r
+          3 - replace \n\r; 4 - replace \r\n;
+       */
+
+       int ichar;
+       /* letters read from input scanner:
+          0 - any char different from \n or \r, even end of stream;
+          1 - \r;  2 - \n
+       */
+
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zstr) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_string_ex(str);
+       convert_to_string_ex(zstr);
-       /* bail out if the string is empty */
-       if (Z_STRLEN_PP(str) == 0) {
-               RETURN_EMPTY_STRING();
+       str    = Z_STRVAL_PP(zstr);
+       length = Z_STRLEN_PP(zstr);
+       end    = str + length;
+
+       /* it is really faster to scan twice and allocate mem once insted scanning once
+          and constantly reallocing */
+       for (p = str; p <= end; p++) {
+               /* when p == end assume any char and take the last pending action */
+               if (p == end)
+                       ichar = 0;
+               else
+                       ichar = (*p == '\n') ? 2 : ((*p == '\r') ? 1 : 0);
+
+               action = acts[state][ichar];
+               state  = jumps[state][ichar];
+               if (action)
+                       repl_cnt++;
+       }
+
+       if (repl_cnt == 0) {
+               RETURN_STRINGL(str, length, 1);
+       }
+
+       new_length = length + repl_cnt * 6;
+       tmp        = target = emalloc(new_length + 1);
+
+       /* reinit state machine */
+       state = 0;
+       for (p = str; p <= end; p++) {
+               /* when p == end assume any char and take the last pending action */
+               if (p == end)
+                       ichar = 0;
+               else
+                       ichar = (*p == '\n') ? 2 : ((*p == '\r') ? 1 : 0);
+               action = acts[state][ichar];
+               state  = jumps[state][ichar];
+               if (action) {
+                       *target++ = '<';
+                       *target++ = 'b';
+                       *target++ = 'r';
+                       *target++ = ' ';
+                       *target++ = '/';
+                       *target++ = '>';
+                       *target++ = strs[action - 1][0];
+                       if (action > 2)
+                               *target++ = strs[action - 1][1];
+               }
+               if (!ichar && p < end)
+                       *target++ = *p;
        }
-
-       /* Windows style line-endings */
-       tmp = php_str_to_str(Z_STRVAL_PP(str), Z_STRLEN_PP(str), "\r\n", 2, "<br />\r\n", 8, &new_length);
-       if (new_length != Z_STRLEN_PP(str))
-               RETURN_STRINGL (tmp, new_length, 0);
-       efree (tmp);
-       /* Mac / Unix style line-endings */
-       if (php_char_to_str(Z_STRVAL_PP(str),Z_STRLEN_PP(str), '\n',"<br />\n", 7, return_value))
-               return;
-       efree (Z_STRVAL_P(return_value));
-       php_char_to_str(Z_STRVAL_PP(str),Z_STRLEN_PP(str), '\r',"<br />\r", 7, return_value);
+       *target = 0;
+
+       RETURN_STRINGL(tmp, new_length, 0);
} /* }}} */ + /* {{{ proto string strip_tags(string str [, string allowable_tags])
    Strips HTML and PHP tags from a string */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, e-mail: php-cvs-unsubscribe@lists.php.net For additional commands, e-mail: php-cvs-help@lists.php.net To contact the list administrators, e-mail: php-list-admin@lists.php.net


« previous php.cvs (#7574) next »