From 4aa9be0f5c8d9135a9f67aa96c1667e017cdc587 Mon Sep 17 00:00:00 2001 From: yugui Date: Fri, 28 Mar 2008 10:58:31 +0000 Subject: * io.c (rb_io_each_char, rb_io_chars, argf_each_char, io_getc): Added character-wise iterators; IO#each_char, IO#chars, ARGF#each_char. [ruby-dev:34052] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- io.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 35 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index a3a06cb837..d19392bf8e 100644 --- a/io.c +++ b/io.c @@ -2227,6 +2227,77 @@ rb_io_each_byte(VALUE io) return io; } +static VALUE +io_getc(rb_io_t *fptr, rb_encoding *enc) +{ + int r, n; + VALUE str; + + if (io_fillbuf(fptr) < 0) { + return Qnil; + } + r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off, fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc); + if (MBCLEN_CHARFOUND_P(r) && + (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) { + str = rb_str_new(fptr->rbuf+fptr->rbuf_off, n); + fptr->rbuf_off += n; + fptr->rbuf_len -= n; + } + else if (MBCLEN_NEEDMORE_P(r)) { + str = rb_str_new(fptr->rbuf+fptr->rbuf_off, fptr->rbuf_len); + fptr->rbuf_len = 0; + getc_needmore: + if (io_fillbuf(fptr) != -1) { + rb_str_cat(str, fptr->rbuf+fptr->rbuf_off, 1); + fptr->rbuf_off++; + fptr->rbuf_len--; + r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc); + if (MBCLEN_NEEDMORE_P(r)) { + goto getc_needmore; + } + } + } + else { + str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1); + fptr->rbuf_off++; + fptr->rbuf_len--; + } + 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 @@ -2240,9 +2311,9 @@ rb_io_each_byte(VALUE io) */ static VALUE -rb_io_lines(int argc, VALUE *argv, VALUE str) +rb_io_lines(int argc, VALUE *argv, VALUE io) { - return rb_enumeratorize(str, ID2SYM(rb_intern("each_line")), argc, argv); + return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv); } /* @@ -2255,9 +2326,27 @@ rb_io_lines(int argc, VALUE *argv, VALUE str) */ static VALUE -rb_io_bytes(VALUE str) +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(str, ID2SYM(rb_intern("each_byte")), 0, 0); + return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0); } /* @@ -2285,38 +2374,8 @@ rb_io_getc(VALUE io) enc = io_input_encoding(fptr); READ_CHECK(fptr); - if (io_fillbuf(fptr) < 0) { - return Qnil; - } - r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off, fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc); - if (MBCLEN_CHARFOUND_P(r) && - (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) { - str = rb_str_new(fptr->rbuf+fptr->rbuf_off, n); - fptr->rbuf_off += n; - fptr->rbuf_len -= n; - } - else if (MBCLEN_NEEDMORE_P(r)) { - str = rb_str_new(fptr->rbuf+fptr->rbuf_off, fptr->rbuf_len); - fptr->rbuf_len = 0; - getc_needmore: - if (io_fillbuf(fptr) != -1) { - rb_str_cat(str, fptr->rbuf+fptr->rbuf_off, 1); - fptr->rbuf_off++; - fptr->rbuf_len--; - r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc); - if (MBCLEN_NEEDMORE_P(r)) { - goto getc_needmore; - } - } - } - else { - str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1); - fptr->rbuf_off++; - fptr->rbuf_len--; - } - return io_enc_str(str, 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); -- cgit v1.2.3