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>
* 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))
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"

304
io.c
View file

@ -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;
}
#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) {
str = Qnil;
goto return_gets;
}
return c;
}
if (append)
rb_str_cat(str, buf, cnt);
else
str = rb_str_new(buf, cnt);
static inline int
swallow(fptr, term)
OpenFile *fptr;
int term;
{
FILE *f = fptr->f;
int c;
if (c != EOF && RSTRING(str)->ptr[RSTRING(str)->len-1] != '\n') {
append = 1;
goto again;
}
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;
}
}
newline = rsptr[rslen - 1];
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);
}
while ((c = appendline(fptr, newline, &str)) != EOF &&
(c != newline || RSTRING(str)->len < rslen ||
memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen)));
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;
}
}
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;
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);