aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-18 14:28:45 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-18 14:28:45 +0000
commit1b821cb4a32b40ba6392abbba6c941aceb47e54d (patch)
tree973b6a8ef59603393a166b6248f1edcb93409f35 /io.c
parente32e9a06e4e05dbe38ae8d42af55db3fd1899469 (diff)
downloadruby-1b821cb4a32b40ba6392abbba6c941aceb47e54d.tar.gz
* io.c (io_ungetbyte): renamed from io_ungetc.
(rb_io_ungetbyte): new method. (rb_io_ungetc): push back into character buffer if enc2 is set. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18694 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/io.c b/io.c
index 33b1045274..df1ae247dd 100644
--- a/io.c
+++ b/io.c
@@ -326,14 +326,10 @@ io_unread(rb_io_t *fptr)
static rb_encoding *io_input_encoding(rb_io_t *fptr);
static void
-io_ungetc(VALUE str, rb_io_t *fptr)
+io_ungetbyte(VALUE str, rb_io_t *fptr)
{
int len = RSTRING_LEN(str);
- if (rb_enc_dummy_p(io_input_encoding(fptr))) {
- rb_raise(rb_eNotImpError, "ungetc against dummy encoding is not currently supported");
- }
-
if (fptr->rbuf == NULL) {
fptr->rbuf_off = 0;
fptr->rbuf_len = 0;
@@ -344,7 +340,7 @@ io_ungetc(VALUE str, rb_io_t *fptr)
fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
}
if (fptr->rbuf_capa < len + fptr->rbuf_len) {
- rb_raise(rb_eIOError, "ungetc failed");
+ rb_raise(rb_eIOError, "ungetbyte failed");
}
if (fptr->rbuf_off < len) {
MEMMOVE(fptr->rbuf+fptr->rbuf_capa-fptr->rbuf_len,
@@ -2715,6 +2711,42 @@ rb_io_readbyte(VALUE io)
/*
* call-seq:
+ * ios.ungetbyte(string) => nil
+ * ios.ungetbyte(integer) => nil
+ *
+ * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
+ * such that a subsequent buffered read will return it. Only one byte
+ * may be pushed back before a subsequent read operation (that is,
+ * you will be able to read only the last of several bytes that have been pushed
+ * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
+ *
+ * f = File.new("testfile") #=> #<File:testfile>
+ * b = f.getbyte #=> 0x38
+ * f.ungetbyte(b) #=> nil
+ * f.getbyte #=> 0x38
+ */
+
+VALUE
+rb_io_ungetbyte(VALUE io, VALUE b)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ if (NIL_P(b)) return Qnil;
+ if (FIXNUM_P(b)) {
+ char cc = FIX2INT(b);
+ b = rb_str_new(&cc, 1);
+ }
+ else {
+ SafeStringValue(b);
+ }
+ io_ungetbyte(b, fptr);
+ return Qnil;
+}
+
+/*
+ * call-seq:
* ios.ungetc(string) => nil
*
* Pushes back one character (passed as a parameter) onto <em>ios</em>,
@@ -2733,6 +2765,7 @@ VALUE
rb_io_ungetc(VALUE io, VALUE c)
{
rb_io_t *fptr;
+ long len;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
@@ -2747,7 +2780,24 @@ rb_io_ungetc(VALUE io, VALUE c)
else {
SafeStringValue(c);
}
- io_ungetc(c, fptr);
+ if (fptr->enc2) {
+ make_readconv(fptr);
+ len = RSTRING_LEN(c);
+ if (fptr->crbuf_capa - fptr->crbuf_len < len)
+ rb_raise(rb_eIOError, "ungetc failed");
+ if (fptr->crbuf_off < len) {
+ MEMMOVE(fptr->crbuf+fptr->crbuf_capa-fptr->crbuf_len,
+ fptr->crbuf+fptr->crbuf_off,
+ char, fptr->crbuf_len);
+ fptr->crbuf_off = fptr->crbuf_capa-fptr->crbuf_len;
+ }
+ fptr->crbuf_off -= len;
+ fptr->crbuf_len += len;
+ MEMMOVE(fptr->crbuf+fptr->crbuf_off, RSTRING_PTR(c), char, len);
+ }
+ else {
+ io_ungetbyte(c, fptr);
+ }
return Qnil;
}
@@ -8019,6 +8069,7 @@ Init_IO(void)
rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
+ rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
rb_define_method(rb_cIO, "flush", rb_io_flush, 0);