diff --git a/io.c b/io.c index a3a06cb837..d19392bf8e 100644 --- a/io.c +++ b/io.c @@ -2227,64 +2227,12 @@ rb_io_each_byte(VALUE io) return io; } -/* - * call-seq: - * str.lines(sep=$/) => anEnumerator - * str.lines(limit) => anEnumerator - * str.lines(sep, limit) => anEnumerator - * - * Returns an enumerator that gives each line in the string. - * - * "foo\nbar\n".lines.to_a #=> ["foo\n", "bar\n"] - * "foo\nb ar".lines.sort #=> ["b ar", "foo\n"] - */ - -static VALUE -rb_io_lines(int argc, VALUE *argv, VALUE str) +static VALUE +io_getc(rb_io_t *fptr, rb_encoding *enc) { - return rb_enumeratorize(str, ID2SYM(rb_intern("each_line")), argc, argv); -} - -/* - * call-seq: - * str.bytes => anEnumerator - * - * Returns an enumerator that gives each byte in the string. - * - * "hello".bytes.to_a #=> [104, 101, 108, 108, 111] - */ - -static VALUE -rb_io_bytes(VALUE str) -{ - return rb_enumeratorize(str, ID2SYM(rb_intern("each_byte")), 0, 0); -} - -/* - * call-seq: - * ios.getc => fixnum or nil - * - * Reads a one-character string from ios. Returns - * nil if called at end of file. - * - * f = File.new("testfile") - * f.getc #=> "8" - * f.getc #=> "1" - */ - -static VALUE -rb_io_getc(VALUE io) -{ - rb_io_t *fptr; int r, n; VALUE str; - rb_encoding *enc; - GetOpenFile(io, fptr); - rb_io_check_readable(fptr); - - enc = io_input_encoding(fptr); - READ_CHECK(fptr); if (io_fillbuf(fptr) < 0) { return Qnil; } @@ -2317,6 +2265,117 @@ rb_io_getc(VALUE io) return io_enc_str(str, fptr); } +/* + * call-seq: + * ios.each_char {|c| block } => ios + * + * Calls the given block once for each character in ios, + * passing the character as an argument. The stream must be opened for + * reading or an IOError will be raised. + * + * f = File.new("testfile") + * f.each_char {|c| print c, ' ' } #=> # + */ + +static VALUE +rb_io_each_char(VALUE io) +{ + rb_io_t *fptr; + rb_encoding *enc; + VALUE c; + + RETURN_ENUMERATOR(io, 0, 0); + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + + enc = io_input_encoding(fptr); + READ_CHECK(fptr); + while (!NIL_P(c = io_getc(fptr, enc))) { + rb_yield(c); + } + return io; +} + + + +/* + * call-seq: + * str.lines(sep=$/) => anEnumerator + * str.lines(limit) => anEnumerator + * str.lines(sep, limit) => anEnumerator + * + * Returns an enumerator that gives each line in the string. + * + * "foo\nbar\n".lines.to_a #=> ["foo\n", "bar\n"] + * "foo\nb ar".lines.sort #=> ["b ar", "foo\n"] + */ + +static VALUE +rb_io_lines(int argc, VALUE *argv, VALUE io) +{ + return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv); +} + +/* + * call-seq: + * str.bytes => anEnumerator + * + * Returns an enumerator that gives each byte in the string. + * + * "hello".bytes.to_a #=> [104, 101, 108, 108, 111] + */ + +static VALUE +rb_io_bytes(VALUE io) +{ + return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0); +} + +/* + * call-seq: + * ios.chars => anEnumerator + * + * Returns an enumerator that gives each character in ios. + * The stream must be opened for reading or an IOError + * will be raised. + * + * f = File.new("testfile) + * f.chars.each {|c| print c, ' ' } + */ + +static VALUE +rb_io_chars(VALUE io) +{ + return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0); +} + +/* + * call-seq: + * ios.getc => fixnum or nil + * + * Reads a one-character string from ios. Returns + * nil if called at end of file. + * + * f = File.new("testfile") + * f.getc #=> "8" + * f.getc #=> "1" + */ + +static VALUE +rb_io_getc(VALUE io) +{ + rb_io_t *fptr; + int r, n; + VALUE str; + rb_encoding *enc; + + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + + enc = io_input_encoding(fptr); + READ_CHECK(fptr); + return io_getc(fptr, enc); +} int rb_getc(FILE *f) { @@ -6534,6 +6593,17 @@ argf_each_byte(VALUE argf) } } +static VALUE +argf_each_char(VALUE argf) +{ + RETURN_ENUMERATOR(argf, 0, 0); + for (;;) { + if (!next_argv()) return Qnil; + rb_block_call(current_file, rb_intern("each_char"), 0, 0, rb_yield, 0); + next_p = 1; + } +} + static VALUE argf_filename(VALUE argf) { @@ -6831,8 +6901,10 @@ Init_IO(void) rb_define_method(rb_cIO, "each", rb_io_each_line, -1); rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1); rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0); + rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0); rb_define_method(rb_cIO, "lines", rb_io_lines, -1); rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0); + rb_define_method(rb_cIO, "chars", rb_io_chars, 0); rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1); rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1); @@ -6929,6 +7001,7 @@ Init_IO(void) rb_define_method(rb_cARGF, "each", argf_each_line, -1); rb_define_method(rb_cARGF, "each_line", argf_each_line, -1); rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0); + rb_define_method(rb_cARGF, "each_char", argf_each_char, 0); rb_define_method(rb_cARGF, "read", argf_read, -1); rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);