]> granicus.if.org Git - php/commitdiff
Add php_stream_get_record_unicde() API call.
authorSara Golemon <pollita@php.net>
Fri, 24 Mar 2006 19:22:24 +0000 (19:22 +0000)
committerSara Golemon <pollita@php.net>
Fri, 24 Mar 2006 19:22:24 +0000 (19:22 +0000)
Update stream_get_line() userspace function to handle unicode streams.

ext/standard/streamsfuncs.c
main/php_streams.h
main/streams/streams.c

index 0cfd37e3de16443f475101eff0af38fb49abaa57..ace8ce1e0534c8970bd46a122bca8a65add742ac 100644 (file)
@@ -1235,18 +1235,15 @@ PHP_FUNCTION(stream_filter_remove)
 
 /* {{{ proto string stream_get_line(resource stream, int maxlen [, string ending])
    Read up to maxlen bytes from a stream or until the ending string is found */
-/* UTODO */
 PHP_FUNCTION(stream_get_line)
 {
-       char *str = NULL;
-       int str_len;
        long max_length;
        zval *zstream;
-       char *buf;
        size_t buf_size;
        php_stream *stream;
-       
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|s", &zstream, &max_length, &str, &str_len) == FAILURE) {
+       zval **delim = NULL;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|Z", &zstream, &max_length, &delim) == FAILURE) {
                RETURN_FALSE;
        }
 
@@ -1260,10 +1257,34 @@ PHP_FUNCTION(stream_get_line)
 
        php_stream_from_zval(stream, &zstream);
 
-       if ((buf = php_stream_get_record(stream, max_length, &buf_size, str, str_len TSRMLS_CC))) {
-               RETURN_STRINGL(buf, buf_size, 0);
+       if (php_stream_reads_unicode(stream)) {
+               UChar *buf;
+
+               if (Z_TYPE_PP(delim) != IS_UNICODE) {
+                       convert_to_unicode_ex(delim);
+               }
+
+               /* maxchars == maxlength will prevent the otherwise generous maxlen == max_length * 2
+                  from allocating beyond what's requested */
+               buf = php_stream_get_record_unicode(stream, max_length * 2, max_length, &buf_size, Z_USTRVAL_PP(delim), Z_USTRLEN_PP(delim) TSRMLS_CC);
+               if (!buf) {
+                       RETURN_FALSE;
+               }
+
+               RETURN_UNICODEL(buf, buf_size, 0);
        } else {
-               RETURN_FALSE;
+               char *buf;
+
+               if (Z_TYPE_PP(delim) != IS_STRING) {
+                       convert_to_string_ex(delim);
+               }
+
+               buf = php_stream_get_record(stream, max_length, &buf_size, Z_STRVAL_PP(delim), Z_STRLEN_PP(delim) TSRMLS_CC);
+               if (!buf) {
+                       RETURN_FALSE;
+               }
+
+               RETURN_STRINGL(buf, buf_size, 0);
        }
 }
 
index 1bb4533443f88e7babe70bd12e6fad586e6c0cad..d62a10393761deb3a65106b292faf724fe611309 100755 (executable)
@@ -329,6 +329,8 @@ PHPAPI void *_php_stream_get_line(php_stream *stream, int buf_type, zstr buf, si
                                                                                                                        _php_stream_get_line((stream), (buf_type), ZSTR(buf), (maxlen), (maxchars), NULL TSRMLS_CC)
 
 PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *returned_len, char *delim, size_t delim_len TSRMLS_DC);
+PHPAPI UChar *php_stream_get_record_unicode(php_stream *stream, size_t maxlen, size_t maxchars, size_t *returned_len, UChar *delim, size_t delim_len TSRMLS_DC);
+
 
 PHPAPI UChar *_php_stream_u_get_line(php_stream *stream, UChar *buf, int32_t *pmax_bytes, int32_t *pmax_chars, int *pis_unicode TSRMLS_DC);
 #define php_stream_u_get_line(stream, buf, maxlen_buf, maxlen_chars, buf_type) _php_stream_u_get_line((stream), (buf), (maxlen_buf), (maxlen_chars), (buf_type) TSRMLS_CC)
index 597ce80f382783f7f92219951b97fb6154e81f90..be39d44270c89cdcd3e285131335665ba8573d66 100755 (executable)
@@ -1171,6 +1171,73 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re
        }
 }
 
+PHPAPI UChar *php_stream_get_record_unicode(php_stream *stream, size_t maxlen, size_t maxchars, size_t *returned_len, UChar *delim, size_t delim_len TSRMLS_DC)
+{
+       UChar *e, *buf;
+       size_t toread;
+       int skip = 0;
+
+       if (!php_stream_reads_unicode(stream)) {
+               return NULL;
+       }
+
+       php_stream_fill_read_buffer(stream, maxlen TSRMLS_CC);
+
+       if (delim_len == 0 || !delim) {
+               toread = maxlen;
+       } else {
+               if (delim_len == 1) {
+                       e = u_memchr(stream->readbuf.u + stream->readpos, *delim, stream->writepos - stream->readpos);
+               } else {
+                       e = u_strFindFirst(stream->readbuf.u + stream->readpos, stream->writepos - stream->readpos, delim, delim_len);
+               }
+
+               if (!e) {
+                       toread = maxlen;
+               } else {
+                       toread = e - (stream->readbuf.u + stream->readpos);
+                       skip = 1;
+               }
+       }
+
+       if (toread > maxlen && maxlen > 0) {
+               toread = maxlen;
+       }
+
+       if (U16_IS_SURROGATE(stream->readbuf.u[stream->readpos + toread - 1]) &&
+               U16_IS_SURROGATE_LEAD(stream->readbuf.u[stream->readpos + toread - 1])) {
+               /* Don't orphan */
+               toread--;
+       }
+
+       if (maxchars > 0) {
+               size_t ulen = u_countChar32(stream->readbuf.u + stream->readpos, toread);
+
+               if (maxchars > ulen) {
+                       int i = 0;
+                       UChar *s = stream->readbuf.u + stream->readpos;
+
+                       U16_FWD_N(s, i, toread, maxchars);
+                       toread = i;
+               }
+       }
+
+       buf = eumalloc(toread + 1);
+       *returned_len = php_stream_read_unicode(stream, buf, toread);
+
+       if (*returned_len >= 0) {
+               if (skip) {
+                       stream->readpos += delim_len;
+                       stream->position += delim_len;
+               }
+               buf[*returned_len] = 0;
+               return buf;
+       } else {
+               efree(buf);
+               return NULL;
+       }
+}
+
 /* Writes a buffer directly to a stream, using multiple of the chunk size */
 static size_t _php_stream_write_buffer(php_stream *stream, int buf_type, zstr buf, int buflen TSRMLS_DC)
 {