2012-09-27 18:28:00 +08:00
|
|
|
var Stream = require('stream').Stream;
|
|
|
|
var util = require('util');
|
|
|
|
var CopyFromStream = function () {
|
|
|
|
Stream.apply(this, arguments);
|
|
|
|
this._buffer = new Buffer(0);
|
|
|
|
this._connection = false;
|
|
|
|
this._finished = false;
|
2012-10-08 01:12:52 +08:00
|
|
|
this._finishedSent = false;
|
|
|
|
this._closed = false;
|
2012-09-27 18:28:00 +08:00
|
|
|
this._error = false;
|
2012-10-08 01:12:52 +08:00
|
|
|
this._dataBuffered = false;
|
2012-09-27 18:28:00 +08:00
|
|
|
this.__defineGetter__("writable", this._writable.bind(this));
|
|
|
|
};
|
|
|
|
util.inherits(CopyFromStream, Stream);
|
|
|
|
CopyFromStream.prototype._writable = function () {
|
2012-10-08 01:12:52 +08:00
|
|
|
return !(this._finished || this._error);
|
2013-01-21 21:30:36 +08:00
|
|
|
};
|
2012-09-27 18:28:00 +08:00
|
|
|
CopyFromStream.prototype.startStreamingToConnection = function (connection) {
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._error) {
|
|
|
|
return;
|
|
|
|
}
|
2012-09-27 18:28:00 +08:00
|
|
|
this._connection = connection;
|
2012-10-08 01:12:52 +08:00
|
|
|
this._sendIfConnectionReady();
|
|
|
|
this._endIfNeedAndPossible();
|
2012-09-27 18:28:00 +08:00
|
|
|
};
|
|
|
|
CopyFromStream.prototype._handleChunk = function (string, encoding) {
|
|
|
|
var dataChunk,
|
|
|
|
tmpBuffer;
|
|
|
|
if (string !== undefined) {
|
|
|
|
if (string instanceof Buffer) {
|
|
|
|
dataChunk = string;
|
|
|
|
} else {
|
|
|
|
dataChunk = new Buffer(string, encoding);
|
|
|
|
}
|
|
|
|
if (this._buffer.length) {
|
2013-01-24 08:09:17 +08:00
|
|
|
//Buffer.concat is better, but it's missing
|
2012-09-27 18:28:00 +08:00
|
|
|
//in node v0.6.x
|
2013-01-24 08:09:17 +08:00
|
|
|
tmpBuffer = new Buffer(this._buffer.length + dataChunk.length);
|
|
|
|
this._buffer.copy(tmpBuffer);
|
2012-10-08 01:12:52 +08:00
|
|
|
dataChunk.copy(tmpBuffer, this._buffer.length);
|
2012-09-27 18:28:00 +08:00
|
|
|
this._buffer = tmpBuffer;
|
|
|
|
} else {
|
|
|
|
this._buffer = dataChunk;
|
|
|
|
}
|
|
|
|
}
|
2013-01-24 08:09:17 +08:00
|
|
|
|
2012-09-27 18:28:00 +08:00
|
|
|
return this._sendIfConnectionReady();
|
|
|
|
};
|
|
|
|
CopyFromStream.prototype._sendIfConnectionReady = function () {
|
|
|
|
var dataSent = false;
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._connection) {
|
2012-09-27 18:28:00 +08:00
|
|
|
dataSent = this._connection.sendCopyFromChunk(this._buffer);
|
|
|
|
this._buffer = new Buffer(0);
|
2013-01-24 08:09:17 +08:00
|
|
|
if (this._dataBuffered) {
|
2012-10-08 01:12:52 +08:00
|
|
|
this.emit('drain');
|
|
|
|
}
|
|
|
|
this._dataBuffered = false;
|
|
|
|
} else {
|
|
|
|
this._dataBuffered = true;
|
2012-09-27 18:28:00 +08:00
|
|
|
}
|
|
|
|
return dataSent;
|
|
|
|
};
|
2012-10-08 01:12:52 +08:00
|
|
|
CopyFromStream.prototype._endIfNeedAndPossible = function () {
|
|
|
|
if (this._connection && this._finished && !this._finishedSent) {
|
|
|
|
this._finishedSent = true;
|
2012-09-27 18:28:00 +08:00
|
|
|
this._connection.endCopyFrom();
|
|
|
|
}
|
2013-01-21 21:30:36 +08:00
|
|
|
};
|
2012-09-27 18:28:00 +08:00
|
|
|
CopyFromStream.prototype.write = function (string, encoding) {
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._error || this._finished) {
|
2012-09-27 18:28:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return this._handleChunk.apply(this, arguments);
|
|
|
|
};
|
|
|
|
CopyFromStream.prototype.end = function (string, encondig) {
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._error || this._finished) {
|
2012-09-27 18:28:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._finished = true;
|
|
|
|
if (string !== undefined) {
|
|
|
|
this._handleChunk.apply(this, arguments);
|
2013-01-21 21:30:36 +08:00
|
|
|
}
|
2012-10-08 01:12:52 +08:00
|
|
|
this._endIfNeedAndPossible();
|
2012-09-27 18:28:00 +08:00
|
|
|
};
|
|
|
|
CopyFromStream.prototype.error = function (error) {
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._error || this._closed) {
|
2013-01-24 08:09:17 +08:00
|
|
|
return false;
|
2012-10-08 01:12:52 +08:00
|
|
|
}
|
2012-09-27 18:28:00 +08:00
|
|
|
this._error = true;
|
|
|
|
this.emit('error', error);
|
|
|
|
};
|
|
|
|
CopyFromStream.prototype.close = function () {
|
2012-10-08 01:12:52 +08:00
|
|
|
if (this._error || this._closed) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!this._finishedSent) {
|
|
|
|
throw new Error("seems to be error in code that uses CopyFromStream");
|
|
|
|
}
|
2012-09-27 18:28:00 +08:00
|
|
|
this.emit("close");
|
|
|
|
};
|
|
|
|
var CopyToStream = function () {
|
|
|
|
Stream.apply(this, arguments);
|
|
|
|
this._error = false;
|
|
|
|
this._finished = false;
|
|
|
|
this._paused = false;
|
|
|
|
this.buffer = new Buffer(0);
|
|
|
|
this._encoding = undefined;
|
|
|
|
this.__defineGetter__('readable', this._readable.bind(this));
|
|
|
|
};
|
|
|
|
util.inherits(CopyToStream, Stream);
|
|
|
|
CopyToStream.prototype._outputDataChunk = function () {
|
|
|
|
if (this._paused) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this.buffer.length) {
|
|
|
|
if (this._encoding) {
|
2013-01-19 04:11:16 +08:00
|
|
|
this.emit('data', this.buffer.toString(this._encoding));
|
2012-09-27 18:28:00 +08:00
|
|
|
} else {
|
|
|
|
this.emit('data', this.buffer);
|
|
|
|
}
|
|
|
|
this.buffer = new Buffer(0);
|
2013-01-19 04:11:16 +08:00
|
|
|
}
|
2012-09-27 18:28:00 +08:00
|
|
|
};
|
|
|
|
CopyToStream.prototype._readable = function () {
|
|
|
|
return !this._finished && !this._error;
|
2013-01-21 21:30:36 +08:00
|
|
|
};
|
2012-09-27 18:28:00 +08:00
|
|
|
CopyToStream.prototype.error = function (error) {
|
|
|
|
if (!this.readable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._error = error;
|
|
|
|
if (!this._paused) {
|
|
|
|
this.emit('error', error);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
CopyToStream.prototype.close = function () {
|
|
|
|
if (!this.readable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._finished = true;
|
|
|
|
if (!this._paused) {
|
|
|
|
this.emit("end");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
CopyToStream.prototype.handleChunk = function (chunk) {
|
|
|
|
var tmpBuffer;
|
|
|
|
if (!this.readable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!this.buffer.length) {
|
|
|
|
this.buffer = chunk;
|
|
|
|
} else {
|
|
|
|
tmpBuffer = new Buffer(this.buffer.length + chunk.length);
|
|
|
|
this.buffer.copy(tmpBuffer);
|
|
|
|
chunk.copy(tmpBuffer, this.buffer.length);
|
|
|
|
this.buffer = tmpBuffer;
|
|
|
|
}
|
|
|
|
this._outputDataChunk();
|
|
|
|
};
|
|
|
|
CopyToStream.prototype.pause = function () {
|
|
|
|
if (!this.readable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._paused = true;
|
|
|
|
};
|
|
|
|
CopyToStream.prototype.resume = function () {
|
|
|
|
if (!this._paused) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._paused = false;
|
|
|
|
this._outputDataChunk();
|
|
|
|
if (this._error) {
|
|
|
|
return this.emit('error', this._error);
|
2013-01-24 08:09:17 +08:00
|
|
|
}
|
2012-09-27 18:28:00 +08:00
|
|
|
if (this._finished) {
|
|
|
|
return this.emit('end');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
CopyToStream.prototype.setEncoding = function (encoding) {
|
|
|
|
this._encoding = encoding;
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
CopyFromStream: CopyFromStream,
|
|
|
|
CopyToStream: CopyToStream
|
|
|
|
};
|