diff --git a/src/file.cc b/src/file.cc index 356fca750e9..1f31ade237e 100644 --- a/src/file.cc +++ b/src/file.cc @@ -10,49 +10,85 @@ #include using namespace v8; +using namespace node; #define FD_SYMBOL v8::String::NewSymbol("fd") #define ACTION_QUEUE_SYMBOL v8::String::NewSymbol("_actionQueue") +#define ENCODING_SYMBOL v8::String::NewSymbol("encoding") + +#define UTF8_SYMBOL v8::String::NewSymbol("utf8") +#define RAW_SYMBOL v8::String::NewSymbol("raw") + +static void +InitActionQueue (Handle handle) +{ + handle->Set(ACTION_QUEUE_SYMBOL, Array::New()); +} // This is the file system object which contains methods // for accessing the file system (like rename, mkdir, etC). // In javascript it is called "File". static Persistent fs; -class FileSystem { -public: - static Handle Rename (const Arguments& args); - static int AfterRename (eio_req *req); +void +File::Initialize (Handle target) +{ + if (!fs.IsEmpty()) + return; - static Handle Stat (const Arguments& args); - static int AfterStat (eio_req *req); + HandleScope scope; - static Handle StrError (const Arguments& args); -}; + Local file_template = FunctionTemplate::New(File::New); + file_template->InstanceTemplate()->SetInternalFieldCount(1); -class File : node::ObjectWrap { -public: - File (Handle handle); - ~File (); + // file methods + NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_open", File::Open); + NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_close", File::Close); + NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_write", File::Write); + NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_read", File::Read); - static Handle New (const Arguments& args); + file_template->InstanceTemplate()->SetAccessor(ENCODING_SYMBOL, File::GetEncoding, File::SetEncoding); - static Handle Open (const Arguments& args); - static int AfterOpen (eio_req *req); + fs = Persistent::New(file_template->GetFunction()); + InitActionQueue(fs); - static Handle Close (const Arguments& args); - static int AfterClose (eio_req *req); + target->Set(String::NewSymbol("File"), fs); - static Handle Write (const Arguments& args); - static int AfterWrite (eio_req *req); + // file system methods + NODE_SET_METHOD(fs, "_ffi_rename", FileSystem::Rename); + NODE_SET_METHOD(fs, "_ffi_stat", FileSystem::Stat); + NODE_SET_METHOD(fs, "strerror", FileSystem::StrError); + fs->Set(String::NewSymbol("STDIN_FILENO"), Integer::New(STDIN_FILENO)); + fs->Set(String::NewSymbol("STDOUT_FILENO"), Integer::New(STDOUT_FILENO)); + fs->Set(String::NewSymbol("STDERR_FILENO"), Integer::New(STDERR_FILENO)); +} - static Handle Read (const Arguments& args); - static int AfterRead (eio_req *req); +Handle +File::GetEncoding (Local property, const AccessorInfo& info) +{ + File *file = NODE_UNWRAP(File, info.This()); -private: - bool HasUtf8Encoding (void); - int GetFD (void); -}; + if (file->encoding_ == UTF8) + return UTF8_SYMBOL; + else + return RAW_SYMBOL; +} + +void +File::SetEncoding (Local property, Local value, const AccessorInfo& info) +{ + File *file = NODE_UNWRAP(File, info.This()); + + if (value->IsString()) { + Local encoding_string = value->ToString(); + char buf[5]; // need enough room for "utf8" or "raw" + encoding_string->WriteAscii(buf, 0, 4); + buf[4] = '\0'; + file->encoding_ = strcasecmp(buf, "utf8") == 0 ? UTF8 : RAW; + } else { + file->encoding_ = RAW; + } +} static void CallTopCallback (Handle handle, const int argc, Handle argv[]) @@ -87,12 +123,6 @@ CallTopCallback (Handle handle, const int argc, Handle argv[]) poll_actions->Call(handle, 0, NULL); } -static void -InitActionQueue (Handle handle) -{ - handle->Set(ACTION_QUEUE_SYMBOL, Array::New()); -} - Handle FileSystem::Rename (const Arguments& args) { @@ -206,6 +236,7 @@ File::File (Handle handle) : ObjectWrap(handle) { HandleScope scope; + encoding_ = RAW; InitActionQueue(handle); } @@ -434,7 +465,7 @@ File::AfterRead (eio_req *req) argv[1] = Local::New(Null()); } else { size_t length = req->result; - if (file->HasUtf8Encoding()) { + if (file->encoding_ == UTF8) { // utf8 encoding argv[1] = String::New(buf, req->result); } else { @@ -460,33 +491,3 @@ File::New(const Arguments& args) return args.This(); } -void -node::Init_file (Handle target) -{ - if (!fs.IsEmpty()) - return; - - HandleScope scope; - - Local file_template = FunctionTemplate::New(File::New); - file_template->InstanceTemplate()->SetInternalFieldCount(1); - - fs = Persistent::New(file_template->GetFunction()); - InitActionQueue(fs); - - target->Set(String::NewSymbol("File"), fs); - - // file system methods - NODE_SET_METHOD(fs, "_ffi_rename", FileSystem::Rename); - NODE_SET_METHOD(fs, "_ffi_stat", FileSystem::Stat); - NODE_SET_METHOD(fs, "strerror", FileSystem::StrError); - fs->Set(String::NewSymbol("STDIN_FILENO"), Integer::New(STDIN_FILENO)); - fs->Set(String::NewSymbol("STDOUT_FILENO"), Integer::New(STDOUT_FILENO)); - fs->Set(String::NewSymbol("STDERR_FILENO"), Integer::New(STDERR_FILENO)); - - // file methods - NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_open", File::Open); - NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_close", File::Close); - NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_write", File::Write); - NODE_SET_METHOD(file_template->InstanceTemplate(), "_ffi_read", File::Read); -} diff --git a/src/file.h b/src/file.h index 5fe372bb7da..a71b83d73e3 100644 --- a/src/file.h +++ b/src/file.h @@ -5,7 +5,50 @@ namespace node { -void Init_file (v8::Handle target); +class FileSystem { +public: + static v8::Handle Rename (const v8::Arguments& args); + static int AfterRename (eio_req *req); + + static v8::Handle Stat (const v8::Arguments& args); + static int AfterStat (eio_req *req); + + static v8::Handle StrError (const v8::Arguments& args); +}; + +class File : ObjectWrap { +public: + static void Initialize (v8::Handle target); + +protected: + File (v8::Handle handle); + ~File (); + + static v8::Handle New (const v8::Arguments& args); + + static v8::Handle Open (const v8::Arguments& args); + static int AfterOpen (eio_req *req); + + static v8::Handle Close (const v8::Arguments& args); + static int AfterClose (eio_req *req); + + static v8::Handle Write (const v8::Arguments& args); + static int AfterWrite (eio_req *req); + + static v8::Handle Read (const v8::Arguments& args); + static int AfterRead (eio_req *req); + + static v8::Handle GetEncoding (v8::Local property, + const v8::AccessorInfo& info); + static void SetEncoding (v8::Local property, + v8::Local value, + const v8::AccessorInfo& info); + + bool HasUtf8Encoding (void); + int GetFD (void); + + enum encoding encoding_; +}; } // namespace node #endif // node_file_h diff --git a/src/file.js b/src/file.js index 3c0f76aee91..9f654420ab0 100644 --- a/src/file.js +++ b/src/file.js @@ -12,16 +12,22 @@ File.exists = function (path, callback) { }); } -File.cat = function (path, callback) { +File.cat = function (path, encoding, callback) { var content = ""; - var file = new File; + var file = new File(); + file.encoding = "utf8"; var pos = 0; var chunkSize = 10*1024; function readChunk () { file.read(chunkSize, pos, function (status, chunk) { if (chunk) { - content += chunk.encodeUtf8(); + + if (chunk.constructor == String) + content += chunk; + else + content = content.concat(chunk); + pos += chunk.length; readChunk(); } else { diff --git a/src/main.js b/src/main.js index 3b0961fd3e8..95b25999a66 100644 --- a/src/main.js +++ b/src/main.js @@ -134,7 +134,7 @@ clearInterval = clearTimeout; } function loadScript (filename, target, callback) { - File.cat(filename, function (status, content) { + File.cat(filename, "utf8", function (status, content) { if (status != 0) { stderr.puts("Error reading " + filename + ": " + File.strerror(status)); exit(1); diff --git a/src/node.cc b/src/node.cc index cb16453efd4..12b39d9f89f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -265,7 +265,8 @@ main (int argc, char *argv[]) // BUILT-IN MODULES node::Init_timer(g); - node::Init_file(g); + + File::Initialize(g); Acceptor::Initialize(g); Connection::Initialize(g);