Everything fine again after "Fix EOF cases" :-) marcus
At 20:41 04.10.2002, Marcus Börger wrote: >No good idea it broke at least exif which was the >first extension that changed to streams. > >marcus > >At 20:21 04.10.2002, Sascha Schumann wrote: >>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 > > >-- >PHP CVS Mailing List (http://www.php.net/) >To unsubscribe, visit: http://www.php.net/unsub.php -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php