1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2276 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2002-03-25 14:50:40 +00:00
parent 45ca4d69aa
commit dfaf41d759
3 changed files with 239 additions and 161 deletions

View file

@ -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> Mon Mar 25 19:30:25 2002 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/extmk.rb.in (arg_config): get rid of single quotes * ext/extmk.rb.in (arg_config): get rid of single quotes

View file

@ -453,29 +453,21 @@ else
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y)) AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
fi 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_CACHE_VAL(rb_cv_fcnt,
[AC_TRY_COMPILE([#include <stdio.h>], [for fcnt in dnl
[FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", ) _cnt dnl
if test "$rb_cv_fcnt" = ""; then __cnt dnl
AC_TRY_COMPILE([#include <stdio.h>], _r dnl
[FILE *f = stdin; f->__cnt = 0;], rb_cv_fcnt="__cnt", ) readCount dnl
fi _rcount dnl for emx0.9c
if test "$rb_cv_fcnt" = ""; then ; do
AC_TRY_COMPILE([#include <stdio.h>], AC_TRY_COMPILE([#include <stdio.h>
[FILE *f = stdin; f->_r = 0;], rb_cv_fcnt="_r", ) ],
fi [FILE *f = stdin; f->$fcnt = 0;],
if test "$rb_cv_fcnt" = ""; then rb_cv_fcnt="$fcnt"; break,
AC_TRY_COMPILE([#include <stdio.h>], rb_cv_fcnt="not found")
[FILE *f = stdin; f->readCount = 0;], done])
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])
if test "$rb_cv_fcnt" = "not found"; then if test "$rb_cv_fcnt" = "not found"; then
AC_MSG_RESULT([not found(OK if using GNU libc)]) AC_MSG_RESULT([not found(OK if using GNU libc)])
else else
@ -483,6 +475,48 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt) AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi 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 dnl default value for $KANJI
DEFAULT_KCODE="KCODE_NONE" DEFAULT_KCODE="KCODE_NONE"

304
io.c
View file

@ -125,17 +125,24 @@ static VALUE lineno;
# ifdef _IO_fpos_t # ifdef _IO_fpos_t
# define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end) # 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_COUNT(fp) ((fp)->_IO_read_end - (fp)->_IO_read_ptr)
# define READ_DATA_PENDING_PTR(fp) ((fp)->_IO_read_ptr)
# else # else
# define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr) # define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
# define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr) # define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr)
# define READ_DATA_PENDING_PTR(fp) ((fp)->_gptr)
# endif # endif
#elif defined(FILE_COUNT) #elif defined(FILE_COUNT)
# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0) # define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
# define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_COUNT) # 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__) #elif defined(__BEOS__)
# define READ_DATA_PENDING(fp) (fp->_state._eof == 0) # define READ_DATA_PENDING(fp) (fp->_state._eof == 0)
#elif defined(__UCLIBC__) #elif defined(__UCLIBC__)
# define READ_DATA_PENDING(fp) ((fp)->bufpos < (fp)->bufend) # 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) #elif defined(__VMS)
# define READ_DATA_PENDING(fp) (((unsigned int)((*(fp))->_flag) & _IOEOF) == 0) # define READ_DATA_PENDING(fp) (((unsigned int)((*(fp))->_flag) & _IOEOF) == 0)
#else #else
@ -143,6 +150,11 @@ static VALUE lineno;
extern int ReadDataPending(); extern int ReadDataPending();
# define READ_DATA_PENDING(fp) ReadDataPending(fp) # define READ_DATA_PENDING(fp) ReadDataPending(fp)
#endif #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 {\ #define READ_CHECK(fp) do {\
if (!READ_DATA_PENDING(fp)) {\ if (!READ_DATA_PENDING(fp)) {\
@ -605,21 +617,16 @@ io_fread(ptr, len, f)
#define SMALLBUF 100 #define SMALLBUF 100
static VALUE static long
read_all(port) remain_size(fptr)
VALUE port;
{
OpenFile *fptr; OpenFile *fptr;
VALUE str = Qnil; {
struct stat st; struct stat st;
off_t siz = BUFSIZ; off_t siz = BUFSIZ;
long bytes = 0; long bytes = 0;
int n; int n;
GetOpenFile(port, fptr); if (feof(fptr->f)) return 0;
rb_io_check_readable(fptr);
if (feof(fptr->f)) return Qnil;
if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode) if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
#ifdef __BEOS__ #ifdef __BEOS__
&& (st.st_dev > 3) && (st.st_dev > 3)
@ -629,12 +636,7 @@ read_all(port)
off_t pos; off_t pos;
if (st.st_size == 0) { if (st.st_size == 0) {
int c = getc(fptr->f); return 1; /* force EOF */
if (c == EOF) {
return rb_str_new(0, 0);
}
ungetc(c, fptr->f);
} }
pos = ftello(fptr->f); pos = ftello(fptr->f);
if (st.st_size > pos && pos >= 0) { 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); READ_CHECK(fptr->f);
if (!siz) siz = BUFSIZ;
str = rb_tainted_str_new(0, siz);
for (;;) { for (;;) {
n = io_fread(RSTRING(str)->ptr+bytes, (long)siz-bytes, fptr->f); n = io_fread(RSTRING(str)->ptr+bytes, (long)siz-bytes, fptr->f);
if (n == 0 && bytes == 0) { if (n == 0 && bytes == 0) {
@ -674,16 +690,17 @@ io_read(argc, argv, io)
VALUE length, str; VALUE length, str;
rb_scan_args(argc, argv, "01", &length); rb_scan_args(argc, argv, "01", &length);
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (NIL_P(length)) { if (NIL_P(length)) {
return read_all(io); return read_all(fptr, remain_size(fptr));
} }
len = NUM2INT(length); len = NUM2INT(length);
if (len < 0) { if (len < 0) {
rb_raise(rb_eArgError, "negative length %d given", len); rb_raise(rb_eArgError, "negative length %d given", len);
} }
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (feof(fptr->f)) return Qnil; if (feof(fptr->f)) return Qnil;
str = rb_str_new(0, len); str = rb_str_new(0, len);
@ -702,22 +719,47 @@ io_read(argc, argv, io)
return str; return str;
} }
static VALUE static int
rb_io_getline_fast(fptr) appendline(fptr, delim, strp)
OpenFile *fptr; OpenFile *fptr;
int delim;
VALUE *strp;
{ {
FILE *f = fptr->f; FILE *f = fptr->f;
VALUE str = Qnil; VALUE str = *strp;
int c; int c = EOF;
#ifndef READ_DATA_PENDING_PTR
char buf[8192]; char buf[8192];
char *bp, *bpe = buf + sizeof buf - 3; char *bp = buf, *bpe = buf + sizeof buf - 3;
int cnt; int cnt;
int append = 0; #endif
again: do {
bp = buf; #ifdef READ_DATA_PENDING_PTR
for (;;) { 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); READ_CHECK(f);
#endif
TRAP_BEG; TRAP_BEG;
c = getc(f); c = getc(f);
TRAP_END; TRAP_END;
@ -726,29 +768,86 @@ rb_io_getline_fast(fptr)
if (errno == EINTR) continue; if (errno == EINTR) continue;
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
} }
break; return c;
}
#ifndef READ_DATA_PENDING_PTR
if ((*bp++ = c) == delim || bp == bpe) {
cnt = bp - buf;
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);
} }
if ((*bp++ = c) == '\n') break;
if (bp == bpe) break;
} }
cnt = bp - buf; #endif
if (c == EOF && !append && cnt == 0) { return c;
str = Qnil; }
goto return_gets;
}
if (append) static inline int
rb_str_cat(str, buf, cnt); swallow(fptr, term)
else OpenFile *fptr;
str = rb_str_new(buf, cnt); int term;
{
FILE *f = fptr->f;
int c;
if (c != EOF && RSTRING(str)->ptr[RSTRING(str)->len-1] != '\n') { do {
append = 1; #ifdef READ_DATA_PENDING_PTR
goto again; 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)) { if (!NIL_P(str)) {
fptr->lineno++; fptr->lineno++;
lineno = INT2FIX(fptr->lineno); lineno = INT2FIX(fptr->lineno);
@ -763,118 +862,42 @@ rb_io_getline(rs, fptr)
VALUE rs; VALUE rs;
OpenFile *fptr; OpenFile *fptr;
{ {
FILE *f;
VALUE str = Qnil; VALUE str = Qnil;
int c, newline;
char *rsptr;
int rslen, rspara = 0;
if (NIL_P(rs)) { if (NIL_P(rs)) {
rsptr = 0; str = read_all(fptr, 0);
rslen = 0;
} }
else if (rs == rb_default_rs) { else if (rs == rb_default_rs) {
return rb_io_getline_fast(fptr); return rb_io_getline_fast(fptr, '\n');
} }
else { else {
int c, newline;
char *rsptr;
int rslen, rspara = 0;
StringValue(rs); StringValue(rs);
rslen = RSTRING(rs)->len; rslen = RSTRING(rs)->len;
if (rslen == 0) { if (rslen == 0) {
rsptr = "\n\n"; rsptr = "\n\n";
rslen = 2; rslen = 2;
rspara = 1; rspara = 1;
swallow(fptr, '\n');
} }
else if (rslen == 1 && RSTRING(rs)->ptr[0] == '\n') { else if (rslen == 1) {
return rb_io_getline_fast(fptr); return rb_io_getline_fast(fptr, RSTRING(rs)->ptr[0]);
} }
else { else {
rsptr = RSTRING(rs)->ptr; rsptr = RSTRING(rs)->ptr;
} }
} newline = rsptr[rslen - 1];
f = fptr->f; while ((c = appendline(fptr, newline, &str)) != EOF &&
if (rspara) { (c != newline || RSTRING(str)->len < rslen ||
do { memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen)));
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; if (rspara) {
{ if (c != EOF) {
char buf[8192]; swallow(fptr, '\n');
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;
}
}
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;
}
}
return_gets:
if (rspara) {
while (c != EOF) {
READ_CHECK(f);
TRAP_BEG;
c = getc(f);
TRAP_END;
if (c != '\n') {
ungetc(c, f);
break;
} }
} }
} }
@ -896,7 +919,7 @@ rb_io_gets(io)
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
rb_io_check_readable(fptr); rb_io_check_readable(fptr);
return rb_io_getline_fast(fptr); return rb_io_getline_fast(fptr, '\n');
} }
static VALUE static VALUE
@ -2871,11 +2894,14 @@ rb_f_backquote(obj, str)
VALUE obj, str; VALUE obj, str;
{ {
VALUE port, result; VALUE port, result;
OpenFile *fptr;
SafeStringValue(str); SafeStringValue(str);
port = pipe_open(RSTRING(str)->ptr, "r"); port = pipe_open(RSTRING(str)->ptr, "r");
if (NIL_P(port)) return rb_str_new(0,0); 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); rb_io_close(port);