]> granicus.if.org Git - php/commitdiff
Update stream_copy_to_stream() for PHP6
authorSara Golemon <pollita@php.net>
Fri, 22 Sep 2006 19:54:30 +0000 (19:54 +0000)
committerSara Golemon <pollita@php.net>
Fri, 22 Sep 2006 19:54:30 +0000 (19:54 +0000)
ext/standard/streamsfuncs.c
main/php_streams.h
main/streams/streams.c

index 23c5286dea0c660e36757c72a15346b6e6f94622..dcf56ffb4724deeba748f29689cb8d099d3edd1a 100644 (file)
@@ -443,7 +443,7 @@ PHP_FUNCTION(stream_get_contents)
 }
 /* }}} */
 
-/* {{{ proto long stream_copy_to_stream(resource source, resource dest [, long maxlen [, long pos]])
+/* {{{ proto long stream_copy_to_stream(resource source, resource dest [, long maxlen [, long pos]]) U
    Reads up to maxlen bytes from source stream and writes them to dest stream. */
 PHP_FUNCTION(stream_copy_to_stream)
 {
index e4cdee2e75cf2f2ca8fc75095a6e1f12e2811f4f..8219081d9e611713ed0d79c28c905425f6569add 100755 (executable)
@@ -456,9 +456,12 @@ END_EXTERN_C()
 #define PHP_STREAM_COPY_ALL            ((size_t)-1)
 
 BEGIN_EXTERN_C()
+PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, int maxchars STREAMS_DC TSRMLS_DC);
 PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
-#define php_stream_copy_to_stream(src, dest, maxlen)   _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
-
+/* Preserve "characters" semantics by having maxlen refer to maxchars in a unicode context */
+#define php_stream_copy_to_stream(src, dest, maxlen)   ( ((src)->readbuf_type == IS_STRING) \
+               ? _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC) \
+               : _php_stream_ucopy_to_stream((src), (dest), -1, (maxlen) STREAMS_CC TSRMLS_CC) )
 
 /* read all data from stream and put into a buffer. Caller must free buffer when done.
  * The copy will use mmap if available. */
index 2aa84d0ee1a15545a58bc5c8a9c867241279329a..75b8a6f63dec02f030586bbb45f32c5c693c8eee 100755 (executable)
@@ -1568,7 +1568,7 @@ PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
 
                ucnv_resetFromUnicode(conv);
 
-               while ((b = php_stream_read_unicode(stream, inbuf_start, sizeof(inbuf_start))) > 0) {
+               while ((b = php_stream_read_unicode(stream, inbuf_start, 8192)) > 0) {
                        char *outbuf = outbuf_start;
                        const UChar *inbuf = inbuf_start;
                        UErrorCode status = U_ZERO_ERROR;
@@ -1733,14 +1733,97 @@ PHPAPI size_t _php_stream_copy_to_mem_ex(php_stream *src, zend_uchar rettype, vo
        return len;
 }
 
+/* Designed for copying UChars (taking into account both maxlen and maxchars) */
+PHPAPI size_t _php_stream_ucopy_to_stream(php_stream *src, php_stream *dest, size_t maxlen, int maxchars STREAMS_DC TSRMLS_DC)
+{
+       size_t haveread = 0;
+       php_stream_statbuf ssbuf;
+
+       if (src->readbuf_type == IS_STRING) {
+               /* Called incorrectly, don't do that. */
+               return _php_stream_copy_to_stream(src, dest, maxlen STREAMS_CC TSRMLS_CC);
+       }
+
+       if (maxlen == 0 || maxchars == 0) {
+               return 0;
+       }
+
+       if (maxlen == PHP_STREAM_COPY_ALL) {
+               maxlen = 0;
+       }
+
+       if (php_stream_stat(src, &ssbuf) == 0) {
+               /* in the event that the source file is 0 bytes, return 1 to indicate success
+                * because opening the file to write had already created a copy */
+               if (ssbuf.sb.st_size == 0
+#ifdef S_ISFIFO
+                && !S_ISFIFO(ssbuf.sb.st_mode)
+#endif
+#ifdef S_ISCHR
+                && !S_ISCHR(ssbuf.sb.st_mode)
+#endif
+               ) {
+                       return 1;
+               }
+       }
+
+       while(1) {
+               UChar buf[CHUNK_SIZE];
+               size_t readchunk = CHUNK_SIZE;
+               size_t didread;
+
+               if (maxlen && (maxlen - haveread) < readchunk) {
+                       readchunk = maxlen - haveread;
+               }
+
+               didread = php_stream_read_unicode_ex(src, buf, readchunk, maxchars);
+
+               if (didread) {
+                       /* extra paranoid */
+                       size_t didwrite, towrite;
+                       UChar *writeptr;
+
+                       if (maxchars > 0) {
+                               /* Determine number of chars in this buf */
+                               maxchars -= u_countChar32(buf, didread);
+                       }
+
+                       towrite = didread;
+                       writeptr = buf;
+                       haveread += didread;
+
+                       while(towrite) {
+                               didwrite = php_stream_write_unicode(dest, writeptr, towrite);
+                               if (didwrite == 0) {
+                                       return 0;       /* error */
+                               }
+
+                               towrite -= didwrite;
+                               writeptr += didwrite;
+                       }
+               } else {
+                       return haveread;
+               }
+
+               if (maxchars == 0 || maxlen - haveread == 0) {
+                       break;
+               }
+       }
+
+       return haveread;
+}
+
+/* Optimized for copying octets from source stream */
 PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC)
 {
-       char buf[CHUNK_SIZE];
-       size_t readchunk;
        size_t haveread = 0;
-       size_t didread;
        php_stream_statbuf ssbuf;
 
+       if (src->readbuf_type == IS_UNICODE) {
+               /* Called incorrectly, don't do that. */
+               return _php_stream_ucopy_to_stream(src, dest, maxlen, -1 STREAMS_CC TSRMLS_CC);
+       }
+
        if (maxlen == 0) {
                return 0;
        }
@@ -1771,7 +1854,7 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
                p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
 
                if (p) {
-                       haveread = php_stream_write(dest, p, mapped);
+                       mapped = php_stream_write(dest, p, mapped);
 
                        php_stream_mmap_unmap(src);
 
@@ -1780,10 +1863,13 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
        }
 
        while(1) {
-               readchunk = sizeof(buf);
+               char buf[CHUNK_SIZE];
+               size_t readchunk = sizeof(buf);
+               size_t didread;
 
-               if (maxlen && (maxlen - haveread) < readchunk)
+               if (maxlen && (maxlen - haveread) < readchunk) {
                        readchunk = maxlen - haveread;
+               }
 
                didread = php_stream_read(src, buf, readchunk);
 
@@ -1813,8 +1899,8 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
                        break;
                }
        }
-       return haveread;
 
+       return haveread;
 }
 /* }}} */