mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-io/io.c: implement IO#getline in C
This commit is contained in:
@@ -107,54 +107,6 @@ class IO
|
||||
ungetc s
|
||||
end
|
||||
|
||||
def readline(arg = "\n", limit = nil)
|
||||
case arg
|
||||
when String
|
||||
rs = arg
|
||||
when Integer
|
||||
rs = "\n"
|
||||
limit = arg
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
|
||||
if rs.nil?
|
||||
return read
|
||||
end
|
||||
|
||||
if rs == ""
|
||||
rs = "\n\n"
|
||||
end
|
||||
|
||||
array = []
|
||||
while true
|
||||
begin
|
||||
_read_buf
|
||||
rescue EOFError
|
||||
array = nil if array.empty?
|
||||
break
|
||||
end
|
||||
|
||||
if limit && limit <= @buf.size
|
||||
array.push @buf[0, limit]
|
||||
@buf[0, limit] = ""
|
||||
break
|
||||
elsif idx = @buf.index(rs)
|
||||
len = idx + rs.size
|
||||
array.push @buf[0, len]
|
||||
@buf[0, len] = ""
|
||||
break
|
||||
else
|
||||
array.push @buf
|
||||
@buf = ''
|
||||
end
|
||||
end
|
||||
|
||||
raise EOFError.new "end of file reached" if array.nil?
|
||||
|
||||
array.join
|
||||
end
|
||||
|
||||
def gets(*args)
|
||||
begin
|
||||
readline(*args)
|
||||
|
||||
+124
-10
@@ -1617,6 +1617,21 @@ io_eof(mrb_state *mrb, mrb_value io)
|
||||
return mrb_bool_value(fptr->eof);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_read_all(mrb_state *mrb, mrb_value io, mrb_value outbuf)
|
||||
{
|
||||
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
|
||||
for (;;) {
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (fptr->eof) {
|
||||
return outbuf;
|
||||
}
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
mrb_str_cat_str(mrb, outbuf, buf);
|
||||
RSTR_SET_LEN(RSTRING(buf), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_read(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
@@ -1646,15 +1661,7 @@ io_read(mrb_state *mrb, mrb_value io)
|
||||
outbuf = mrb_str_new_capa(mrb, BUF_SIZE);
|
||||
}
|
||||
if (!length_given) { /* read as much as possible */
|
||||
for (;;) {
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (fptr->eof) {
|
||||
return outbuf;
|
||||
}
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
mrb_str_cat_str(mrb, outbuf, buf);
|
||||
RSTR_SET_LEN(RSTRING(buf), 0);
|
||||
}
|
||||
return io_read_all(mrb, io, outbuf);
|
||||
}
|
||||
for (;;) {
|
||||
io_read_buf_noraise(mrb, io);
|
||||
@@ -1677,6 +1684,113 @@ io_read(mrb_state *mrb, mrb_value io)
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_readline(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value rs = mrb_nil_value();
|
||||
mrb_int limit;
|
||||
mrb_bool rs_given = FALSE; /* newline break */
|
||||
mrb_bool limit_given = FALSE; /* no limit */
|
||||
mrb_value outbuf;
|
||||
|
||||
mrb_get_args(mrb, "|o?i?", &rs, &rs_given, &limit, &limit_given);
|
||||
|
||||
if (limit_given == FALSE) {
|
||||
if (rs_given) {
|
||||
if (mrb_nil_p(rs)) {
|
||||
rs_given = FALSE;
|
||||
}
|
||||
else if (mrb_integer_p(rs)) {
|
||||
limit = mrb_integer(rs);
|
||||
limit_given = TRUE;
|
||||
rs = mrb_nil_value();
|
||||
}
|
||||
else if (!mrb_string_p(rs)) {
|
||||
mrb_ensure_int_type(mrb, rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rs_given) {
|
||||
if (mrb_nil_p(rs)) {
|
||||
rs_given = FALSE;
|
||||
}
|
||||
else {
|
||||
mrb_ensure_string_type(mrb, rs);
|
||||
if (RSTRING_LEN(rs) == 0) { /* paragraph mode */
|
||||
rs = mrb_str_new_lit(mrb, "\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
rs = mrb_str_new_lit(mrb, "\n");
|
||||
rs_given = TRUE;
|
||||
}
|
||||
/* from now on rs_given==FALSE means no RS */
|
||||
if (mrb_nil_p(rs) && !limit_given) {
|
||||
return io_read_all(mrb, io, mrb_str_new_capa(mrb, BUF_SIZE));
|
||||
}
|
||||
|
||||
if (limit_given) {
|
||||
if (limit == 0) return mrb_str_new(mrb, NULL, 0);
|
||||
outbuf = mrb_str_new_capa(mrb, limit);
|
||||
}
|
||||
else {
|
||||
outbuf = mrb_str_new(mrb, NULL, 0);
|
||||
}
|
||||
|
||||
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
io_read_buf(mrb, io);
|
||||
|
||||
if (!rs_given) { /* no RS; only limit */
|
||||
mrb_assert(limit_given);
|
||||
for (;;) {
|
||||
if (RSTRING_LEN(buf) >= limit) {
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), limit);
|
||||
io_bufshift(mrb, RSTRING(buf), limit);
|
||||
return outbuf;
|
||||
}
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), RSTRING_LEN(buf));
|
||||
limit -= RSTRING_LEN(buf);
|
||||
RSTR_SET_LEN(RSTRING(buf), 0);
|
||||
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (fptr->eof) {
|
||||
if (RSTRING_LEN(outbuf) == 0)
|
||||
mrb_raise(mrb, E_EOF_ERROR, "end of file reached");
|
||||
return outbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) { /* with RS */
|
||||
mrb_int idx = mrb_str_index(mrb, buf, RSTRING_PTR(rs), RSTRING_LEN(rs), 0);
|
||||
if (idx >= 0) { /* found */
|
||||
mrb_int n = idx+RSTRING_LEN(rs);
|
||||
if (limit_given && limit < n) {
|
||||
n = limit;
|
||||
}
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), n);
|
||||
io_bufshift(mrb, RSTRING(buf), n);
|
||||
return outbuf;
|
||||
}
|
||||
if (limit_given && RSTRING_LEN(buf) < limit) {
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), limit);
|
||||
io_bufshift(mrb, RSTRING(buf), limit);
|
||||
return outbuf;
|
||||
}
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), RSTRING_LEN(buf));
|
||||
RSTR_SET_LEN(RSTRING(buf), 0);
|
||||
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (fptr->eof) {
|
||||
if (RSTRING_LEN(outbuf) == 0)
|
||||
mrb_raise(mrb, E_EOF_ERROR, "end of file reached");
|
||||
return outbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_readchar(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
@@ -1751,6 +1865,7 @@ mrb_init_io(mrb_state *mrb)
|
||||
mrb_define_method(mrb, io, "isatty", io_isatty, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, io, "eof?", io_eof, MRB_ARGS_NONE()); /* 15.2.20.5.6 */
|
||||
mrb_define_method(mrb, io, "read", io_read, MRB_ARGS_OPT(2)); /* 15.2.20.5.14 */
|
||||
mrb_define_method(mrb, io, "readline", io_readline, MRB_ARGS_OPT(2)); /* 15.2.20.5.16 */
|
||||
mrb_define_method(mrb, io, "sync", io_sync, MRB_ARGS_NONE()); /* 15.2.20.5.18 */
|
||||
mrb_define_method(mrb, io, "sync=", io_set_sync, MRB_ARGS_REQ(1)); /* 15.2.20.5.19 */
|
||||
mrb_define_method(mrb, io, "sysread", io_sysread, MRB_ARGS_ARG(1,1));
|
||||
@@ -1777,6 +1892,5 @@ mrb_init_io(mrb_state *mrb)
|
||||
mrb_define_const_id(mrb, io, MRB_SYM(SEEK_CUR), mrb_fixnum_value(SEEK_CUR));
|
||||
mrb_define_const_id(mrb, io, MRB_SYM(SEEK_END), mrb_fixnum_value(SEEK_END));
|
||||
|
||||
mrb_define_method(mrb, io, "_read_buf", io_read_buf, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, io, "_bufread", io_bufread_m, MRB_ARGS_REQ(2));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user