summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <pollita@php.net>2006-03-24 19:22:24 +0000
committerSara Golemon <pollita@php.net>2006-03-24 19:22:24 +0000
commit880dd406f2f35770c21c3cf269a1ff45cf22561b (patch)
treed47d66f0bd100cd83066f568a7ea33f9327e2739
parentde2f7f1d6660732053bbe2ef1c9ff6b7c2f72633 (diff)
downloadphp-git-880dd406f2f35770c21c3cf269a1ff45cf22561b.tar.gz
Add php_stream_get_record_unicde() API call.
Update stream_get_line() userspace function to handle unicode streams.
-rw-r--r--ext/standard/streamsfuncs.c39
-rwxr-xr-xmain/php_streams.h2
-rwxr-xr-xmain/streams/streams.c67
3 files changed, 99 insertions, 9 deletions
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index 0cfd37e3de..ace8ce1e05 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -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);
}
}
diff --git a/main/php_streams.h b/main/php_streams.h
index 1bb4533443..d62a103937 100755
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -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)
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 597ce80f38..be39d44270 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -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)
{