Browse Source

Put file stream methods into prototype, small style fixes

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
7faf7d5c8d
  1. 303
      lib/fs.js

303
lib/fs.js

@ -492,99 +492,107 @@ var FileReadStream = fs.FileReadStream = function(path, options) {
options = options || {};
for (var i in options) this[i] = options[i];
var
self = this,
buffer = null;
var self = this;
function read() {
if (!self.readable || self.paused) {
fs.open(this.path, this.flags, this.mode, function(err, fd) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
fs.read(self.fd, self.bufferSize, undefined, self.encoding, function(err, data, bytesRead) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
if (bytesRead === 0) {
self.emit('end');
self.forceClose();
return;
}
// do not emit events if the stream is paused
if (self.paused) {
buffer = data;
return;
}
self.fd = fd;
self.emit('open', fd);
self._read();
});
};
sys.inherits(FileReadStream, events.EventEmitter);
// do not emit events anymore after we declared the stream unreadable
if (!self.readable) {
return;
}
self.emit('data', data);
read();
});
}
FileReadStream.prototype._read = function () {
var self = this;
if (!self.readable || self.paused) return;
fs.open(this.path, this.flags, this.mode, function(err, fd) {
fs.read(self.fd,
self.bufferSize,
undefined,
self.encoding,
function(err, data, bytesRead) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
self.fd = fd;
self.emit('open', fd);
read();
if (bytesRead === 0) {
self.emit('end');
self.forceClose();
return;
}
// do not emit events if the stream is paused
if (self.paused) {
self.buffer = data;
return;
}
// do not emit events anymore after we declared the stream unreadable
if (!self.readable) {
return;
}
self.emit('data', data);
self._read();
});
};
this.forceClose = function(cb) {
this.readable = false;
function close() {
fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(err);
}
self.emit('error', err);
return;
}
FileReadStream.prototype.forceClose = function (cb) {
var self = this;
this.readable = false;
function close() {
fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(null);
cb(err);
}
self.emit('close');
});
}
self.emit('error', err);
return;
}
if (this.fd) {
close();
} else {
this.addListener('open', close);
}
};
if (cb) {
cb(null);
}
self.emit('close');
});
}
if (this.fd) {
close();
} else {
this.addListener('open', close);
}
};
this.pause = function() {
this.paused = true;
};
this.resume = function() {
this.paused = false;
FileReadStream.prototype.pause = function() {
this.paused = true;
};
if (buffer !== null) {
self.emit('data', buffer);
buffer = null;
}
read();
};
FileReadStream.prototype.resume = function() {
this.paused = false;
if (this.buffer) {
this.emit('data', this.buffer);
this.buffer = null;
}
this._read();
};
sys.inherits(FileReadStream, events.EventEmitter);
fs.createWriteStream = function(path, options) {
return new FileWriteStream(path, options);
@ -604,105 +612,108 @@ var FileWriteStream = fs.FileWriteStream = function(path, options) {
options = options || {};
for (var i in options) this[i] = options[i];
var
self = this,
queue = [],
busy = false;
this.busy = false;
this._queue = [];
queue.push([fs.open, this.path, this.flags, this.mode, undefined]);
this._queue.push([fs.open, this.path, this.flags, this.mode, undefined]);
this.flush();
};
sys.inherits(FileWriteStream, events.EventEmitter);
function flush() {
if (busy) {
return;
}
var args = queue.shift();
if (!args) {
return self.emit('drain');
}
busy = true;
FileWriteStream.prototype.flush = function () {
if (this.busy) return;
var self = this;
var
method = args.shift(),
cb = args.pop();
var args = this._queue.shift();
if (!args) return self.emit('drain');
args.push(function(err) {
busy = false;
this.busy = true;
if (err) {
self.writeable = false;
if (cb) {
cb(err);
}
self.emit('error', err);
return;
}
var
method = args.shift(),
cb = args.pop();
// stop flushing after close
if (method === fs.close) {
if (cb) {
cb(null);
}
self.emit('close');
return;
}
var self = this;
// save reference for file pointer
if (method === fs.open) {
self.fd = arguments[1];
self.emit('open', self.fd);
} else if (cb) {
// write callback
cb(null, arguments[1]);
args.push(function(err) {
self.busy = false;
if (err) {
self.writeable = false;
if (cb) {
cb(err);
}
self.emit('error', err);
return;
}
flush();
});
// stop flushing after close
if (method === fs.close) {
if (cb) {
cb(null);
}
self.emit('close');
return;
}
// Inject the file pointer
if (method !== fs.open) {
args.unshift(self.fd);
// save reference for file pointer
if (method === fs.open) {
self.fd = arguments[1];
self.emit('open', self.fd);
} else if (cb) {
// write callback
cb(null, arguments[1]);
}
method.apply(this, args);
};
self.flush();
});
this.write = function(data, cb) {
if (!this.writeable) {
throw new Error('stream not writeable');
}
// Inject the file pointer
if (method !== fs.open) {
args.unshift(self.fd);
}
queue.push([fs.write, data, undefined, this.encoding, cb]);
flush();
return false;
};
method.apply(this, args);
};
this.close = function(cb) {
this.writeable = false;
queue.push([fs.close, cb]);
flush();
};
this.forceClose = function(cb) {
this.writeable = false;
fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(err);
}
FileWriteStream.prototype.write = function(data, cb) {
if (!this.writeable) {
throw new Error('stream not writeable');
}
self.emit('error', err);
return;
}
this._queue.push([fs.write, data, undefined, this.encoding, cb]);
this.flush();
return false;
};
FileWriteStream.prototype.close = function (cb) {
this.writeable = false;
this._queue.push([fs.close, cb]);
this.flush();
};
FileWriteStream.prototype.forceClose = function (cb) {
this.writeable = false;
fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(null);
cb(err);
}
self.emit('close');
});
};
flush();
self.emit('error', err);
return;
}
if (cb) {
cb(null);
}
self.emit('close');
});
};
sys.inherits(FileWriteStream, events.EventEmitter);

Loading…
Cancel
Save