Browse Source

add file.write()

v0.7.4-release
Ryan 16 years ago
parent
commit
7e1350f6e4
  1. 138
      src/file.cc
  2. 18
      test/simple.js
  3. 14
      wscript

138
src/file.cc

@ -4,15 +4,18 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
using namespace v8;
class File;
class Callback {
public:
Callback(Handle<Value> v);
~Callback();
Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
File *file;
private:
Persistent<Function> handle_;
};
@ -153,12 +156,17 @@ public:
static File* Unwrap (Handle<Object> obj);
void OnError (const char *syscall, int errorno);
void Open (const char *path, const char *mode);
static int AfterOpen (eio_req *req);
void Close ();
static int AfterClose (eio_req *req);
void Write (char *buf, size_t length, Callback *callback);
static int AfterWrite (eio_req *req);
private:
static void MakeWeak (Persistent<Value> _, void *data);
@ -200,7 +208,6 @@ File::MakeWeak (Persistent<Value> _, void *data)
delete file;
}
int
File::AfterClose (eio_req *req)
{
@ -218,6 +225,30 @@ File::Close ()
node_eio_submit(req);
}
void
File::OnError (const char *syscall, int errorno)
{
HandleScope scope;
Handle<Value> on_error_value = handle_->Get( String::NewSymbol("onError") );
if (!on_error_value->IsFunction())
return;
Handle<Function> on_error = Handle<Function>::Cast(on_error_value);
const int argc = 3;
Local<Value> argv[argc];
argv[0] = String::New(syscall);
argv[1] = Integer::New(errorno);
argv[2] = String::New(strerror(errorno));
TryCatch try_catch;
on_error->Call(handle_, argc, argv);
if(try_catch.HasCaught())
node_fatal_exception(try_catch);
}
int
File::AfterOpen (eio_req *req)
{
@ -227,15 +258,7 @@ File::AfterOpen (eio_req *req)
TryCatch try_catch;
if(req->result < 0) {
// TODO
/*
const int argc = 2;
Local<Value> argv[argc];
argv[0] = Integer::New(errorno);
argv[1] = String::New(strerror(errorno));
*/
printf("error opening file...handle me\n");
file->OnError("open", req->errorno);
return 0;
}
@ -266,24 +289,15 @@ File::Open (const char *path, const char *mode)
// I don't want to to use fopen() because eio doesn't support it.
switch(mode[0]) {
case 'r':
if (mode[1] == '+')
flags = O_RDWR;
else
flags = O_RDONLY;
flags = (mode[1] == '+' ? O_RDWR : O_RDONLY);
break;
case 'w':
if (mode[1] == '+')
flags = O_RDWR | O_CREAT | O_TRUNC;
else
flags = O_WRONLY | O_CREAT | O_TRUNC;
flags = O_CREAT | O_TRUNC | (mode[1] == '+' ? O_RDWR : O_WRONLY);
break;
case 'a':
if (mode[1] == '+')
flags = O_RDWR | O_APPEND | O_CREAT;
else
flags = O_WRONLY | O_APPEND | O_CREAT;
flags = O_APPEND | O_CREAT | (mode[1] == '+' ? O_RDWR : O_WRONLY);
break;
}
@ -291,6 +305,43 @@ File::Open (const char *path, const char *mode)
node_eio_submit(req);
}
int
File::AfterWrite (eio_req *req)
{
Callback *callback = static_cast<Callback*>(req->data);
HandleScope scope;
char *buf = static_cast<char*>(req->ptr2);
delete buf;
size_t written = req->result;
if (callback) {
const int argc = 2;
Local<Value> argv[argc];
argv[0] = Integer::New(req->errorno);
argv[1] = written >= 0 ? Integer::New(written) : Integer::New(0);
callback->Call(callback->file->handle_, argc, argv);
delete callback;
}
return 0;
}
void
File::Write (char *buf, size_t length, Callback *callback)
{
if (callback)
callback->file = this;
// NOTE: -1 offset in eio_write() invokes write() instead of pwrite()
if (fd_ < 0) {
printf("trying to write to a bad fd!\n");
return;
}
eio_req *req = eio_write(fd_, buf, length, -1, EIO_PRI_DEFAULT, File::AfterWrite, callback);
node_eio_submit(req);
}
static Handle<Value>
NewFile (const Arguments& args)
{
@ -331,6 +382,48 @@ JS_METHOD(file_close)
return Undefined();
}
JS_METHOD(file_write)
{
if (args.Length() < 1) return Undefined();
if (!args[0]->IsString())
HandleScope scope;
File *file = File::Unwrap(args.Holder());
char *buf = NULL;
size_t length = 0;
if (args[0]->IsString()) {
// utf8 encoded data
Local<String> string = args[0]->ToString();
length = string->Utf8Length();
buf = new char[length];
string->WriteUtf8(buf, length);
} else if (args[0]->IsArray()) {
// binary data
Local<Array> array = Local<Array>::Cast(args[0]);
length = array->Length();
buf = new char[length];
for (int i = 0; i < length; i++) {
Local<Value> int_value = array->Get(Integer::New(i));
buf[i] = int_value->Int32Value();
}
} else {
// bad arguments. raise error?
return Undefined();
}
Callback *callback = args[1]->IsFunction() ? new Callback(args[1]) : NULL;
file->Write(buf, length, callback);
return Undefined();
}
void
NodeInit_file (Handle<Object> target)
{
@ -348,4 +441,5 @@ NodeInit_file (Handle<Object> target)
JS_SET_METHOD(file_template->InstanceTemplate(), "open", file_open);
JS_SET_METHOD(file_template->InstanceTemplate(), "close", file_close);
JS_SET_METHOD(file_template->InstanceTemplate(), "write", file_write);
}

18
test/simple.js

@ -0,0 +1,18 @@
var f = new File;
f.onError = function (call) {
node.blocking.print("file error with " + call );
}
f.onOpen = function () {
node.blocking.print("file opened.");
f.write("hello world\n", function (status, written) {
node.blocking.print("written. status: "
+ status.toString()
+ " written: "
+ written.toString()
);
f.close();
});
};
f.open("/tmp/world", "a+");

14
wscript

@ -45,6 +45,11 @@ def configure(conf):
conf.define("HAVE_CONFIG_H", 1)
conf.write_config_header('config.h')
conf.env.append_value('CXXFLAGS', '-g')
debug_env = conf.env.copy()
conf.set_env_name('debug', debug_env)
conf.setenv('debug')
def build(bld):
bld.add_subdirs('deps/libeio deps/libev')
@ -54,10 +59,12 @@ def build(bld):
deps_tgt = join(bld.srcnode.abspath(bld.env),"deps")
v8dir_src = join(deps_src,"v8")
v8dir_tgt = join(deps_tgt, "v8")
v8lib = bld.env["staticlib_PATTERN"] % "v8"
v8lib = bld.env["staticlib_PATTERN"] % "v8_g"
#v8lib = bld.env["staticlib_PATTERN"] % "v8"
v8 = bld.new_task_gen(
target=join("deps/v8",v8lib),
rule='cp -rf %s %s && cd %s && scons -Q library=static snapshot=on'
rule='cp -rf %s %s && cd %s && scons -Q mode=debug library=static snapshot=on'
#rule='cp -rf %s %s && cd %s && scons -Q library=static snapshot=on'
% ( v8dir_src
, deps_tgt
, v8dir_tgt
@ -65,7 +72,8 @@ def build(bld):
before="cxx"
)
bld.env["CPPPATH_V8"] = "deps/v8/include"
bld.env["STATICLIB_V8"] = "v8"
#bld.env["STATICLIB_V8"] = "v8"
bld.env["STATICLIB_V8"] = "v8_g"
bld.env["LIBPATH_V8"] = v8dir_tgt
bld.env["LINKFLAGS_V8"] = "-pthread"

Loading…
Cancel
Save