Browse Source

add file.read only. raw encoding right now.

v0.7.4-release
Ryan 16 years ago
parent
commit
c8e20fbf81
  1. 202
      src/file.cc
  2. 10
      src/file.js
  3. 1
      src/node.h
  4. 18
      test/simple.js

202
src/file.cc

@ -158,7 +158,7 @@ public:
File (Handle<Object> handle); File (Handle<Object> handle);
~File (); ~File ();
static File* Unwrap (Handle<Object> obj); static File* Unwrap (Handle<Object> handle);
static Handle<Value> Open (const Arguments& args); static Handle<Value> Open (const Arguments& args);
static int AfterOpen (eio_req *req); static int AfterOpen (eio_req *req);
@ -169,8 +169,12 @@ public:
static Handle<Value> Write (const Arguments& args); static Handle<Value> Write (const Arguments& args);
static int AfterWrite (eio_req *req); static int AfterWrite (eio_req *req);
static Handle<Value> Read (const Arguments& args);
static int AfterRead (eio_req *req);
private: private:
bool HasUtf8Encoding (void);
int GetFD (void);
static void MakeWeak (Persistent<Value> _, void *data); static void MakeWeak (Persistent<Value> _, void *data);
void CallTopCallback (const int argc, Handle<Value> argv[]); void CallTopCallback (const int argc, Handle<Value> argv[]);
Persistent<Object> handle_; Persistent<Object> handle_;
@ -197,36 +201,65 @@ File::~File ()
} }
File* File*
File::Unwrap (Handle<Object> obj) File::Unwrap (Handle<Object> handle)
{ {
HandleScope scope; HandleScope scope;
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0)); Handle<External> field = Handle<External>::Cast(handle->GetInternalField(0));
File* file = static_cast<File*>(field->Value()); File* file = static_cast<File*>(field->Value());
return file; return file;
} }
void bool
File::MakeWeak (Persistent<Value> _, void *data) File::HasUtf8Encoding (void)
{ {
File *file = static_cast<File*> (data); return false;
delete file;
} }
int int
File::AfterClose (eio_req *req) File::GetFD (void)
{ {
File *file = static_cast<File*>(req->data); Handle<Value> fd_value = handle_->Get(FD_SYMBOL);
int fd = fd_value->IntegerValue();
}
if (req->result == 0) { void
file->handle_->Delete(FD_SYMBOL); File::CallTopCallback (const int argc, Handle<Value> argv[])
{
HandleScope scope;
Local<Value> queue_value = handle_->Get(ACTION_QUEUE_SYMBOL);
assert(queue_value->IsArray());
Local<Array> queue = Local<Array>::Cast(queue_value);
Local<Value> top_value = queue->Get(Integer::New(0));
if (top_value->IsObject()) {
Local<Object> top = top_value->ToObject();
Local<Value> callback_value = top->Get(String::NewSymbol("callback"));
if (callback_value->IsFunction()) {
Handle<Function> callback = Handle<Function>::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; // poll_actions
Local<Value> argv[argc]; Local<Value> poll_actions_value = handle_->Get(String::NewSymbol("_pollActions"));
argv[0] = Integer::New(req->errorno); assert(poll_actions_value->IsFunction());
file->CallTopCallback(argc, argv); Handle<Function> poll_actions = Handle<Function>::Cast(poll_actions_value);
return 0; poll_actions->Call(handle_, 0, NULL);
}
void
File::MakeWeak (Persistent<Value> _, void *data)
{
File *file = static_cast<File*> (data);
delete file;
} }
Handle<Value> Handle<Value>
@ -236,8 +269,7 @@ File::Close (const Arguments& args)
File *file = File::Unwrap(args.Holder()); File *file = File::Unwrap(args.Holder());
Handle<Value> fd_value = file->handle_->Get(FD_SYMBOL); int fd = file->GetFD();
int fd = fd_value->IntegerValue();
eio_req *req = eio_close (fd, EIO_PRI_DEFAULT, File::AfterClose, file); eio_req *req = eio_close (fd, EIO_PRI_DEFAULT, File::AfterClose, file);
node_eio_submit(req); node_eio_submit(req);
@ -246,17 +278,16 @@ File::Close (const Arguments& args)
} }
int int
File::AfterOpen (eio_req *req) File::AfterClose (eio_req *req)
{ {
File *file = static_cast<File*>(req->data); File *file = static_cast<File*>(req->data);
HandleScope scope;
if(req->result >= 0) { if (req->result == 0) {
file->handle_->Set(FD_SYMBOL, Integer::New(req->result)); file->handle_->Delete(FD_SYMBOL);
} }
const int argc = 1; const int argc = 1;
Handle<Value> argv[argc]; Local<Value> argv[argc];
argv[0] = Integer::New(req->errorno); argv[0] = Integer::New(req->errorno);
file->CallTopCallback(argc, argv); file->CallTopCallback(argc, argv);
@ -310,55 +341,19 @@ File::Open (const Arguments& args)
return Undefined(); return Undefined();
} }
void
File::CallTopCallback (const int argc, Handle<Value> argv[])
{
HandleScope scope;
Local<Value> queue_value = handle_->Get(ACTION_QUEUE_SYMBOL);
assert(queue_value->IsArray());
Local<Array> queue = Local<Array>::Cast(queue_value);
Local<Value> top_value = queue->Get(Integer::New(0));
if (top_value->IsObject()) {
Local<Object> top = top_value->ToObject();
Local<Value> callback_value = top->Get(String::NewSymbol("callback"));
if (callback_value->IsFunction()) {
Handle<Function> callback = Handle<Function>::Cast(callback_value);
TryCatch try_catch;
callback->Call(handle_, argc, argv);
if(try_catch.HasCaught()) {
node_fatal_exception(try_catch);
return;
}
}
}
// poll_actions
Local<Value> poll_actions_value = handle_->Get(String::NewSymbol("_pollActions"));
assert(poll_actions_value->IsFunction());
Handle<Function> poll_actions = Handle<Function>::Cast(poll_actions_value);
poll_actions->Call(handle_, 0, NULL);
}
int int
File::AfterWrite (eio_req *req) File::AfterOpen (eio_req *req)
{ {
File *file = static_cast<File*>(req->data); File *file = static_cast<File*>(req->data);
char *buf = static_cast<char*>(req->ptr2);
delete buf;
size_t written = req->result;
HandleScope scope; HandleScope scope;
const int argc = 2; if(req->result >= 0) {
Local<Value> argv[argc]; file->handle_->Set(FD_SYMBOL, Integer::New(req->result));
}
const int argc = 1;
Handle<Value> argv[argc];
argv[0] = Integer::New(req->errorno); argv[0] = Integer::New(req->errorno);
argv[1] = written >= 0 ? Integer::New(written) : Integer::New(0);
file->CallTopCallback(argc, argv); file->CallTopCallback(argc, argv);
return 0; return 0;
@ -403,8 +398,8 @@ File::Write (const Arguments& args)
printf("trying to write to a bad fd!\n"); printf("trying to write to a bad fd!\n");
return Undefined(); return Undefined();
} }
Handle<Value> 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() // 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); 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(); return Undefined();
} }
int
File::AfterWrite (eio_req *req)
{
File *file = static_cast<File*>(req->data);
char *buf = static_cast<char*>(req->ptr2);
delete buf;
size_t written = req->result;
HandleScope scope;
const int argc = 2;
Local<Value> 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<Value>
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<File*>(req->data);
HandleScope scope;
const int argc = 2;
Local<Value> argv[argc];
argv[0] = Integer::New(req->errorno);
Local<String> buffer;
size_t length = req->result;
char *buf = static_cast<char*>(req->ptr2);
if (file->HasUtf8Encoding()) {
argv[1] = String::New(buf, req->result);
} else {
// raw encoding
Local<Array> 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<Value> static Handle<Value>
NewFile (const Arguments& args) NewFile (const Arguments& args)
{ {
@ -452,4 +517,5 @@ NodeInit_file (Handle<Object> target)
JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_open", File::Open); 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_close", File::Close);
JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_write", File::Write); JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_write", File::Write);
JS_SET_METHOD(file_template->InstanceTemplate(), "_ffi_read", File::Read);
} }

10
src/file.js

@ -37,6 +37,10 @@ File.prototype.write = function (buf, callback) {
this._addAction("write", [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) { File.prototype._addAction = function (method, args, callback) {
this._actionQueue.push({ method: method this._actionQueue.push({ method: method
, callback: callback , callback: callback
@ -63,3 +67,9 @@ stdout.fd = File.STDOUT_FILENO;
var stderr = new File(); var stderr = new File();
stderr.fd = File.STDERR_FILENO; stderr.fd = File.STDERR_FILENO;
Array.prototype.encodeUtf8 = function () {
return String.fromCharCode.apply(String, this);
}

1
src/node.h

@ -10,6 +10,7 @@
#define JS_SET_METHOD(obj, name, callback) \ #define JS_SET_METHOD(obj, name, callback) \
obj->Set(JS_SYMBOL(name), v8::FunctionTemplate::New(callback)->GetFunction()) obj->Set(JS_SYMBOL(name), v8::FunctionTemplate::New(callback)->GetFunction())
enum encoding {UTF8, RAW};
void node_fatal_exception (v8::TryCatch &try_catch); void node_fatal_exception (v8::TryCatch &try_catch);
#define node_loop() ev_default_loop(0) #define node_loop() ev_default_loop(0)

18
test/simple.js

@ -1,18 +1,18 @@
var f = new File; var f = new File;
f.open("/tmp/world", "a+", function (status) { f.open("/tmp/world", "r+", function (status) {
if (status == 0) { if (status == 0) {
stdout.puts("file open"); stdout.puts("file open");
f.write("hello world\n", function (status, written) { f.write("hello world\n")
f.write("something else.\n", function () {
stdout.puts("written. status: " stdout.puts("written. ");
+ status.toString() });
+ " written: " f.read(100, function (status, buf) {
+ written.toString() stdout.puts("read: >>" + buf.encodeUtf8() + "<<");
);
f.close();
}); });
} else { } else {
stdout.puts("file open failed: " + status.toString()); stdout.puts("file open failed: " + status.toString());
} }
f.close(function () { stdout.puts("closed.") });
}); });

Loading…
Cancel
Save