Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fs: fs.readFileSync()

  • Loading branch information...
commit 020cf87dba729d00211813634f51d2e63c142a09 1 parent afa12c5
@indutny authored
View
3  candor.io.gyp
@@ -1,7 +1,8 @@
{
'variables': {
'library_files': [
- 'lib/can.can', # This should come first
+ 'lib/can.can',
+ 'lib/fs.can',
'lib/module.can',
]
},
View
26 lib/can.can
@@ -1,27 +1 @@
// Main binding
-log = global.log
-compile = global.compile
-binding = global.binding
-fs = global._bindings.fs
-buffer = global._bindings.buffer
-
-log("Hello world!")
-
-buff = buffer.new(1024)
-
-fd = fs.open("/tmp/3.txt", fs.flags.O_RDONLY, 438)
-if (fd < 0) {
- log("fail!")
- return
-}
-
-fs.read(fd, buff, 0, 1024, (err, bytes) {
- log(bytes)
- fs.close(fd)
-
- buff = buffer.slice(buff, 0, bytes)
-
- log(buffer.stringify(buff))
-})
-
-return { yay: true }
View
36 lib/fs.can
@@ -0,0 +1,36 @@
+// FS module
+exports = {}
+fs = global._bindings.fs
+buffer = global._bindings.buffer
+
+exports.readFileSync = (filename) {
+ fd = fs.open(filename, fs.flags.O_RDONLY, 438)
+
+ stat = fs.stat(filename)
+ if (stat == nil) return
+
+ size = stat.size
+ buffs = []
+ buff_len = 0
+ total = 0
+ while (size > 0) {
+ buff = buffer.new(size)
+ bytesRead = fs.read(fd, buff, size, -1)
+
+ if (bytesRead == 0) break
+ buffs[buff_len++] = buff
+ total = total + bytesRead
+
+ if (bytesRead == size) {
+ size = 8 * 1024
+ } else {
+ size = 0
+ }
+ }
+
+ fs.close(fd)
+
+ return buffer.concat(buffs, total)
+}
+
+return exports
View
4 lib/module.can
@@ -1 +1,5 @@
// Module
+buffer = global._bindings.buffer
+fs = global._natives.fs
+
+global.log(buffer.stringify(fs.readFileSync('/tmp/3.txt')))
View
56 src/bindings/buffer.cc
@@ -48,17 +48,15 @@ Value* Buffer::Slice(uint32_t argc, Value** argv) {
if (argc < 1 || !Buffer::HasInstance(argv[0])) return Nil::New();
Buffer* b = CWrapper::Unwrap<Buffer>(argv[0]);
- Buffer* c;
+ Buffer* c = new Buffer(0);
+
if (argc == 1) {
- // Just return a copy
- c = new Buffer(b->size());
- memcpy(c->data(), b->data(), b->size());
+ // Just return a buffer
} else if (argc >= 2 && argv[1]->Is<Number>()) {
int begin = argv[1]->As<Number>()->IntegralValue();
- // Oob - return empty buffer
if (begin > b->size()) {
- c = new Buffer(0);
+ // Oob - return empty buffer
} else if (argc >= 3 && argv[2]->Is<Number>()) {
int end = argv[2]->As<Number>()->IntegralValue();
@@ -66,25 +64,61 @@ Value* Buffer::Slice(uint32_t argc, Value** argv) {
// slice(10, 1) or slice(10, 10)
if (end <= begin) {
- c = new Buffer(0);
+ // Empty buffer
} else {
- c = new Buffer(end - begin);
- memcpy(c->data(), b->data() + begin, end - begin);
+ c->size_ = end - begin;
+ c->data_ = b->data_ + begin;
}
} else {
- c = new Buffer(b->size() - begin);
- memcpy(c->data(), b->data() + begin, b->size() - begin);
+ c->size_ = b->size() - begin;
+ c->data_ = b->data_ + begin;
}
}
return c->Wrap();
}
+Value* Buffer::Concat(uint32_t argc, Value** argv) {
+ if (argc < 1 || !argv[0]->Is<Array>()) return Nil::New();
+
+ Array* arr = argv[0]->As<Array>();
+ int total = 0;
+
+ if (argc < 2 || !argv[1]->Is<Number>()) {
+ // Calculate total
+ for (int i = 0; i < arr->Length(); i++) {
+ if (!Buffer::HasInstance(arr->Get(i))) continue;
+ Buffer* current = CWrapper::Unwrap<Buffer>(arr->Get(i));
+
+ total += current->size();
+ }
+ } else {
+ total = argv[1]->As<Number>()->IntegralValue();
+ }
+
+ Buffer* result = new Buffer(total);
+ int offset = 0;
+ for (int i = 0; i < arr->Length(); i++) {
+ if (!Buffer::HasInstance(arr->Get(i))) continue;
+ Buffer* current = CWrapper::Unwrap<Buffer>(arr->Get(i));
+
+ int bytes = current->size();
+ if (offset + bytes > result->size()) bytes = result->size() - offset;
+
+ memcpy(result->data(), current->data(), bytes);
+ offset += bytes;
+ }
+
+ return result->Wrap();
+}
+
+
void Buffer::Init(Object* target) {
target->Set("new", Function::New(Buffer::New));
target->Set("length", Function::New(Buffer::Length));
target->Set("stringify", Function::New(Buffer::Stringify));
target->Set("slice", Function::New(Buffer::Slice));
+ target->Set("concat", Function::New(Buffer::Concat));
}
} // namespace can
View
10 src/bindings/buffer.h
@@ -21,10 +21,6 @@ class Buffer : public candor::CWrapper {
inline char* data() { return data_; }
inline ssize_t size() { return size_; }
- static candor::Value* New(uint32_t argc, candor::Value** argv);
- static candor::Value* Length(uint32_t argc, candor::Value** argv);
- static candor::Value* Stringify(uint32_t argc, candor::Value** argv);
- static candor::Value* Slice(uint32_t argc, candor::Value** argv);
static void Init(candor::Object* target);
static bool HasInstance(candor::Value* value);
@@ -33,6 +29,12 @@ class Buffer : public candor::CWrapper {
static const int magic;
protected:
+ static candor::Value* New(uint32_t argc, candor::Value** argv);
+ static candor::Value* Length(uint32_t argc, candor::Value** argv);
+ static candor::Value* Stringify(uint32_t argc, candor::Value** argv);
+ static candor::Value* Slice(uint32_t argc, candor::Value** argv);
+ static candor::Value* Concat(uint32_t argc, candor::Value** argv);
+
char* data_;
ssize_t size_;
};
View
136 src/bindings/fs.cc
@@ -12,29 +12,27 @@ using namespace candor;
const int FSWrap::magic = 0;
-#define SYNC_CALL(method, res, ...) \
- { \
- uv_fs_t req; \
- res = uv_fs_##method(uv_default_loop(), \
- &req, \
- __VA_ARGS__, \
- NULL); \
- }
+#define SYNC_CALL(method, ...) \
+ uv_fs_t _req; \
+ _req.result = uv_fs_##method(uv_default_loop(), \
+ &_req, \
+ __VA_ARGS__, \
+ NULL);
+
+#define SYNC_REQ (&_req)
#define ASYNC_CALL(method, cb, ...) \
- { \
- FSWrap* wrap = new FSWrap(cb); \
- int r = uv_fs_##method(uv_default_loop(), \
- wrap->req(), \
- __VA_ARGS__, \
- FSWrap::HandleCallback); \
- if (r) { \
- Value* argv[2] = { \
- String::New("FS request failed"), \
- Number::NewIntegral(r) \
- }; \
- cb->Call(2, argv); \
- } \
+ FSWrap* wrap = new FSWrap(cb); \
+ int r = uv_fs_##method(uv_default_loop(), \
+ wrap->req(), \
+ __VA_ARGS__, \
+ FSWrap::HandleCallback); \
+ if (r) { \
+ Value* argv[2] = { \
+ String::New("FS request failed"), \
+ Number::NewIntegral(r) \
+ }; \
+ cb->Call(2, argv); \
}
FSWrap::FSWrap(Function* cb) : CWrapper(&magic), cb_(cb) {
@@ -51,10 +49,32 @@ FSWrap::~FSWrap() {
}
+Object* FSWrap::GetStatObject(uv_fs_t* req) {
+ Object* res = Object::New();
+
+ assert(req->fs_type == UV_FS_STAT);
+ uv_statbuf_t* s = reinterpret_cast<uv_statbuf_t*>(req->ptr);
+
+ res->Set("uid", Number::NewIntegral(s->st_uid));
+ res->Set("gid", Number::NewIntegral(s->st_gid));
+ res->Set("size", Number::NewIntegral(s->st_size));
+ res->Set("atime", Number::NewIntegral(s->st_atime));
+ res->Set("mtime", Number::NewIntegral(s->st_mtime));
+ res->Set("ctime", Number::NewIntegral(s->st_ctime));
+
+ return res;
+}
+
+
void FSWrap::HandleCallback(uv_fs_t* req) {
FSWrap* wrap = reinterpret_cast<FSWrap*>(req->data);
Value* argv[2] = { Nil::New(), Number::NewIntegral(req->result) };
+
+ if (req->fs_type == UV_FS_STAT) {
+ argv[1] = GetStatObject(req);
+ }
+
wrap->cb_->Call(2, argv);
wrap->cb_.Unref();
wrap->Unref();
@@ -97,11 +117,10 @@ Value* FS::Open(uint32_t argc, Value** argv) {
return Nil::New();
} else {
- int r;
- SYNC_CALL(open, r, path, flags, mode);
+ SYNC_CALL(open, path, flags, mode);
delete[] path;
- return Number::NewIntegral(r);
+ return Number::NewIntegral(SYNC_REQ->result);
}
}
@@ -119,9 +138,8 @@ Value* FS::Close(uint32_t argc, Value** argv) {
ASYNC_CALL(close, cb, fd);
return Nil::New();
} else {
- int r;
- SYNC_CALL(close, r, fd);
- return Number::NewIntegral(r);
+ SYNC_CALL(close, fd);
+ return Number::NewIntegral(SYNC_REQ->result);
}
}
@@ -138,8 +156,8 @@ Value* FS::Read(uint32_t argc, Value** argv) {
int fd = argv[0]->As<Number>()->IntegralValue();
Buffer* buff = CWrapper::Unwrap<Buffer>(argv[1]);
- int offset = argv[2]->As<Number>()->IntegralValue();
- int len = argv[3]->As<Number>()->IntegralValue();
+ int len = argv[2]->As<Number>()->IntegralValue();
+ int offset = argv[3]->As<Number>()->IntegralValue();
assert(offset + len <= buff->size());
@@ -148,9 +166,61 @@ Value* FS::Read(uint32_t argc, Value** argv) {
ASYNC_CALL(read, cb, fd, buff->data(), len, offset);
return Nil::New();
} else {
- int r;
- SYNC_CALL(read, r, fd, buff->data(), len, offset);
- return Number::NewIntegral(r);
+ SYNC_CALL(read, fd, buff->data(), len, offset);
+ return Number::NewIntegral(SYNC_REQ->result);
+ }
+}
+
+
+Value* FS::Write(uint32_t argc, Value** argv) {
+ // Input constraints
+ if (argc < 4 ||
+ !argv[0]->Is<Number>() ||
+ !Buffer::HasInstance(argv[1]) ||
+ !argv[2]->Is<Number>() ||
+ !argv[3]->Is<Number>()) {
+ return Nil::New();
+ }
+
+ int fd = argv[0]->As<Number>()->IntegralValue();
+ Buffer* buff = CWrapper::Unwrap<Buffer>(argv[1]);
+ int len = argv[2]->As<Number>()->IntegralValue();
+ int offset = argv[3]->As<Number>()->IntegralValue();
+
+ assert(offset + len <= buff->size());
+
+ if (argc >= 5 && argv[4]->Is<Function>()) {
+ Function* cb = argv[4]->As<Function>();
+ ASYNC_CALL(write, cb, fd, buff->data(), len, offset);
+ return Nil::New();
+ } else {
+ SYNC_CALL(write, fd, buff->data(), len, offset);
+ return Number::NewIntegral(SYNC_REQ->result);
+ }
+}
+
+
+Value* FS::Stat(uint32_t argc, Value** argv) {
+ // Input constraints
+ if (argc < 1 ||
+ !argv[0]->Is<String>()) {
+ return Nil::New();
+ }
+
+ char* path = StringToChar(argv[0]);
+ if (argc >= 2 && argv[1]->Is<Function>()) {
+ Function* cb = argv[1]->As<Function>();
+ ASYNC_CALL(stat, cb, path);
+ delete[] path;
+
+ return Nil::New();
+ } else {
+ SYNC_CALL(stat, path);
+ delete[] path;
+
+ if (SYNC_REQ->result) return Nil::New();
+
+ return FSWrap::GetStatObject(SYNC_REQ);
}
}
@@ -169,6 +239,8 @@ void FS::Init(Object* target) {
target->Set("open", Function::New(Open));
target->Set("close", Function::New(Close));
target->Set("read", Function::New(Read));
+ target->Set("write", Function::New(Write));
+ target->Set("stat", Function::New(Stat));
}
} // namespace can
View
3  src/bindings/fs.h
@@ -11,6 +11,7 @@ class FSWrap : public candor::CWrapper {
FSWrap(candor::Function* cb);
~FSWrap();
+ static candor::Object* GetStatObject(uv_fs_t* req);
static void HandleCallback(uv_fs_t* req);
inline uv_fs_t* req() { return req_; }
@@ -32,6 +33,8 @@ class FS {
static candor::Value* Open(uint32_t argc, candor::Value** argv);
static candor::Value* Close(uint32_t argc, candor::Value** argv);
static candor::Value* Read(uint32_t argc, candor::Value** argv);
+ static candor::Value* Write(uint32_t argc, candor::Value** argv);
+ static candor::Value* Stat(uint32_t argc, candor::Value** argv);
};
} // namespace can
View
5 src/natives.cc
@@ -19,6 +19,11 @@ void LoadNatives() {
Function* fn = Function::New(can_natives[i].name,
can_natives[i].source,
can_natives[i].size);
+
+ if (Isolate::GetCurrent()->HasError()) {
+ Isolate::GetCurrent()->PrintError();
+ abort();
+ }
fn->SetContext(GetRuntime());
// Put interface into _natives hashmap
Please sign in to comment.
Something went wrong with that request. Please try again.