add file.write()
authorRyan <ry@tinyclouds.org>
Thu, 16 Apr 2009 09:37:44 +0000 (11:37 +0200)
committerRyan <ry@tinyclouds.org>
Thu, 16 Apr 2009 09:37:44 +0000 (11:37 +0200)
src/file.cc
test/simple.js [new file with mode: 0644]
wscript

index e01fa71..4c881fa 100644 (file)
@@ -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);
 }
diff --git a/test/simple.js b/test/simple.js
new file mode 100644 (file)
index 0000000..3651188
--- /dev/null
@@ -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+");
diff --git a/wscript b/wscript
index e422cfa..a2a04e3 100644 (file)
--- a/wscript
+++ b/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"