From c8e20fbf8114965013a5aa15abc198b94d265672 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 16 Apr 2009 21:05:26 +0200 Subject: [PATCH] add file.read only. raw encoding right now. --- src/file.cc | 202 ++++++++++++++++++++++++++++++++----------------- src/file.js | 10 +++ src/node.h | 1 + test/simple.js | 18 ++--- 4 files changed, 154 insertions(+), 77 deletions(-) diff --git a/src/file.cc b/src/file.cc index 578e3cd634..6d4ff15062 100644 --- a/src/file.cc +++ b/src/file.cc @@ -158,7 +158,7 @@ public: File (Handle handle); ~File (); - static File* Unwrap (Handle obj); + static File* Unwrap (Handle handle); static Handle Open (const Arguments& args); static int AfterOpen (eio_req *req); @@ -169,8 +169,12 @@ public: static Handle Write (const Arguments& args); static int AfterWrite (eio_req *req); + static Handle Read (const Arguments& args); + static int AfterRead (eio_req *req); private: + bool HasUtf8Encoding (void); + int GetFD (void); static void MakeWeak (Persistent _, void *data); void CallTopCallback (const int argc, Handle argv[]); Persistent handle_; @@ -197,36 +201,65 @@ File::~File () } File* -File::Unwrap (Handle obj) +File::Unwrap (Handle handle) { HandleScope scope; - Handle field = Handle::Cast(obj->GetInternalField(0)); + Handle field = Handle::Cast(handle->GetInternalField(0)); File* file = static_cast(field->Value()); return file; } -void -File::MakeWeak (Persistent _, void *data) +bool +File::HasUtf8Encoding (void) { - File *file = static_cast (data); - delete file; + return false; } int -File::AfterClose (eio_req *req) +File::GetFD (void) { - File *file = static_cast(req->data); + Handle fd_value = handle_->Get(FD_SYMBOL); + int fd = fd_value->IntegerValue(); +} - if (req->result == 0) { - file->handle_->Delete(FD_SYMBOL); +void +File::CallTopCallback (const int argc, Handle argv[]) +{ + HandleScope scope; + + Local queue_value = handle_->Get(ACTION_QUEUE_SYMBOL); + assert(queue_value->IsArray()); + + Local queue = Local::Cast(queue_value); + Local top_value = queue->Get(Integer::New(0)); + if (top_value->IsObject()) { + Local top = top_value->ToObject(); + Local callback_value = top->Get(String::NewSymbol("callback")); + if (callback_value->IsFunction()) { + Handle callback = Handle::Cast(callback_value); + + TryCatch try_catch; + callback->Call(handle_, argc, argv); + if(try_catch.HasCaught()) { + node_fatal_exception(try_catch); + return; + } + } } - const int argc = 1; - Local argv[argc]; - argv[0] = Integer::New(req->errorno); - file->CallTopCallback(argc, argv); + // poll_actions + Local poll_actions_value = handle_->Get(String::NewSymbol("_pollActions")); + assert(poll_actions_value->IsFunction()); + Handle poll_actions = Handle::Cast(poll_actions_value); - return 0; + poll_actions->Call(handle_, 0, NULL); +} + +void +File::MakeWeak (Persistent _, void *data) +{ + File *file = static_cast (data); + delete file; } Handle @@ -236,8 +269,7 @@ File::Close (const Arguments& args) File *file = File::Unwrap(args.Holder()); - Handle fd_value = file->handle_->Get(FD_SYMBOL); - int fd = fd_value->IntegerValue(); + int fd = file->GetFD(); eio_req *req = eio_close (fd, EIO_PRI_DEFAULT, File::AfterClose, file); node_eio_submit(req); @@ -246,17 +278,16 @@ File::Close (const Arguments& args) } int -File::AfterOpen (eio_req *req) +File::AfterClose (eio_req *req) { File *file = static_cast(req->data); - HandleScope scope; - if(req->result >= 0) { - file->handle_->Set(FD_SYMBOL, Integer::New(req->result)); + if (req->result == 0) { + file->handle_->Delete(FD_SYMBOL); } const int argc = 1; - Handle argv[argc]; + Local argv[argc]; argv[0] = Integer::New(req->errorno); file->CallTopCallback(argc, argv); @@ -310,55 +341,19 @@ File::Open (const Arguments& args) return Undefined(); } -void -File::CallTopCallback (const int argc, Handle argv[]) -{ - HandleScope scope; - - Local queue_value = handle_->Get(ACTION_QUEUE_SYMBOL); - assert(queue_value->IsArray()); - - Local queue = Local::Cast(queue_value); - Local top_value = queue->Get(Integer::New(0)); - if (top_value->IsObject()) { - Local top = top_value->ToObject(); - Local callback_value = top->Get(String::NewSymbol("callback")); - if (callback_value->IsFunction()) { - Handle callback = Handle::Cast(callback_value); - - TryCatch try_catch; - callback->Call(handle_, argc, argv); - if(try_catch.HasCaught()) { - node_fatal_exception(try_catch); - return; - } - } - } - - // poll_actions - Local poll_actions_value = handle_->Get(String::NewSymbol("_pollActions")); - assert(poll_actions_value->IsFunction()); - Handle poll_actions = Handle::Cast(poll_actions_value); - - poll_actions->Call(handle_, 0, NULL); -} - - int -File::AfterWrite (eio_req *req) +File::AfterOpen (eio_req *req) { File *file = static_cast(req->data); - - char *buf = static_cast(req->ptr2); - delete buf; - size_t written = req->result; - HandleScope scope; - const int argc = 2; - Local argv[argc]; + if(req->result >= 0) { + file->handle_->Set(FD_SYMBOL, Integer::New(req->result)); + } + + const int argc = 1; + Handle argv[argc]; argv[0] = Integer::New(req->errorno); - argv[1] = written >= 0 ? Integer::New(written) : Integer::New(0); file->CallTopCallback(argc, argv); return 0; @@ -403,8 +398,8 @@ File::Write (const Arguments& args) printf("trying to write to a bad fd!\n"); return Undefined(); } - Handle fd_value = file->handle_->Get(FD_SYMBOL); - int fd = fd_value->IntegerValue(); + + int fd = file->GetFD(); // NOTE: -1 offset in eio_write() invokes write() instead of pwrite() eio_req *req = eio_write(fd, buf, length, -1, EIO_PRI_DEFAULT, File::AfterWrite, file); @@ -413,6 +408,76 @@ File::Write (const Arguments& args) return Undefined(); } +int +File::AfterWrite (eio_req *req) +{ + File *file = static_cast(req->data); + + char *buf = static_cast(req->ptr2); + delete buf; + size_t written = req->result; + + HandleScope scope; + + const int argc = 2; + Local argv[argc]; + argv[0] = Integer::New(req->errorno); + argv[1] = written >= 0 ? Integer::New(written) : Integer::New(0); + file->CallTopCallback(argc, argv); + + return 0; +} + +Handle +File::Read (const Arguments& args) +{ + if (args.Length() < 1) return Undefined(); + if (!args[0]->IsNumber()) return Undefined(); + + HandleScope scope; + File *file = File::Unwrap(args.Holder()); + size_t length = args[0]->IntegerValue(); + + int fd = file->GetFD(); + + // NOTE: -1 offset in eio_read() invokes read() instead of pread() + // NULL pointer tells eio to allocate it itself + eio_req *req = eio_read(fd, NULL, length, -1, EIO_PRI_DEFAULT, File::AfterRead, file); + node_eio_submit(req); + + return Undefined(); +} + +int +File::AfterRead (eio_req *req) +{ + File *file = static_cast(req->data); + HandleScope scope; + + const int argc = 2; + Local argv[argc]; + argv[0] = Integer::New(req->errorno); + + Local buffer; + size_t length = req->result; + char *buf = static_cast(req->ptr2); + + if (file->HasUtf8Encoding()) { + argv[1] = String::New(buf, req->result); + } else { + // raw encoding + Local array = Array::New(length); + for (int i = 0; i < length; i++) { + array->Set(Integer::New(i), Integer::New(buf[i])); + } + argv[1] = array; + } + + file->CallTopCallback(argc, argv); + + return 0; +} + static Handle NewFile (const Arguments& args) { @@ -452,4 +517,5 @@ NodeInit_file (Handle target) JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_open", File::Open); JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_close", File::Close); JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_write", File::Write); + JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_read", File::Read); } diff --git a/src/file.js b/src/file.js index 8bd004528a..b291fc7468 100644 --- a/src/file.js +++ b/src/file.js @@ -37,6 +37,10 @@ File.prototype.write = function (buf, callback) { this._addAction("write", [buf], callback); }; +File.prototype.read = function (length, callback) { + this._addAction("read", [length], callback); +}; + File.prototype._addAction = function (method, args, callback) { this._actionQueue.push({ method: method , callback: callback @@ -63,3 +67,9 @@ stdout.fd = File.STDOUT_FILENO; var stderr = new File(); stderr.fd = File.STDERR_FILENO; + + + +Array.prototype.encodeUtf8 = function () { + return String.fromCharCode.apply(String, this); +} diff --git a/src/node.h b/src/node.h index 15de1b1810..28968ea62c 100644 --- a/src/node.h +++ b/src/node.h @@ -10,6 +10,7 @@ #define JS_SET_METHOD(obj, name, callback) \ obj->Set(JS_SYMBOL(name), v8::FunctionTemplate::New(callback)->GetFunction()) +enum encoding {UTF8, RAW}; void node_fatal_exception (v8::TryCatch &try_catch); #define node_loop() ev_default_loop(0) diff --git a/test/simple.js b/test/simple.js index 0440065cc6..7179d6cf8e 100644 --- a/test/simple.js +++ b/test/simple.js @@ -1,18 +1,18 @@ var f = new File; -f.open("/tmp/world", "a+", function (status) { +f.open("/tmp/world", "r+", function (status) { if (status == 0) { stdout.puts("file open"); - f.write("hello world\n", function (status, written) { - - stdout.puts("written. status: " - + status.toString() - + " written: " - + written.toString() - ); - f.close(); + f.write("hello world\n") + f.write("something else.\n", function () { + stdout.puts("written. "); + }); + f.read(100, function (status, buf) { + stdout.puts("read: >>" + buf.encodeUtf8() + "<<"); }); } else { stdout.puts("file open failed: " + status.toString()); } + + f.close(function () { stdout.puts("closed.") }); });