sas             Fri Oct  4 14:21:40 2002 EDT

  Modified files:              
    /php4/main  network.c php_streams.h streams.c 
  Log:
  Improve the general behaviour of stream_gets and fix its semantics
  with regard to sockets. The behaviour should be aligned with PHP 4.2 now.
  This has been verified to some degree.
  
  If the underlying stream operations block when no new data is readable,
  we need to take extra precautions.
  
  If there is buffered data available, we check for a EOL. If it exists,
  we pass the data immediately back to the caller. This saves a call
  to the read implementation and will not block where blocking
  is not necessary at all.
  
  If the stream buffer contains more data than the caller requested,
  we can also avoid that costly step and simply return that data.
  
  
Index: php4/main/network.c
diff -u php4/main/network.c:1.70 php4/main/network.c:1.71
--- php4/main/network.c:1.70    Sat Sep 28 18:12:23 2002
+++ php4/main/network.c Fri Oct  4 14:21:40 2002
@@ -16,7 +16,7 @@
    | Streams work by Wez Furlong <[EMAIL PROTECTED]>                   |
    +----------------------------------------------------------------------+
  */
-/* $Id: network.c,v 1.70 2002/09/28 22:12:23 wez Exp $ */
+/* $Id: network.c,v 1.71 2002/10/04 18:21:40 sas Exp $ */
 
 /*#define DEBUG_MAIN_NETWORK 1*/
 
@@ -923,7 +923,8 @@
        NULL, /* seek */
        php_sockop_cast,
        php_sockop_stat,
-       php_sockop_set_option
+       php_sockop_set_option,
+       1
 };
 
 
Index: php4/main/php_streams.h
diff -u php4/main/php_streams.h:1.51 php4/main/php_streams.h:1.52
--- php4/main/php_streams.h:1.51        Sat Sep 28 18:10:47 2002
+++ php4/main/php_streams.h     Fri Oct  4 14:21:40 2002
@@ -153,6 +153,7 @@
        int (*cast)(php_stream *stream, int castas, void **ret TSRMLS_DC);
        int (*stat)(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
        int (*set_option)(php_stream *stream, int option, int value, void *ptrparam 
TSRMLS_DC);
+       int dont_block;
 } php_stream_ops;
 
 typedef struct _php_stream_wrapper_ops {
Index: php4/main/streams.c
diff -u php4/main/streams.c:1.89 php4/main/streams.c:1.90
--- php4/main/streams.c:1.89    Thu Oct  3 12:06:41 2002
+++ php4/main/streams.c Fri Oct  4 14:21:40 2002
@@ -20,7 +20,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: streams.c,v 1.89 2002/10/03 16:06:41 helly Exp $ */
+/* $Id: streams.c,v 1.90 2002/10/04 18:21:40 sas Exp $ */
 
 #define _GNU_SOURCE
 #include "php.h"
@@ -494,7 +494,11 @@
                
                if (justread <= 0)
                        break;
+               
                stream->writepos += justread;
+               
+               if (stream->ops->dont_block)
+                       break;
        }
 }
 
@@ -615,74 +619,105 @@
        return stream->ops->stat(stream, ssb TSRMLS_CC);
 }
 
-PHPAPI char *_php_stream_gets(php_stream *stream, char *buf, size_t maxlen TSRMLS_DC)
+static char *php_stream_locate_eol(php_stream *stream TSRMLS_DC)
 {
+       size_t avail;
        char *cr, *lf, *eol = NULL;
-       size_t toread = 0, didread = 0, justread = 0, avail = 0;
        char *readptr;
        
+       readptr = stream->readbuf + stream->readpos;
+       avail = stream->writepos - stream->readpos;
+
+       /* Look for EOL */
+       if (stream->flags & PHP_STREAM_FLAG_DETECT_EOL) {
+               cr = memchr(readptr, '\r', avail);
+               lf = memchr(readptr, '\n', avail);
+
+               if (cr && lf != cr + 1) {
+                       /* mac */
+                       stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL;
+                       stream->flags |= PHP_STREAM_FLAG_EOL_MAC;
+                       eol = cr;
+               } else if ((cr && lf && cr == lf - 1) || (lf)) {
+                       /* dos or unix endings */
+                       stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL;
+                       eol = lf;
+               }
+       } else if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
+               eol = memchr(readptr, '\r', avail);
+       } else {
+               /* unix (and dos) line endings */
+               eol = memchr(readptr, '\n', avail);
+       }
+
+       return eol;
+}
+
+PHPAPI char *_php_stream_gets(php_stream *stream, char *buf, size_t maxlen TSRMLS_DC)
+{
+       size_t avail = 0;
+       
        if (maxlen == 0)
                return NULL;
-       
-       while (didread < maxlen - 1) {
-               toread = maxlen - 1;
-               if (toread > stream->chunk_size)
-                       toread = stream->chunk_size;
 
-               php_stream_fill_read_buffer(stream, toread TSRMLS_CC);
+       /*
+        * If the underlying stream operations block when no new data is readable,
+        * we need to take extra precautions.
+        *
+        * If there is buffered data available, we check for a EOL. If it exists,
+        * we pass the data immediately back to the caller. This saves a call
+        * to the read implementation and will not block where blocking
+        * is not necessary at all.
+        *
+        * If the stream buffer contains more data than the caller requested,
+        * we can also avoid that costly step and simply return that data.
+        */
 
-               readptr = stream->readbuf + stream->readpos;
+       for (;;) {
                avail = stream->writepos - stream->readpos;
 
-               if (avail == 0)
-                       break;
-               
-               /* Look for EOL */
-               if (stream->flags & PHP_STREAM_FLAG_DETECT_EOL) {
-                       cr = memchr(readptr, '\r', avail);
-                       lf = memchr(readptr, '\n', avail);
-
-                       if (cr && lf != cr + 1) {
-                               /* mac */
-                               stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL;
-                               stream->flags |= PHP_STREAM_FLAG_EOL_MAC;
-                               eol = cr;
-                       } else if ((cr && lf && cr == lf - 1) || (lf)) {
-                               /* dos or unix endings */
-                               stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL;
-                               eol = lf;
+               if (avail > 0) {
+                       size_t cpysz = 0;
+                       char *readptr;
+                       char *eol;
+                       int done = 0;
+
+                       readptr = stream->readbuf + stream->readpos;
+                       eol = php_stream_locate_eol(stream TSRMLS_CC);
+
+                       if (eol) {
+                               cpysz = eol - readptr + 1;
+                               done = 1;
+                       } else {
+                               cpysz = avail;
                        }
-               } else if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
-                       eol = memchr(readptr, '\r', avail);
-               } else {
-                       /* unix (and dos) line endings */
-                       eol = memchr(readptr, '\n', avail);
-               }
 
-               if (eol && (size_t)((ptrdiff_t)eol + 1 - (ptrdiff_t)readptr) <= maxlen 
- 1) {
-                       justread = eol + 1 - readptr;
-               } else {
-                       eol = NULL;
-                       justread = toread;
-                       if (justread > avail)
-                               justread = avail;
-               }
+                       if (cpysz >= maxlen - 1) {
+                               cpysz = maxlen - 1;
+                               done = 1;
+                       }
 
-               memcpy(buf, readptr, justread);
-               didread += justread;
-               buf += justread;
-               stream->readpos += justread;
+                       memcpy(buf, readptr, cpysz);
 
-               if (eol)
-                       break;
-       }
+                       stream->position += cpysz;
+                       stream->readpos += cpysz;
+                       buf += cpysz;
+                       maxlen -= cpysz;
 
-       if (didread == 0)
-               return NULL;
+                       if (done) {
+                               break;
+                       }
+               } else {
+                       size_t toread = maxlen - 1;
+                       if (toread > stream->chunk_size)
+                               toread = stream->chunk_size;
+
+                       /* XXX: Should not the loop end, if the stream op fails? */
+                       php_stream_fill_read_buffer(stream, toread TSRMLS_CC);
+               }
+       }
        
-       /* terminate the buffer */
-       *buf = '\0';
-       stream->position += didread;
+       buf[0] = '\0';
 
        return buf;
 }



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to