aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--configure.in78
-rw-r--r--io.c304
3 files changed, 239 insertions, 161 deletions
diff --git a/ChangeLog b/ChangeLog
index 1b2439f8e5..480010e5fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Mon Mar 25 23:39:25 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * configure.in (FILE_READPTR): new. for IO#gets improvement.
+
+ * io.c (READ_DATA_PENDING_PTR): ditto.
+
+ * io.c (remain_size): separated from read_all().
+
+ * io.c (read_all): argument chagend.
+
+ * io.c (appendline): new. get a line and append to string.
+
+ * io.c (swallow): new. swallow continuous line delimiters.
+
+ * io.c (rb_io_getline_fast): add delimiter argument.
+
+ * io.c (rb_io_getline): performance improvement.
+
Mon Mar 25 19:30:25 2002 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/extmk.rb.in (arg_config): get rid of single quotes
diff --git a/configure.in b/configure.in
index d7c6c290d5..e147656a8f 100644
--- a/configure.in
+++ b/configure.in
@@ -453,29 +453,21 @@ else
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
fi
-AC_MSG_CHECKING(count field in FILE structures)
+AC_MSG_CHECKING(read count field in FILE structures)
AC_CACHE_VAL(rb_cv_fcnt,
-[AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", )
-if test "$rb_cv_fcnt" = ""; then
- AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->__cnt = 0;], rb_cv_fcnt="__cnt", )
-fi
-if test "$rb_cv_fcnt" = ""; then
- AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->_r = 0;], rb_cv_fcnt="_r", )
-fi
-if test "$rb_cv_fcnt" = ""; then
- AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->readCount = 0;],
- rb_cv_fcnt="readCount", )
-fi
-dnl for emx0.9c
-if test "$rb_cv_fcnt" = ""; then
- AC_TRY_COMPILE([#include <stdio.h>],
- [FILE *f = stdin; f->_rcount = 0;],
- rb_cv_fcnt="_rcount", rb_cv_fcnt="not found")
-fi])
+[for fcnt in dnl
+ _cnt dnl
+ __cnt dnl
+ _r dnl
+ readCount dnl
+ _rcount dnl for emx0.9c
+; do
+ AC_TRY_COMPILE([#include <stdio.h>
+],
+ [FILE *f = stdin; f->$fcnt = 0;],
+ rb_cv_fcnt="$fcnt"; break,
+ rb_cv_fcnt="not found")
+done])
if test "$rb_cv_fcnt" = "not found"; then
AC_MSG_RESULT([not found(OK if using GNU libc)])
else
@@ -483,6 +475,48 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi
+AC_MSG_CHECKING(read buffer ptr field in FILE structures)
+AC_CACHE_VAL(rb_cv_frptr,
+[for frptr in dnl
+ _IO_read_ptr dnl
+ _ptr dnl
+ __ptr dnl
+ bufpos dnl
+; do
+ AC_TRY_COMPILE([#include <stdio.h>
+],
+ [FILE *f = stdin; char buf[256]; f->$frptr = buf;],
+ rb_cv_frptr="$frptr"; break,
+ rb_cv_frptr="not found")
+done])
+if test "$rb_cv_frptr" = "not found"; then
+ AC_MSG_RESULT([not found])
+else
+ AC_MSG_RESULT($rb_cv_frptr)
+ AC_DEFINE_UNQUOTED(FILE_READPTR, $rb_cv_frptr)
+
+ if test "$rb_cv_fcnt" = "not found"; then
+ AC_MSG_CHECKING(read buffer end field in FILE structures)
+ AC_CACHE_VAL(rb_cv_frend,
+ [for frend in dnl
+ _IO_read_end dnl
+ bufend dnl
+ ; do
+ AC_TRY_COMPILE([#include <stdio.h>
+ ],
+ [FILE *f = stdin; char buf[256]; f->$frend = buf;],
+ rb_cv_frend="$frend"; break,
+ rb_cv_frend="not found")
+ done])
+ if test "$rb_cv_frend" = "not found"; then
+ AC_MSG_RESULT([not found])
+ else
+ AC_MSG_RESULT($rb_cv_frend)
+ AC_DEFINE_UNQUOTED(FILE_READEND, $rb_cv_frend)
+ fi
+ fi
+fi
+
dnl default value for $KANJI
DEFAULT_KCODE="KCODE_NONE"
diff --git a/io.c b/io.c
index b7c14ec565..1b5221d1ee 100644
--- a/io.c
+++ b/io.c
@@ -125,17 +125,24 @@ static VALUE lineno;
# ifdef _IO_fpos_t
# define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
# define READ_DATA_PENDING_COUNT(fp) ((fp)->_IO_read_end - (fp)->_IO_read_ptr)
+# define READ_DATA_PENDING_PTR(fp) ((fp)->_IO_read_ptr)
# else
# define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
# define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr)
+# define READ_DATA_PENDING_PTR(fp) ((fp)->_gptr)
# endif
#elif defined(FILE_COUNT)
# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
# define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_COUNT)
+#elif defined(FILE_READEND)
+# define READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
+# define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_READEND - (fp)->FILE_READPTR)
#elif defined(__BEOS__)
# define READ_DATA_PENDING(fp) (fp->_state._eof == 0)
#elif defined(__UCLIBC__)
# define READ_DATA_PENDING(fp) ((fp)->bufpos < (fp)->bufend)
+# define READ_DATA_PENDING_COUNT(fp) ((fp)->bufend - (fp)->bufpos)
+# define READ_DATA_PENDING_PTR(fp) ((fp)->bufpos)
#elif defined(__VMS)
# define READ_DATA_PENDING(fp) (((unsigned int)((*(fp))->_flag) & _IOEOF) == 0)
#else
@@ -143,6 +150,11 @@ static VALUE lineno;
extern int ReadDataPending();
# define READ_DATA_PENDING(fp) ReadDataPending(fp)
#endif
+#ifndef READ_DATA_PENDING_PTR
+# ifdef FILE_READPTR
+# define READ_DATA_PENDING_PTR(fp) ((fp)->FILE_READPTR)
+# endif
+#endif
#define READ_CHECK(fp) do {\
if (!READ_DATA_PENDING(fp)) {\
@@ -605,21 +617,16 @@ io_fread(ptr, len, f)
#define SMALLBUF 100
-static VALUE
-read_all(port)
- VALUE port;
-{
+static long
+remain_size(fptr)
OpenFile *fptr;
- VALUE str = Qnil;
+{
struct stat st;
off_t siz = BUFSIZ;
long bytes = 0;
int n;
- GetOpenFile(port, fptr);
- rb_io_check_readable(fptr);
-
- if (feof(fptr->f)) return Qnil;
+ if (feof(fptr->f)) return 0;
if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
#ifdef __BEOS__
&& (st.st_dev > 3)
@@ -629,12 +636,7 @@ read_all(port)
off_t pos;
if (st.st_size == 0) {
- int c = getc(fptr->f);
-
- if (c == EOF) {
- return rb_str_new(0, 0);
- }
- ungetc(c, fptr->f);
+ return 1; /* force EOF */
}
pos = ftello(fptr->f);
if (st.st_size > pos && pos >= 0) {
@@ -644,8 +646,22 @@ read_all(port)
}
}
}
- str = rb_tainted_str_new(0, (long)siz);
+ return (long)siz;
+}
+
+static VALUE
+read_all(fptr, siz)
+ OpenFile *fptr;
+ long siz;
+{
+ VALUE str;
+ long bytes = 0;
+ int n;
+
+ if (feof(fptr->f)) return Qnil;
READ_CHECK(fptr->f);
+ if (!siz) siz = BUFSIZ;
+ str = rb_tainted_str_new(0, siz);
for (;;) {
n = io_fread(RSTRING(str)->ptr+bytes, (long)siz-bytes, fptr->f);
if (n == 0 && bytes == 0) {
@@ -674,16 +690,17 @@ io_read(argc, argv, io)
VALUE length, str;
rb_scan_args(argc, argv, "01", &length);
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
if (NIL_P(length)) {
- return read_all(io);
+ return read_all(fptr, remain_size(fptr));
}
len = NUM2INT(length);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %d given", len);
}
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
if (feof(fptr->f)) return Qnil;
str = rb_str_new(0, len);
@@ -702,22 +719,47 @@ io_read(argc, argv, io)
return str;
}
-static VALUE
-rb_io_getline_fast(fptr)
+static int
+appendline(fptr, delim, strp)
OpenFile *fptr;
+ int delim;
+ VALUE *strp;
{
FILE *f = fptr->f;
- VALUE str = Qnil;
- int c;
+ VALUE str = *strp;
+ int c = EOF;
+#ifndef READ_DATA_PENDING_PTR
char buf[8192];
- char *bp, *bpe = buf + sizeof buf - 3;
+ char *bp = buf, *bpe = buf + sizeof buf - 3;
int cnt;
- int append = 0;
+#endif
- again:
- bp = buf;
- for (;;) {
+ do {
+#ifdef READ_DATA_PENDING_PTR
+ int pending = READ_DATA_PENDING_COUNT(f);
+ if (pending > 0) {
+ const char *p = READ_DATA_PENDING_PTR(f);
+ const char *e = memchr(p, delim, pending);
+ long last = 0;
+ if (e) pending = e - p + 1;
+ if (!NIL_P(str)) {
+ last = RSTRING(str)->len;
+ rb_str_resize(str, last + (c != EOF) + pending);
+ }
+ else {
+ *strp = str = rb_str_new(0, (c != EOF) + pending);
+ }
+ if (c != EOF) {
+ RSTRING(str)->ptr[last++] = c;
+ }
+ fread(RSTRING(str)->ptr + last, 1, pending, f); /* must not fail */
+ if (e) return delim;
+ }
+ rb_thread_wait_fd(fileno(f));
+ rb_io_check_closed(fptr);
+#else
READ_CHECK(f);
+#endif
TRAP_BEG;
c = getc(f);
TRAP_END;
@@ -726,29 +768,86 @@ rb_io_getline_fast(fptr)
if (errno == EINTR) continue;
rb_sys_fail(fptr->path);
}
- break;
+ return c;
}
- if ((*bp++ = c) == '\n') break;
- if (bp == bpe) break;
- }
- cnt = bp - buf;
+#ifndef READ_DATA_PENDING_PTR
+ if ((*bp++ = c) == delim || bp == bpe) {
+ cnt = bp - buf;
- if (c == EOF && !append && cnt == 0) {
- str = Qnil;
- goto return_gets;
+ if (cnt > 0) {
+ if (!NIL_P(str))
+ rb_str_cat(str, buf, cnt);
+ else
+ *strp = str = rb_str_new(buf, cnt);
+ }
+ bp = buf;
+ }
+#endif
+ } while (c != delim);
+
+#ifdef READ_DATA_PENDING_PTR
+ {
+ char ch = c;
+ if (!NIL_P(str)) {
+ rb_str_cat(str, &ch, 1);
+ }
+ else {
+ *strp = str = rb_str_new(&ch, 1);
+ }
}
+#endif
- if (append)
- rb_str_cat(str, buf, cnt);
- else
- str = rb_str_new(buf, cnt);
+ return c;
+}
- if (c != EOF && RSTRING(str)->ptr[RSTRING(str)->len-1] != '\n') {
- append = 1;
- goto again;
- }
+static inline int
+swallow(fptr, term)
+ OpenFile *fptr;
+ int term;
+{
+ FILE *f = fptr->f;
+ int c;
+
+ do {
+#ifdef READ_DATA_PENDING_PTR
+ int cnt;
+ while ((cnt = READ_DATA_PENDING_COUNT(f)) > 0) {
+ char buf[1024];
+ const char *p = READ_DATA_PENDING_PTR(f);
+ int i;
+ if (cnt > sizeof buf) cnt = sizeof buf;
+ if (*p != term) return Qtrue;
+ i = cnt;
+ while (--i && *++p == term);
+ if (!fread(buf, 1, cnt - i, f)) /* must not fail */
+ rb_sys_fail(fptr->path);
+ }
+ rb_thread_wait_fd(fileno(f));
+ rb_io_check_closed(fptr);
+#else
+ READ_CHECK(f);
+#endif
+ TRAP_BEG;
+ c = getc(f);
+ TRAP_END;
+ if (c != term) {
+ ungetc(c, f);
+ return Qtrue;
+ }
+ } while (c != EOF);
+ return Qfalse;
+}
+
+static VALUE
+rb_io_getline_fast(fptr, delim)
+ OpenFile *fptr;
+ int delim;
+{
+ VALUE str = Qnil;
+ int c;
+
+ while ((c = appendline(fptr, delim, &str)) != EOF && c != delim);
- return_gets:
if (!NIL_P(str)) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
@@ -763,118 +862,42 @@ rb_io_getline(rs, fptr)
VALUE rs;
OpenFile *fptr;
{
- FILE *f;
VALUE str = Qnil;
- int c, newline;
- char *rsptr;
- int rslen, rspara = 0;
if (NIL_P(rs)) {
- rsptr = 0;
- rslen = 0;
+ str = read_all(fptr, 0);
}
else if (rs == rb_default_rs) {
- return rb_io_getline_fast(fptr);
+ return rb_io_getline_fast(fptr, '\n');
}
else {
+ int c, newline;
+ char *rsptr;
+ int rslen, rspara = 0;
+
StringValue(rs);
rslen = RSTRING(rs)->len;
if (rslen == 0) {
rsptr = "\n\n";
rslen = 2;
rspara = 1;
+ swallow(fptr, '\n');
}
- else if (rslen == 1 && RSTRING(rs)->ptr[0] == '\n') {
- return rb_io_getline_fast(fptr);
+ else if (rslen == 1) {
+ return rb_io_getline_fast(fptr, RSTRING(rs)->ptr[0]);
}
else {
rsptr = RSTRING(rs)->ptr;
}
- }
-
- f = fptr->f;
- if (rspara) {
- do {
- READ_CHECK(f);
- TRAP_BEG;
- c = getc(f);
- TRAP_END;
- if (c != '\n') {
- ungetc(c,f);
- break;
- }
- } while (c != EOF);
- }
-
- newline = rslen ? rsptr[rslen - 1] : 0777;
- {
- char buf[8192];
- char *bp, *bpe = buf + sizeof buf - 3;
- int cnt;
- int append = 0;
-
- again:
- bp = buf;
-
- if (rslen) {
- for (;;) {
- READ_CHECK(f);
- TRAP_BEG;
- c = getc(f);
- TRAP_END;
- if (c == EOF) {
- if (ferror(f)) {
- if (errno == EINTR) continue;
- rb_sys_fail(fptr->path);
- }
- break;
- }
- if ((*bp++ = c) == newline) break;
- if (bp == bpe) break;
- }
- cnt = bp - buf;
- }
- else {
- READ_CHECK(f);
- cnt = io_fread(buf, sizeof(buf), f);
- if (cnt == 0) {
- if (ferror(f)) rb_sys_fail(fptr->path);
- c = EOF;
- }
- else {
- c = 0;
- }
- }
+ newline = rsptr[rslen - 1];
- if (c == EOF && !append && cnt == 0) {
- str = Qnil;
- goto return_gets;
- }
-
- if (append)
- rb_str_cat(str, buf, cnt);
- else
- str = rb_str_new(buf, cnt);
-
- if (c != EOF &&
- (!rslen ||
- RSTRING(str)->len < rslen ||
- memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen))) {
- append = 1;
- goto again;
- }
- }
+ while ((c = appendline(fptr, newline, &str)) != EOF &&
+ (c != newline || RSTRING(str)->len < rslen ||
+ memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen)));
- return_gets:
- if (rspara) {
- while (c != EOF) {
- READ_CHECK(f);
- TRAP_BEG;
- c = getc(f);
- TRAP_END;
- if (c != '\n') {
- ungetc(c, f);
- break;
+ if (rspara) {
+ if (c != EOF) {
+ swallow(fptr, '\n');
}
}
}
@@ -896,7 +919,7 @@ rb_io_gets(io)
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- return rb_io_getline_fast(fptr);
+ return rb_io_getline_fast(fptr, '\n');
}
static VALUE
@@ -2871,11 +2894,14 @@ rb_f_backquote(obj, str)
VALUE obj, str;
{
VALUE port, result;
+ OpenFile *fptr;
SafeStringValue(str);
port = pipe_open(RSTRING(str)->ptr, "r");
if (NIL_P(port)) return rb_str_new(0,0);
- result = read_all(port);
+
+ GetOpenFile(port, fptr);
+ result = read_all(fptr, remain_size(fptr));
rb_io_close(port);