ruby-changes:4355
From: ko1@a...
Date: Fri, 28 Mar 2008 19:58:44 +0900 (JST)
Subject: [ruby-changes:4355] yugui - Ruby:r15845 (trunk): * io.c (rb_io_each_char, rb_io_chars, argf_each_char, io_getc): Added character-wise
yugui 2008-03-28 19:58:31 +0900 (Fri, 28 Mar 2008)
New Revision: 15845
Modified files:
trunk/io.c
Log:
* 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]
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/io.c?r1=15845&r2=15844&diff_format=u
Index: io.c
===================================================================
--- io.c (revision 15844)
+++ io.c (revision 15845)
@@ -2227,8 +2227,79 @@
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 <em>ios</em>,
+ * passing the character as an argument. The stream must be opened for
+ * reading or an <code>IOError</code> will be raised.
+ *
+ * f = File.new("testfile")
+ * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
+ */
+
+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
@@ -2240,9 +2311,9 @@
*/
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,13 +2326,31 @@
*/
static VALUE
-rb_io_bytes(VALUE str)
+rb_io_bytes(VALUE io)
{
- return rb_enumeratorize(str, ID2SYM(rb_intern("each_byte")), 0, 0);
+ return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
}
/*
* call-seq:
+ * ios.chars => anEnumerator
+ *
+ * Returns an enumerator that gives each character in <em>ios</em>.
+ * The stream must be opened for reading or an <code>IOError</code>
+ * 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 <em>ios</em>. Returns
@@ -2285,38 +2374,8 @@
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)
{
@@ -6535,6 +6594,17 @@
}
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)
{
next_argv();
@@ -6831,8 +6901,10 @@
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 @@
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);
--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/