mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Clean up eio wrappers. Create EIOPromise.
This commit is contained in:
@@ -220,29 +220,9 @@ Promise::Detach (void)
|
||||
coroutine_top->Destack();
|
||||
}
|
||||
|
||||
if (ref_) {
|
||||
ev_unref(EV_DEFAULT_UC);
|
||||
}
|
||||
|
||||
ObjectWrap::Detach();
|
||||
}
|
||||
|
||||
Promise*
|
||||
Promise::Create (bool ref)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> handle =
|
||||
Promise::constructor_template->GetFunction()->NewInstance();
|
||||
|
||||
Promise *promise = ObjectWrap::Unwrap<Promise>(handle);
|
||||
|
||||
promise->ref_ = ref;
|
||||
if (ref) ev_ref(EV_DEFAULT_UC);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
bool
|
||||
Promise::EmitSuccess (int argc, v8::Handle<v8::Value> argv[])
|
||||
{
|
||||
@@ -262,3 +242,18 @@ Promise::EmitError (int argc, v8::Handle<v8::Value> argv[])
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Promise*
|
||||
Promise::Create (void)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> handle =
|
||||
Promise::constructor_template->GetFunction()->NewInstance();
|
||||
|
||||
Promise *promise = new Promise();
|
||||
promise->Wrap(handle);
|
||||
promise->Attach();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,12 @@ class Promise : public EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
|
||||
static Promise* Create (bool ref = false);
|
||||
static Promise* Create (void);
|
||||
|
||||
bool EmitSuccess (int argc, v8::Handle<v8::Value> argv[]);
|
||||
bool EmitError (int argc, v8::Handle<v8::Value> argv[]);
|
||||
void Block ();
|
||||
|
||||
|
||||
v8::Handle<v8::Object> Handle ()
|
||||
{
|
||||
return handle_;
|
||||
@@ -45,7 +43,6 @@ class Promise : public EventEmitter {
|
||||
virtual void Detach (void);
|
||||
|
||||
bool blocking_;
|
||||
bool ref_;
|
||||
Promise *prev_; /* for the prev in the Poor Man's coroutine stack */
|
||||
|
||||
void Destack ();
|
||||
@@ -53,10 +50,8 @@ class Promise : public EventEmitter {
|
||||
Promise () : EventEmitter()
|
||||
{
|
||||
blocking_ = false;
|
||||
ref_ = false;
|
||||
prev_ = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
#endif
|
||||
|
||||
465
src/file.cc
465
src/file.cc
@@ -28,184 +28,242 @@ using namespace node;
|
||||
#define CTIME_SYMBOL String::NewSymbol("ctime")
|
||||
#define BAD_ARGUMENTS Exception::TypeError(String::New("Bad argument"))
|
||||
|
||||
static int
|
||||
AfterClose (eio_req *req)
|
||||
void
|
||||
EIOPromise::Attach (void)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
if (req->result == 0) {
|
||||
promise->EmitSuccess(0, NULL);
|
||||
} else {
|
||||
promise->EmitError(0, NULL);
|
||||
ev_ref(EV_DEFAULT_UC);
|
||||
Promise::Attach();
|
||||
}
|
||||
|
||||
void
|
||||
EIOPromise::Detach (void)
|
||||
{
|
||||
Promise::Detach();
|
||||
ev_unref(EV_DEFAULT_UC);
|
||||
}
|
||||
|
||||
EIOPromise*
|
||||
EIOPromise::Create (void)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> handle =
|
||||
Promise::constructor_template->GetFunction()->NewInstance();
|
||||
|
||||
EIOPromise *promise = new EIOPromise();
|
||||
promise->Wrap(handle);
|
||||
|
||||
promise->Attach();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
#define NODE_UNIXTIME(t) v8::Date::New(1000*static_cast<double>(t))
|
||||
int
|
||||
EIOPromise::After (eio_req *req)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
EIOPromise *promise = reinterpret_cast<EIOPromise*>(req->data);
|
||||
assert(req == promise->req_);
|
||||
|
||||
if (req->errorno != 0) {
|
||||
Local<Value> exception = Exception::Error(
|
||||
String::NewSymbol(strerror(req->errorno)));
|
||||
promise->EmitError(1, &exception);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int argc = 0;
|
||||
Local<Value> argv[5]; // 5 is the maximum number of args
|
||||
|
||||
switch (req->type) {
|
||||
case EIO_CLOSE:
|
||||
case EIO_RENAME:
|
||||
case EIO_UNLINK:
|
||||
case EIO_RMDIR:
|
||||
argc = 0;
|
||||
break;
|
||||
|
||||
case EIO_OPEN:
|
||||
case EIO_WRITE:
|
||||
argc = 1;
|
||||
argv[0] = Integer::New(req->result);
|
||||
break;
|
||||
|
||||
case EIO_STAT:
|
||||
{
|
||||
Local<Object> stats = Object::New();
|
||||
struct stat *s = reinterpret_cast<struct stat*>(req->ptr2);
|
||||
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); /* ID of device containing file */
|
||||
stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); /* inode number */
|
||||
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); /* protection */
|
||||
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); /* number of hard links */
|
||||
stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); /* user ID of owner */
|
||||
stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); /* group ID of owner */
|
||||
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); /* device ID (if special file) */
|
||||
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); /* total size, in bytes */
|
||||
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); /* blocksize for filesystem I/O */
|
||||
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); /* number of blocks allocated */
|
||||
stats->Set(ATIME_SYMBOL, NODE_UNIXTIME(s->st_atime)); /* time of last access */
|
||||
stats->Set(MTIME_SYMBOL, NODE_UNIXTIME(s->st_mtime)); /* time of last modification */
|
||||
stats->Set(CTIME_SYMBOL, NODE_UNIXTIME(s->st_ctime)); /* time of last status change */
|
||||
argc = 1;
|
||||
argv[0] = stats;
|
||||
break;
|
||||
}
|
||||
|
||||
case EIO_READ:
|
||||
{
|
||||
argc = 2;
|
||||
// FIXME the following is really ugly!
|
||||
if (promise->encoding_ == RAW) {
|
||||
if (req->result == 0) {
|
||||
argv[0] = Local<Value>::New(Null());
|
||||
argv[1] = Integer::New(0);
|
||||
} else {
|
||||
char *buf = reinterpret_cast<char*>(req->ptr2);
|
||||
size_t len = req->result;
|
||||
Local<Array> array = Array::New(len);
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
unsigned char val = reinterpret_cast<const unsigned char*>(buf)[i];
|
||||
array->Set(Integer::New(i), Integer::New(val));
|
||||
}
|
||||
argv[0] = array;
|
||||
argv[1] = Integer::New(req->result);
|
||||
}
|
||||
} else {
|
||||
// UTF8
|
||||
if (req->result == 0) {
|
||||
// eof
|
||||
argv[0] = Local<Value>::New(Null());
|
||||
argv[1] = Integer::New(0);
|
||||
} else {
|
||||
char *buf = reinterpret_cast<char*>(req->ptr2);
|
||||
argv[0] = String::New(buf, req->result);
|
||||
argv[1] = Integer::New(req->result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0 && "Unhandled eio response");
|
||||
}
|
||||
|
||||
promise->EmitSuccess(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
Close (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 1 || !args[0]->IsInt32())
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
int fd = args[0]->Int32Value();
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
|
||||
eio_close(fd, EIO_PRI_DEFAULT, AfterClose, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
return scope.Close(EIOPromise::Close(fd));
|
||||
}
|
||||
|
||||
static int
|
||||
AfterRename (eio_req *req)
|
||||
static Handle<Value>
|
||||
Stat (const Arguments& args)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
if (req->result == 0) {
|
||||
promise->EmitSuccess(0, NULL);
|
||||
} else {
|
||||
promise->EmitError(0, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Handle<Value> Rename (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsString())
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsString()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
|
||||
return scope.Close(EIOPromise::Stat(*path));
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
Rename (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsString()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
String::Utf8Value new_path(args[1]->ToString());
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
return scope.Close(EIOPromise::Rename(*path, *new_path));
|
||||
Promise *promise = EIOPromise::Create();
|
||||
|
||||
eio_rename(*path, *new_path, EIO_PRI_DEFAULT, AfterRename, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
}
|
||||
|
||||
static int
|
||||
AfterUnlink (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
if (req->result == 0) {
|
||||
promise->EmitSuccess(0, NULL);
|
||||
} else {
|
||||
promise->EmitError(0, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Handle<Value> Unlink (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 1 || !args[0]->IsString())
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
HandleScope scope;
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
Promise *promise = Promise::Create(true);
|
||||
eio_unlink(*path, EIO_PRI_DEFAULT, AfterUnlink, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
}
|
||||
|
||||
static int
|
||||
AfterRMDir (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
if (req->result == 0) {
|
||||
promise->EmitSuccess(0, NULL);
|
||||
} else {
|
||||
promise->EmitError(0, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Handle<Value> RMDir (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 1 || !args[0]->IsString())
|
||||
if (args.Length() < 1 || !args[0]->IsString()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
HandleScope scope;
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
Promise *promise = Promise::Create(true);
|
||||
eio_rmdir(*path, EIO_PRI_DEFAULT, AfterRMDir, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
}
|
||||
|
||||
static int
|
||||
AfterOpen (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
|
||||
if (req->result < 0) {
|
||||
promise->EmitError(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
return scope.Close(EIOPromise::Unlink(*path));
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
RMDir (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
Local<Value> argv[1] = { Integer::New(req->result) };
|
||||
promise->EmitSuccess(1, argv);
|
||||
return 0;
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsString()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
return scope.Close(EIOPromise::RMDir(*path));
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
Open (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
if ( args.Length() < 3
|
||||
|| !args[0]->IsString()
|
||||
|| !args[1]->IsInt32()
|
||||
|| !args[2]->IsInt32()
|
||||
) return ThrowException(BAD_ARGUMENTS);
|
||||
|
||||
HandleScope scope;
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
int flags = args[1]->Int32Value();
|
||||
mode_t mode = static_cast<mode_t>(args[2]->Int32Value());
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
|
||||
eio_open(*path, flags, mode, EIO_PRI_DEFAULT, AfterOpen, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
return scope.Close(EIOPromise::Open(*path, flags, mode));
|
||||
}
|
||||
|
||||
static int
|
||||
AfterWrite (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
|
||||
if (req->result < 0) {
|
||||
promise->EmitError(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
free(req->ptr2);
|
||||
|
||||
ssize_t written = req->result;
|
||||
Local<Value> argv[1];
|
||||
argv[0] = written >= 0 ? Integer::New(written) : Integer::New(0);
|
||||
|
||||
promise->EmitSuccess(1, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* node.fs.write(fd, data, position, callback)
|
||||
/* node.fs.write(fd, data, position=null)
|
||||
* Wrapper for write(2).
|
||||
*
|
||||
* 0 fd integer. file descriptor
|
||||
* 1 data the data to write (string = utf8, array = raw)
|
||||
* 2 position if integer, position to write at in the file.
|
||||
* if null, write from the current position
|
||||
*
|
||||
* 3 callback(errorno, written)
|
||||
*/
|
||||
static Handle<Value>
|
||||
Write (const Arguments& args)
|
||||
{
|
||||
if ( args.Length() < 3
|
||||
|| !args[0]->IsInt32()
|
||||
) return ThrowException(BAD_ARGUMENTS);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsInt32()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
int fd = args[0]->Int32Value();
|
||||
off_t pos = args[2]->IsNumber() ? args[2]->IntegerValue() : -1;
|
||||
off_t offset = args[2]->IsNumber() ? args[2]->IntegerValue() : -1;
|
||||
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
@@ -231,92 +289,27 @@ Write (const Arguments& args)
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
eio_write(fd, buf, len, pos, EIO_PRI_DEFAULT, AfterWrite, promise);
|
||||
return scope.Close(promise->Handle());
|
||||
return scope.Close(EIOPromise::Write(fd, buf, len, offset));
|
||||
}
|
||||
|
||||
static int
|
||||
AfterUtf8Read (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
|
||||
if (req->result < 0) {
|
||||
promise->EmitError(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
Local<Value> argv[2];
|
||||
|
||||
if (req->result == 0) {
|
||||
// eof
|
||||
argv[0] = Local<Value>::New(Null());
|
||||
argv[1] = Integer::New(0);
|
||||
} else {
|
||||
char *buf = reinterpret_cast<char*>(req->ptr2);
|
||||
argv[0] = String::New(buf, req->result);
|
||||
argv[1] = Integer::New(req->result);
|
||||
}
|
||||
|
||||
promise->EmitSuccess(2, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
AfterRawRead(eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
|
||||
if (req->result < 0) {
|
||||
promise->EmitError(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
Local<Value> argv[2];
|
||||
|
||||
if (req->result == 0) {
|
||||
argv[0] = Local<Value>::New(Null());
|
||||
argv[1] = Integer::New(0);
|
||||
} else {
|
||||
char *buf = reinterpret_cast<char*>(req->ptr2);
|
||||
size_t len = req->result;
|
||||
Local<Array> array = Array::New(len);
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
unsigned char val = reinterpret_cast<const unsigned char*>(buf)[i];
|
||||
array->Set(Integer::New(i), Integer::New(val));
|
||||
}
|
||||
argv[0] = array;
|
||||
argv[1] = Integer::New(req->result);
|
||||
}
|
||||
|
||||
promise->EmitSuccess(2, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* node.fs.read(fd, length, position, encoding, callback)
|
||||
/* node.fs.read(fd, length, position, encoding)
|
||||
* Wrapper for read(2).
|
||||
*
|
||||
* 0 fd integer. file descriptor
|
||||
* 1 length integer. length to read
|
||||
* 2 position if integer, position to read from in the file.
|
||||
* if null, read from the current position
|
||||
* 3 encoding either node.fs.UTF8 or node.fs.RAW
|
||||
*
|
||||
* 4 callback(errorno, data)
|
||||
* 3 encoding either node.UTF8 or node.RAW
|
||||
*/
|
||||
static Handle<Value>
|
||||
Read (const Arguments& args)
|
||||
{
|
||||
if ( args.Length() < 2
|
||||
|| !args[0]->IsInt32() // fd
|
||||
|| !args[1]->IsNumber() // len
|
||||
) return ThrowException(BAD_ARGUMENTS);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsInt32() || !args[1]->IsNumber()) {
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
int fd = args[0]->Int32Value();
|
||||
size_t len = args[1]->IntegerValue();
|
||||
off_t pos = args[2]->IsNumber() ? args[2]->IntegerValue() : -1;
|
||||
@@ -326,94 +319,7 @@ Read (const Arguments& args)
|
||||
encoding = static_cast<enum encoding>(args[3]->Int32Value());
|
||||
}
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
|
||||
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself
|
||||
eio_read(fd, NULL, len, pos, EIO_PRI_DEFAULT,
|
||||
encoding == UTF8 ? AfterUtf8Read : AfterRawRead, promise);
|
||||
|
||||
return scope.Close(promise->Handle());
|
||||
}
|
||||
|
||||
static int
|
||||
AfterStat (eio_req *req)
|
||||
{
|
||||
Promise *promise = reinterpret_cast<Promise*>(req->data);
|
||||
|
||||
if (req->result < 0) {
|
||||
promise->EmitError(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> stats = Object::New();
|
||||
|
||||
struct stat *s = reinterpret_cast<struct stat*>(req->ptr2);
|
||||
|
||||
/* ID of device containing file */
|
||||
stats->Set(DEV_SYMBOL, Integer::New(s->st_dev));
|
||||
/* inode number */
|
||||
stats->Set(INO_SYMBOL, Integer::New(s->st_ino));
|
||||
/* protection */
|
||||
stats->Set(MODE_SYMBOL, Integer::New(s->st_mode));
|
||||
/* number of hard links */
|
||||
stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink));
|
||||
/* user ID of owner */
|
||||
stats->Set(UID_SYMBOL, Integer::New(s->st_uid));
|
||||
/* group ID of owner */
|
||||
stats->Set(GID_SYMBOL, Integer::New(s->st_gid));
|
||||
/* device ID (if special file) */
|
||||
stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev));
|
||||
/* total size, in bytes */
|
||||
stats->Set(SIZE_SYMBOL, Integer::New(s->st_size));
|
||||
/* blocksize for filesystem I/O */
|
||||
stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize));
|
||||
/* number of blocks allocated */
|
||||
stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks));
|
||||
/* time of last access */
|
||||
stats->Set(ATIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_atime)));
|
||||
/* time of last modification */
|
||||
stats->Set(MTIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_mtime)));
|
||||
/* time of last status change */
|
||||
stats->Set(CTIME_SYMBOL, Date::New(1000*static_cast<double>(s->st_ctime)));
|
||||
|
||||
Local<Value> argv[1] = { stats };
|
||||
promise->EmitSuccess(1, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
Stat (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 1 || !args[0]->IsString())
|
||||
return ThrowException(BAD_ARGUMENTS);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
String::Utf8Value path(args[0]->ToString());
|
||||
|
||||
Promise *promise = Promise::Create(true);
|
||||
|
||||
eio_stat(*path, EIO_PRI_DEFAULT, AfterStat, promise);
|
||||
|
||||
return scope.Close(promise->Handle());
|
||||
}
|
||||
|
||||
static Handle<Value>
|
||||
StrError (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 1) return v8::Undefined();
|
||||
if (!args[0]->IsNumber()) return v8::Undefined();
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
int errorno = args[0]->IntegerValue();
|
||||
|
||||
Local<String> message = String::New(strerror(errorno));
|
||||
|
||||
return scope.Close(message);
|
||||
return scope.Close(EIOPromise::Read(fd, len, pos, encoding));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -421,7 +327,6 @@ File::Initialize (Handle<Object> target)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
// POSIX Wrappers
|
||||
NODE_SET_METHOD(target, "close", Close);
|
||||
NODE_SET_METHOD(target, "open", Open);
|
||||
NODE_SET_METHOD(target, "read", Read);
|
||||
@@ -430,6 +335,4 @@ File::Initialize (Handle<Object> target)
|
||||
NODE_SET_METHOD(target, "stat", Stat);
|
||||
NODE_SET_METHOD(target, "unlink", Unlink);
|
||||
NODE_SET_METHOD(target, "write", Write);
|
||||
|
||||
NODE_SET_METHOD(target, "strerror", StrError);
|
||||
}
|
||||
|
||||
100
src/file.h
100
src/file.h
@@ -1,14 +1,114 @@
|
||||
#ifndef node_file_h
|
||||
#define node_file_h
|
||||
|
||||
#include "node.h"
|
||||
#include "events.h"
|
||||
#include <v8.h>
|
||||
|
||||
namespace node {
|
||||
|
||||
/* Are you missing your favorite POSIX function? It might be very easy to
|
||||
* add a wrapper. Take a look in deps/libeio/eio.h at the list of wrapper
|
||||
* functions. If your function is in that list, just follow the lead of
|
||||
* EIOPromise::Open. You'll need to add two functions, one static function
|
||||
* in EIOPromise, and one static function which interprets the javascript
|
||||
* args in src/file.cc. Then just a reference to that function in
|
||||
* File::Initialize() and you should be good to go.
|
||||
* Don't forget to add a test to test/mjsunit.
|
||||
*/
|
||||
|
||||
#define NODE_V8_METHOD_DECLARE(name) \
|
||||
static v8::Handle<v8::Value> name (const v8::Arguments& args)
|
||||
|
||||
class File {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
};
|
||||
|
||||
class EIOPromise : public Promise {
|
||||
public:
|
||||
static v8::Handle<v8::Object>
|
||||
Open (const char *path, int flags, mode_t mode)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_open(path, flags, mode, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Close (int fd)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_close(fd, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Write (int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_write(fd, buf, count, offset, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Read (int fd, size_t count, off_t offset, enum encoding encoding)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->encoding_ = encoding;
|
||||
// NOTE: 2nd param: NULL pointer tells eio to allocate it itself
|
||||
p->req_ = eio_read(fd, NULL, count, offset, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Stat (const char *path)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_stat(path, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Rename (const char *path, const char *new_path)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_rename(path, new_path, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
Unlink (const char *path)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_unlink(path, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Object>
|
||||
RMDir (const char *path)
|
||||
{
|
||||
EIOPromise *p = Create();
|
||||
p->req_ = eio_rmdir(path, EIO_PRI_DEFAULT, After, p);
|
||||
return p->handle_;
|
||||
}
|
||||
|
||||
static EIOPromise* Create (void);
|
||||
|
||||
protected:
|
||||
|
||||
void Attach (void);
|
||||
void Detach (void);
|
||||
|
||||
EIOPromise () : Promise() { }
|
||||
|
||||
private:
|
||||
|
||||
static int After (eio_req *req);
|
||||
|
||||
eio_req *req_;
|
||||
enum encoding encoding_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
#endif // node_file_h
|
||||
|
||||
Reference in New Issue
Block a user