mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-io/io.c: implement IO#read in C
This commit is contained in:
@@ -107,47 +107,6 @@ class IO
|
||||
ungetc s
|
||||
end
|
||||
|
||||
def read(length = nil, outbuf = "")
|
||||
unless length.nil?
|
||||
unless length.is_a? Integer
|
||||
raise TypeError.new "can't convert #{length.class} into Integer"
|
||||
end
|
||||
if length < 0
|
||||
raise ArgumentError.new "negative length: #{length} given"
|
||||
end
|
||||
if length == 0
|
||||
return "" # easy case
|
||||
end
|
||||
end
|
||||
|
||||
array = []
|
||||
while true
|
||||
begin
|
||||
_read_buf
|
||||
rescue EOFError
|
||||
array = nil if array.empty? and (not length.nil?) and length != 0
|
||||
break
|
||||
end
|
||||
|
||||
if length
|
||||
consume = (length <= @buf.bytesize) ? length : @buf.bytesize
|
||||
array.push IO._bufread(@buf, consume)
|
||||
length -= consume
|
||||
break if length == 0
|
||||
else
|
||||
array.push @buf
|
||||
@buf = ''
|
||||
end
|
||||
end
|
||||
|
||||
if array.nil?
|
||||
outbuf.replace("")
|
||||
nil
|
||||
else
|
||||
outbuf.replace(array.join)
|
||||
end
|
||||
end
|
||||
|
||||
def readline(arg = "\n", limit = nil)
|
||||
case arg
|
||||
when String
|
||||
|
||||
@@ -1597,17 +1597,86 @@ io_read_buf(mrb_state *mrb, mrb_value io)
|
||||
return io_read_common(mrb, sysread, io, buf, BUF_SIZE, 0, 1);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_read_buf_noraise(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb->c->ci->mid = 0;
|
||||
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
if (RSTRING_LEN(buf) > 0) return buf;
|
||||
return io_read_common(mrb, sysread, io, buf, BUF_SIZE, 0, 0);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_eof(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
if (RSTRING_LEN(buf) > 0) return mrb_false_value();
|
||||
io_read_common(mrb, sysread, io, buf, BUF_SIZE, 0, 0);
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (RSTRING_LEN(buf) > 0) return mrb_false_value();
|
||||
return mrb_bool_value(fptr->eof);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_read(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value outbuf = mrb_nil_value();
|
||||
mrb_value len;
|
||||
mrb_int length = 0;
|
||||
mrb_bool length_given;
|
||||
struct mrb_io *fptr = io_get_read_fptr(mrb, io);
|
||||
|
||||
mrb_get_args(mrb, "|o?S", &len, &length_given, &outbuf);
|
||||
if (length_given) {
|
||||
if (mrb_nil_p(len)) {
|
||||
length_given = FALSE;
|
||||
}
|
||||
else {
|
||||
length = mrb_as_int(mrb, len);
|
||||
if (length < 0) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative length %d given", length);
|
||||
}
|
||||
if (length == 0) {
|
||||
return mrb_str_new(mrb, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mrb_nil_p(outbuf)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
io_read_buf_noraise(mrb, io);
|
||||
if (fptr->eof || length == 0) {
|
||||
if (RSTRING_LEN(outbuf) == 0)
|
||||
return mrb_nil_value();
|
||||
return outbuf;
|
||||
}
|
||||
mrb_value buf = io_buf(mrb, io);
|
||||
if (RSTRING_LEN(buf) < length) {
|
||||
mrb_str_cat_str(mrb, outbuf, buf);
|
||||
length -= RSTRING_LEN(buf);
|
||||
RSTR_SET_LEN(RSTRING(buf), 0);
|
||||
}
|
||||
else {
|
||||
mrb_str_cat(mrb, outbuf, RSTRING_PTR(buf), length);
|
||||
io_bufshift(mrb, RSTRING(buf), length);
|
||||
return outbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_readchar(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
@@ -1681,6 +1750,7 @@ mrb_init_io(mrb_state *mrb)
|
||||
mrb_define_method(mrb, io, "initialize_copy", io_init_copy, MRB_ARGS_REQ(1));
|
||||
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, "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));
|
||||
|
||||
Reference in New Issue
Block a user