[macruby-changes] [908] MacRuby/branches/experimental/io.c
source_changes at macosforge.org
source_changes at macosforge.org
Fri Mar 13 18:50:56 PDT 2009
Revision: 908
http://trac.macosforge.org/projects/ruby/changeset/908
Author: lsansonetti at apple.com
Date: 2009-03-13 18:50:55 -0700 (Fri, 13 Mar 2009)
Log Message:
-----------
implemented IO.read()
Modified Paths:
--------------
MacRuby/branches/experimental/io.c
Modified: MacRuby/branches/experimental/io.c
===================================================================
--- MacRuby/branches/experimental/io.c 2009-03-14 01:37:48 UTC (rev 907)
+++ MacRuby/branches/experimental/io.c 2009-03-14 01:50:55 UTC (rev 908)
@@ -256,13 +256,51 @@
return (VALUE)io;
}
-static VALUE
-prep_io(int fd, int mode, VALUE klass, const char *path)
+static inline CFReadStreamRef
+rb_io_open_read_stream(int fd, CFURLRef url)
{
- // TODO honor mode
+ CFReadStreamRef r;
- VALUE io = io_alloc(rb_cIO, 0);
+ if (url != NULL) {
+ r = CFReadStreamCreateWithFile(NULL, url);
+ assert(r != NULL);
+ }
+ else {
+ // TODO
+ abort();
+ }
+ if (!CFReadStreamOpen(r)) {
+ rb_raise(rb_eRuntimeError, "cannot open read stream");
+ }
+
+ return r;
+}
+
+static inline CFWriteStreamRef
+rb_io_open_write_stream(int fd, CFURLRef url)
+{
+ CFWriteStreamRef w;
+
+ if (url != NULL) {
+ w = CFWriteStreamCreateWithFile(NULL, url);
+ assert(w != NULL);
+ }
+ else {
+ // TODO
+ abort();
+ }
+
+ if (!CFWriteStreamOpen(w)) {
+ rb_raise(rb_eRuntimeError, "cannot open read stream");
+ }
+
+ return w;
+}
+
+static inline void
+prep_io_struct(rb_io_t *io_struct, int fd, int mode, const char *path)
+{
CFReadStreamRef r = NULL;
CFWriteStreamRef w = NULL;
@@ -271,12 +309,10 @@
(const UInt8 *)path, strlen(path), false);
assert(url != NULL);
if (mode & FMODE_READABLE) {
- r = CFReadStreamCreateWithFile(NULL, url);
- assert(r != NULL);
+ r = rb_io_open_read_stream(fd, url);
}
if (mode & FMODE_WRITABLE) {
- w = CFWriteStreamCreateWithFile(NULL, url);
- assert(w != NULL);
+ w = rb_io_open_write_stream(fd, url);
}
CFRelease(url);
}
@@ -288,15 +324,6 @@
assert(r != NULL || w != NULL);
- if (r != NULL && !CFReadStreamOpen(r)) {
- rb_raise(rb_eRuntimeError, "cannot open read stream");
- }
- if (w != NULL && !CFWriteStreamOpen(w)) {
- rb_raise(rb_eRuntimeError, "cannot open write stream");
- }
-
- rb_io_t *io_struct = RFILE(io)->fptr;
-
if (r != NULL) {
GC_WB(&io_struct->readStream, r);
CFMakeCollectable(r);
@@ -317,7 +344,17 @@
io_struct->ungetc_buf = NULL;
io_struct->ungetc_buf_len = 0;
io_struct->ungetc_buf_pos = 0;
+}
+static VALUE
+prep_io(int fd, int mode, VALUE klass, const char *path)
+{
+ VALUE io = io_alloc(rb_cIO, 0);
+
+ rb_io_t *io_struct = RFILE(io)->fptr;
+
+ prep_io_struct(io_struct, fd, mode, path);
+
rb_objc_keep_for_exit_finalize((VALUE)io);
return io;
@@ -372,7 +409,8 @@
length = CFDataGetLength(data);
}
else {
- buffer = (UInt8 *)CFStringGetCStringPtr((CFStringRef)to_write, kCFStringEncodingUTF8);
+ buffer = (UInt8 *)CFStringGetCStringPtr((CFStringRef)to_write,
+ kCFStringEncodingUTF8);
if (buffer != NULL) {
length = CFStringGetLength((CFStringRef)to_write);
}
@@ -447,20 +485,34 @@
* f.pos #=> 17
*/
+static inline long
+rb_io_read_stream_get_offset(CFReadStreamRef stream)
+{
+ long result = 0L;
+
+ CFNumberRef pos = CFReadStreamCopyProperty(stream,
+ kCFStreamPropertyFileCurrentOffset);
+ CFNumberGetValue(pos, kCFNumberSInt32Type, &result);
+ CFRelease(pos);
+
+ return result;
+}
+
+static inline void
+rb_io_read_stream_set_offset(CFReadStreamRef stream, long offset)
+{
+ CFNumberRef pos = CFNumberCreate(NULL, kCFNumberSInt32Type, &offset);
+ CFReadStreamSetProperty(stream, kCFStreamPropertyFileCurrentOffset, pos);
+ CFRelease(pos);
+}
+
static VALUE
rb_io_tell(VALUE io, SEL sel)
{
rb_io_t *io_struct = ExtractIOStruct(io);
rb_io_assert_readable(io_struct);
-
- CFNumberRef pos = CFReadStreamCopyProperty(io_struct->readStream,
- kCFStreamPropertyFileCurrentOffset);
- long result = 0L;
- CFNumberGetValue(pos, kCFNumberSInt32Type, &result);
- CFRelease(pos);
- return LONG2FIX(result);
-
+ return LONG2FIX(rb_io_read_stream_get_offset(io_struct->readStream));
}
static VALUE
@@ -469,14 +521,10 @@
rb_io_t *io_struct = ExtractIOStruct(io);
rb_io_assert_readable(io_struct);
rb_io_assert_writable(io_struct);
-
- long position = FIX2LONG(offset);
-
+
// 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);
- CFRelease(pos_property);
+ rb_io_read_stream_set_offset(io_struct->readStream, FIX2LONG(offset));
+
return INT2FIX(0); // is this right?
}
@@ -735,7 +783,30 @@
return io;
}
-static bool
+static inline long
+rb_io_stream_read_internal(CFReadStreamRef readStream, UInt8 *buffer, long len)
+{
+ long data_read = 0;
+
+ while (data_read < len) {
+ int code = CFReadStreamRead(readStream, &buffer[data_read],
+ len - data_read);
+
+ if (code == 0) {
+ // EOF
+ break;
+ }
+ else if (code == -1) {
+ rb_raise(rb_eRuntimeError, "internal error while reading stream");
+ }
+
+ data_read += code;
+ }
+
+ return data_read;
+}
+
+static inline long
rb_io_read_internal(rb_io_t *io_struct, UInt8 *buffer, long len)
{
assert(io_struct->readStream != NULL);
@@ -753,25 +824,16 @@
xfree(io_struct->ungetc_buf);
io_struct->ungetc_buf = NULL;
}
+ if (data_read == len) {
+ return data_read;
+ }
}
- // We still need to read.
- while (data_read < len) {
- int code = CFReadStreamRead(io_struct->readStream, &buffer[data_read],
- len - data_read);
+ // Read from the stream.
+ data_read += rb_io_stream_read_internal(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;
+ return data_read;
}
/*
@@ -945,9 +1007,11 @@
CFDataIncreaseLength(data, size);
UInt8 *buf = CFDataGetMutableBytePtr(data);
- if (!rb_io_read_internal(io_struct, buf, size)) {
+ long data_read = rb_io_read_internal(io_struct, buf, size);
+ if (data_read < size) {
rb_eof_error();
}
+ CFDataSetLength(data, data_read + 1);
return outbuf;
}
@@ -1252,9 +1316,9 @@
{
rb_io_t *io_struct = ExtractIOStruct(io);
rb_io_assert_readable(io_struct);
-
+
UInt8 byte;
- if (!rb_io_read_internal(io_struct, &byte, 1)) {
+ if (rb_io_read_internal(io_struct, &byte, 1) != 1) {
return Qnil;
}
@@ -1553,7 +1617,7 @@
long data_read = 0;
while (true) {
UInt8 byte;
- if (!rb_io_read_internal(io_struct, &byte, 1)) {
+ if (rb_io_read_internal(io_struct, &byte, 1) != 1) {
break;
}
@@ -2903,7 +2967,58 @@
static VALUE
rb_io_s_read(VALUE recv, SEL sel, int argc, VALUE *argv)
{
-rb_notimplement();
+ VALUE fname, length, offset, opt;
+
+ rb_scan_args(argc, argv, "13", &fname, &length, &offset, &opt);
+
+ // TODO honor opt
+
+ StringValue(fname);
+
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
+ (const UInt8 *)RSTRING_PTR(fname), RSTRING_LEN(fname), false);
+ assert(url != NULL);
+
+ CFReadStreamRef readStream = rb_io_open_read_stream(-1, url);
+
+ CFRelease(url);
+
+ if (!NIL_P(offset)) {
+ long o = FIX2LONG(offset);
+ rb_io_read_stream_set_offset(readStream, o);
+ }
+
+ VALUE outbuf = rb_bytestring_new();
+ CFMutableDataRef data = rb_bytestring_wrapped_data(outbuf);
+ long data_read = 0;
+
+ if (NIL_P(length)) {
+ // Read all
+ long size = 128;
+ CFDataIncreaseLength(data, size);
+ UInt8 *buf = CFDataGetMutableBytePtr(data);
+ while (true) {
+ const long fragment = rb_io_stream_read_internal(readStream,
+ &buf[data_read], size);
+ data_read += fragment;
+ if (fragment < size) {
+ break;
+ }
+ size += size;
+ CFDataIncreaseLength(data, size);
+ buf = CFDataGetMutableBytePtr(data);
+ }
+ }
+ else {
+ const long size = FIX2LONG(length);
+ CFDataIncreaseLength(data, size);
+ UInt8 *buf = CFDataGetMutableBytePtr(data);
+ data_read = rb_io_stream_read_internal(readStream, buf, size);
+ }
+
+ CFDataSetLength(data, data_read + 1);
+
+ return outbuf;
}
/*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090313/b3d4fd35/attachment-0001.html>
More information about the macruby-changes
mailing list