[macruby-changes] [902] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 12 21:54:54 PDT 2009
Revision: 902
http://trac.macosforge.org/projects/ruby/changeset/902
Author: lsansonetti at apple.com
Date: 2009-03-12 21:54:54 -0700 (Thu, 12 Mar 2009)
Log Message:
-----------
fixed more IO regressions, implemented ungetc, gets and close
Modified Paths:
--------------
MacRuby/branches/experimental/include/ruby/io.h
MacRuby/branches/experimental/io.c
MacRuby/branches/experimental/parse.y
MacRuby/branches/experimental/ruby.c
Modified: MacRuby/branches/experimental/include/ruby/io.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/io.h 2009-03-13 04:07:45 UTC (rev 901)
+++ MacRuby/branches/experimental/include/ruby/io.h 2009-03-13 04:54:54 UTC (rev 902)
@@ -30,6 +30,8 @@
pid_t pid;
int lineno;
int fd;
+ UInt8 *ungetc_buf;
+ long ungetc_buf_len;
} rb_io_t;
#define HAVE_RB_IO_T 1
Modified: MacRuby/branches/experimental/io.c
===================================================================
--- MacRuby/branches/experimental/io.c 2009-03-13 04:07:45 UTC (rev 901)
+++ MacRuby/branches/experimental/io.c 2009-03-13 04:54:54 UTC (rev 902)
@@ -295,13 +295,28 @@
rb_raise(rb_eRuntimeError, "cannot open write stream");
}
- GC_WB(&RFILE(io)->fptr->readStream, r);
- GC_WB(&RFILE(io)->fptr->writeStream, w);
+ rb_io_t *io_struct = RFILE(io)->fptr;
+
+ if (r != NULL) {
+ GC_WB(&io_struct->readStream, r);
+ CFMakeCollectable(r);
+ }
+ else {
+ io_struct->readStream = NULL;
+ }
+
+ if (w != NULL) {
+ GC_WB(&io_struct->writeStream, w);
+ CFMakeCollectable(w);
+ }
+ else {
+ io_struct->writeStream = NULL;
+ }
- //CFMakeCollectable(r);
- //CFMakeCollectable(w);
-
- RFILE(io)->fptr->fd = fd;
+ io_struct->fd = fd;
+ io_struct->ungetc_buf = NULL;
+ io_struct->ungetc_buf_len = 0;
+
rb_objc_keep_for_exit_finalize((VALUE)io);
return io;
@@ -392,7 +407,7 @@
VALUE
rb_io_addstr(VALUE io, SEL sel, VALUE str)
{
- io_write(io, sel, str);
+ io_write(io, 0, str);
return io;
}
@@ -437,7 +452,8 @@
rb_io_t *io_struct = ExtractIOStruct(io);
rb_io_assert_readable(io_struct);
- CFNumberRef pos = CFReadStreamCopyProperty(io_struct->readStream, kCFStreamPropertyFileCurrentOffset);
+ CFNumberRef pos = CFReadStreamCopyProperty(io_struct->readStream,
+ kCFStreamPropertyFileCurrentOffset);
long result = 0L;
CFNumberGetValue(pos, kCFNumberSInt32Type, &result);
CFRelease(pos);
@@ -457,7 +473,8 @@
// TODO: make this work with IO::SEEK_CUR, SEEK_END, etc.
CFNumberRef pos_property = CFNumberCreate(NULL, kCFNumberSInt32Type, &position);
- CFReadStreamSetProperty(io_struct->readStream, kCFStreamPropertyFileCurrentOffset, pos_property);
+ CFReadStreamSetProperty(io_struct->readStream, kCFStreamPropertyFileCurrentOffset,
+ pos_property);
CFRelease(pos_property);
return INT2FIX(0); // is this right?
}
@@ -573,7 +590,8 @@
{
rb_io_t *io_struct = ExtractIOStruct(io);
rb_io_assert_readable(io_struct);
- return CONDITION_TO_BOOLEAN((CFReadStreamGetStatus(io_struct->readStream) == kCFStreamStatusAtEnd));
+ return CONDITION_TO_BOOLEAN(
+ CFReadStreamGetStatus(io_struct->readStream) == kCFStreamStatusAtEnd);
}
/*
@@ -716,8 +734,44 @@
return io;
}
-#define SMALLBUF 100
+static bool
+rb_io_read_internal(rb_io_t *io_struct, UInt8 *buffer, long len)
+{
+ assert(io_struct->readStream != NULL);
+ long data_read = 0;
+
+ // First let's check if there is something to read in our ungets buffer.
+ if (io_struct->ungetc_buf_len > 0) {
+ data_read = MIN(io_struct->ungetc_buf_len, len);
+ memcpy(buffer, io_struct->ungetc_buf, data_read);
+ io_struct->ungetc_buf_len -= len;
+ if (io_struct->ungetc_buf_len == 0) {
+ xfree(io_struct->ungetc_buf);
+ io_struct->ungetc_buf = NULL;
+ return true;
+ }
+ }
+
+ // We still need to read.
+ while (data_read < len) {
+ int code = CFReadStreamRead(io_struct->readStream, &buffer[data_read],
+ len - data_read);
+
+ if (code == 0) {
+ // EOF
+ return false;
+ }
+ else if (code == -1) {
+ rb_raise(rb_eRuntimeError, "internal error while reading stream");
+ }
+
+ data_read += code;
+ }
+
+ return true;
+}
+
/*
* call-seq:
* ios.readpartial(maxlen) => string
@@ -864,8 +918,15 @@
rb_io_t *io_struct;
rb_scan_args(argc, argv, "11", &len, &outbuf);
+
io_struct = ExtractIOStruct(io);
+ rb_io_assert_readable(io_struct);
+ long size = FIX2LONG(len);
+ if (size == 0) {
+ return rb_str_new2("");
+ }
+
if (NIL_P(outbuf)) {
outbuf = rb_bytestring_new();
}
@@ -877,12 +938,15 @@
//outbuf = rb_coerce_to_bytestring(outbuf);
abort();
}
+
CFMutableDataRef data = rb_bytestring_wrapped_data(outbuf);
- // we need to tell the data how much we read
- CFDataIncreaseLength(data, FIX2LONG(len)); // sentinel byte?
- CFReadStreamRead(io_struct->readStream, CFDataGetMutableBytePtr(data),
- FIX2LONG(len));
- // TODO check the return value of CFReadStreamRead() for errors/eof
+ CFDataIncreaseLength(data, size);
+ UInt8 *buf = CFDataGetMutableBytePtr(data);
+
+ if (!rb_io_read_internal(io_struct, buf, len)) {
+ rb_eof_error();
+ }
+
return outbuf;
}
@@ -1185,16 +1249,11 @@
rb_io_getbyte(VALUE io, SEL sel)
{
rb_io_t *io_struct = ExtractIOStruct(io);
+ rb_io_assert_readable(io_struct);
UInt8 byte;
- int code = CFReadStreamRead(io_struct->readStream, &byte, 1);
- if (code != 1) {
- if (code == 0) {
- // EOF
- return Qnil;
- }
- // TODO raise an exception
- abort();
+ if (!rb_io_read_internal(io_struct, &byte, 1)) {
+ return Qnil;
}
return INT2FIX(byte);
@@ -1238,7 +1297,39 @@
VALUE
rb_io_ungetc(VALUE io, SEL sel, VALUE c)
{
- rb_notimplement();
+ rb_io_t *io_struct = ExtractIOStruct(io);
+
+ rb_io_assert_readable(io_struct);
+
+ if (NIL_P(c)) {
+ return Qnil;
+ }
+
+ UInt8 *bytes;
+ size_t len;
+
+ if (FIXNUM_P(c)) {
+ UInt8 cc = (UInt8)FIX2INT(c);
+
+ bytes = (UInt8 *)alloca(2);
+ bytes[0] = cc;
+ bytes[1] = '\0';
+ len = 1;
+ }
+ else {
+ SafeStringValue(c);
+ bytes = (UInt8 *)RSTRING_PTR(c);
+ len = RSTRING_LEN(c);
+ }
+
+ GC_WB(&io_struct->ungetc_buf, xrealloc(io_struct->ungetc_buf,
+ io_struct->ungetc_buf_len + len));
+
+ memcpy(&io_struct->ungetc_buf[io_struct->ungetc_buf_len], bytes, len);
+
+ io_struct->ungetc_buf_len += len;
+
+ return Qnil;
}
/*
@@ -1294,15 +1385,26 @@
static VALUE
rb_io_set_close_on_exec(VALUE io, SEL sel, VALUE arg)
{
-rb_notimplement();
+ rb_notimplement();
}
+static inline void
+io_close(VALUE io, bool close_read, bool close_write)
+{
+ rb_io_t *io_struct = ExtractIOStruct(io);
+
+ if (close_read && io_struct->readStream != NULL) {
+ CFReadStreamClose(io_struct->readStream);
+ }
+ if (close_write && io_struct->writeStream != NULL) {
+ CFWriteStreamClose(io_struct->writeStream);
+ }
+}
+
static VALUE
rb_io_close_m(VALUE io, SEL sel)
{
- rb_io_t *io_struct = ExtractIOStruct(io);
- CFReadStreamClose(io_struct->readStream);
- CFWriteStreamClose(io_struct->writeStream);
+ io_close(io, true, true);
return Qnil;
}
@@ -1352,7 +1454,8 @@
static VALUE
rb_io_close_read(VALUE io, SEL sel)
{
-rb_notimplement();
+ io_close(io, true, false);
+ return Qnil;
}
/*
@@ -1377,13 +1480,15 @@
static VALUE
rb_io_close_write(VALUE io, SEL sel)
{
-rb_notimplement();
+ io_close(io, false, true);
+ return Qnil;
}
VALUE
rb_io_close(VALUE io, SEL sel)
{
- rb_notimplement();
+ io_close(io, true, true);
+ return Qnil;
}
VALUE
@@ -1391,16 +1496,53 @@
{
VALUE klass = rb_cIO;
- if (path != NULL && strcmp(path, "-")) {
+ if (path != NULL && strcmp(path, "-") != 0) {
klass = rb_cFile;
}
return prep_io(fd, rb_io_modenum_flags(mode), klass, path);
}
VALUE
-rb_io_gets(VALUE v, SEL s)
+rb_io_gets(VALUE io, SEL sel)
{
- rb_notimplement();
+ rb_io_t *io_struct = ExtractIOStruct(io);
+ rb_io_assert_readable(io_struct);
+
+ VALUE outbuf = rb_bytestring_new();
+ CFMutableDataRef data = rb_bytestring_wrapped_data(outbuf);
+
+ long s = 128;
+ CFDataIncreaseLength(data, s);
+ UInt8 *buf = CFDataGetMutableBytePtr(data);
+
+ // FIXME this is a very naive implementation
+
+ long data_read = 0;
+ while (true) {
+ UInt8 byte;
+ if (!rb_io_read_internal(io_struct, &byte, 1)) {
+ break;
+ }
+
+ if (data_read > s) {
+ s += s;
+ CFDataIncreaseLength(data, s);
+ buf = CFDataGetMutableBytePtr(data);
+ }
+ buf[data_read++] = byte;
+
+ if (byte == '\n') {
+ break;
+ }
+ }
+
+ if (data_read == 0) {
+ return Qnil;
+ }
+
+ CFDataSetLength(data, data_read + 1);
+
+ return outbuf;
}
/*
@@ -1780,13 +1922,13 @@
argv = &line;
}
while(argc--) {
- rb_io_write(rb_stdout, sel, *argv++);
+ rb_io_write(rb_stdout, 0, *argv++);
if(!NIL_P(rb_output_fs)) {
- rb_io_write(rb_stdout, sel, rb_output_fs);
+ rb_io_write(rb_stdout, 0, rb_output_fs);
}
}
if(!NIL_P(rb_output_rs)) {
- rb_io_write(rb_stdout, sel, rb_output_rs);
+ rb_io_write(rb_stdout, 0, rb_output_rs);
}
return Qnil;
}
@@ -1819,7 +1961,7 @@
static VALUE
rb_f_print(VALUE recv, SEL sel, int argc, VALUE *argv)
{
- rb_io_print(rb_stdout, sel, argc, argv);
+ rb_io_print(rb_stdout, 0, argc, argv);
return Qnil;
}
@@ -1898,9 +2040,9 @@
static VALUE
rb_f_puts(VALUE recv, SEL sel, int argc, VALUE *argv)
{
- while(argc--) {
- rb_io_write(rb_stdout, sel, *argv++);
- rb_io_write(rb_stdout, sel, rb_default_rs);
+ while (argc--) {
+ rb_io_write(rb_stdout, 0, *argv++);
+ rb_io_write(rb_stdout, 0, rb_default_rs);
}
return Qnil;
}
@@ -1908,13 +2050,13 @@
void
rb_p(VALUE obj, SEL sel) /* for debug print within C code */
{
- rb_io_write(rb_stdout, sel, rb_obj_as_string(rb_inspect(obj)));
- rb_io_write(rb_stdout, sel, rb_default_rs);
+ rb_io_write(rb_stdout, 0, rb_obj_as_string(rb_inspect(obj)));
+ rb_io_write(rb_stdout, 0, rb_default_rs);
}
VALUE rb_io_write(VALUE v, SEL sel, VALUE i)
{
- io_write(v, sel, i);
+ io_write(v, 0, i);
return Qnil;
}
Modified: MacRuby/branches/experimental/parse.y
===================================================================
--- MacRuby/branches/experimental/parse.y 2009-03-13 04:07:45 UTC (rev 901)
+++ MacRuby/branches/experimental/parse.y 2009-03-13 04:54:54 UTC (rev 902)
@@ -5032,7 +5032,7 @@
static VALUE
lex_io_gets(struct parser_params *parser, VALUE io)
{
- return rb_io_gets(io, (SEL)0);
+ return rb_io_gets(io, 0);
}
NODE*
Modified: MacRuby/branches/experimental/ruby.c
===================================================================
--- MacRuby/branches/experimental/ruby.c 2009-03-13 04:07:45 UTC (rev 901)
+++ MacRuby/branches/experimental/ruby.c 2009-03-13 04:54:54 UTC (rev 902)
@@ -1277,7 +1277,7 @@
if (opt->xflag) {
forbid_setid("-x");
opt->xflag = Qfalse;
- while (!NIL_P(line = rb_io_gets(f, (SEL)"gets"))) {
+ while (!NIL_P(line = rb_io_gets(f, 0))) {
line_start++;
const char *lineptr = RSTRING_PTR(line);
if (RSTRING_LEN(line) > 2
@@ -1291,11 +1291,11 @@
rb_raise(rb_eLoadError, "no Ruby script found in input");
}
- c = rb_io_getbyte(f, (SEL)"getbyte");
+ c = rb_io_getbyte(f, 0);
if (c == INT2FIX('#')) {
- c = rb_io_getbyte(f, (SEL)"getbyte");
+ c = rb_io_getbyte(f, 0);
if (c == INT2FIX('!')) {
- line = rb_io_gets(f, (SEL)"gets");
+ line = rb_io_gets(f, 0);
if (NIL_P(line))
return 0;
@@ -1344,12 +1344,12 @@
}
/* push back shebang for pragma may exist in next line */
- rb_io_ungetc(f, (SEL)"ungetc:", rb_str_new2("!\n"));
+ rb_io_ungetc(f, 0, rb_str_new2("!\n"));
}
else if (!NIL_P(c)) {
- rb_io_ungetc(f, (SEL)"ungetc:", c);
+ rb_io_ungetc(f, 0, c);
}
- rb_io_ungetc(f, (SEL)"ungetc:", INT2FIX('#'));
+ rb_io_ungetc(f, 0, INT2FIX('#'));
if (no_src_enc && opt->src.enc.name) {
#if WITH_OBJC
opt->src.enc.enc = opt_enc_find(opt->src.enc.name);
@@ -1368,7 +1368,7 @@
}
}
else if (!NIL_P(c)) {
- rb_io_ungetc(f, (SEL)"ungetc", c);
+ rb_io_ungetc(f, 0, c);
}
require_libraries(); /* Why here? unnatural */
}
@@ -1401,7 +1401,7 @@
rb_define_global_const("DATA", f);
}
else if (f != rb_stdin) {
- rb_io_close(f, (SEL)"close");
+ rb_io_close(f, 0);
}
return tree;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090312/838a18af/attachment-0001.html>
More information about the macruby-changes
mailing list