You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.7 KiB

File.rename = function (file1, file2, callback) {
this._addAction("rename", [file1, file2], callback);
};
File.stat = function (path, callback) {
this._addAction("stat", [path], callback);
};
File.exists = function (path, callback) {
this._addAction("stat", [path], function (status) {
callback(status == 0);
});
}
File.cat = function (path, encoding, callback) {
var file = new File();
file.encoding = encoding;
var content = "";
if (file.encoding == "raw") content = [];
var pos = 0;
var chunkSize = 10*1024;
16 years ago
function readChunk () {
file.read(chunkSize, pos, function (status, chunk) {
16 years ago
if (chunk) {
if (chunk.constructor == String)
content += chunk;
else
content = content.concat(chunk);
pos += chunk.length;
16 years ago
readChunk();
} else {
callback(0, content);
file.close();
}
});
}
file.open(path, "r", function (status) {
if (status == 0)
readChunk();
else
callback (status);
});
}
File.prototype.puts = function (data, callback) {
this.write(data + "\n", -1, callback);
};
File.prototype.print = function (data, callback) {
this.write(data, -1, callback);
};
File.prototype.open = function (path, mode, callback) {
this._addAction("open", [path, mode], callback);
};
File.prototype.close = function (callback) {
this._addAction("close", [], callback);
};
File.prototype.write = function (buf, pos, callback) {
this._addAction("write", [buf, pos], callback);
};
File.prototype.read = function (length, pos, callback) {
this._addAction("read", [length, pos], callback);
};
// Some explanation of the File binding.
//
// All file operations are blocking. To get around this they are executed
// in a thread pool in C++ (libeio).
//
// The ordering of method calls to a file should be preserved, so they are
// only executed one at a time. A queue, called _actionQueue is employed.
//
// The constructor File() is implemented in C++. It initlizes
// the member _actionQueue = []
//
// Any of the methods called on a file are put into this queue. When they
// reach the head of the queue they will be executed. C++ calles the
// method _pollActions each time it becomes idle. If there is no action
// currently being executed then _pollActions will not be called. Thus when
// actions are added to an empty _actionQueue, they should be immediately
// executed.
//
// When an action has completed, the C++ side is going to look at the first
// element of _actionQueue in order to get a handle on the callback
// function. Only after that completion callback has been made can the
// action be shifted out of the queue.
//
// See File::CallTopCallback() in file.cc to see the other side of the
// binding.
File._addAction = File.prototype._addAction = function (method, args, callback) {
this._actionQueue.push({ method: method
, callback: callback
, args: args
});
if (this._actionQueue.length == 1) this._act();
}
File._act = File.prototype._act = function () {
var action = this._actionQueue[0];
if (action)
// TODO FIXME what if the action throws an error?
this["_ffi_" + action.method].apply(this, action.args);
};
// called from C++ after each action finishes
// (i.e. when it returns from the thread pool)
File._pollActions = File.prototype._pollActions = function () {
this._actionQueue.shift();
this._act();
};
var stdout = new File();
stdout.fd = File.STDOUT_FILENO;
var stderr = new File();
stderr.fd = File.STDERR_FILENO;
var stdin = new File();
stdin.fd = File.STDIN_FILENO;
this.puts = function (data, callback) {
stdout.puts(data, callback);
}
this.p = function (data, callback) {
puts(JSON.stringify(data), callback);
}