var util = require("util"), | |
stream = require("stream"), | |
constants = require("./constants"); | |
// TODO: clear up specs on returning false from a write and emitting a drain event. | |
// Does this mean if I return false from a write, I should ignore any write requests between that false return and the drain event? | |
var WritableStreamBuffer = module.exports = function(opts) { | |
var that = this; | |
stream.Stream.call(this); | |
opts = opts || {}; | |
var initialSize = opts.initialSize || constants.DEFAULT_INITIAL_SIZE; | |
var incrementAmount = opts.incrementAmount || constants.DEFAULT_INCREMENT_AMOUNT; | |
var buffer = new Buffer(initialSize); | |
var size = 0; | |
this.writable = true; | |
this.readable = false; | |
this.size = function() { | |
return size; | |
}; | |
this.maxSize = function() { | |
return buffer.length; | |
}; | |
this.getContents = function(length) { | |
if(!size) return false; | |
var data = new Buffer(Math.min(length || size, size)); | |
buffer.copy(data, 0, 0, data.length); | |
if(data.length < size) | |
buffer.copy(buffer, 0, data.length); | |
size -= data.length; | |
return data; | |
}; | |
this.getContentsAsString = function(encoding, length) { | |
if(!size) return false; | |
var data = buffer.toString(encoding || "utf8", 0, Math.min(length || size, size)); | |
var dataLength = Buffer.byteLength(data); | |
if(dataLength < size) | |
buffer.copy(buffer, 0, dataLength); | |
size -= dataLength; | |
return data; | |
}; | |
var increaseBufferIfNecessary = function(incomingDataSize) { | |
if((buffer.length - size) < incomingDataSize) { | |
var factor = Math.ceil((incomingDataSize - (buffer.length - size)) / incrementAmount); | |
var newBuffer = new Buffer(buffer.length + (incrementAmount * factor)); | |
buffer.copy(newBuffer, 0, 0, size); | |
buffer = newBuffer; | |
} | |
}; | |
this.write = function(data, encoding) { | |
if(!that.writable) return; | |
if(Buffer.isBuffer(data)) { | |
increaseBufferIfNecessary(data.length); | |
data.copy(buffer, size, 0); | |
size += data.length; | |
} | |
else { | |
data = data + ""; | |
increaseBufferIfNecessary(data.length); | |
buffer.write(data, size, encoding || "utf8"); | |
size += Buffer.byteLength(data); | |
} | |
}; | |
this.end = function() { | |
var args = Array.prototype.slice.apply(arguments); | |
if(args.length) that.write.apply(that, args); | |
that.destroy(); | |
}; | |
this.destroySoon = this.destroy = function() { | |
that.writable = false; | |
that.emit("close"); | |
}; | |
}; | |
util.inherits(WritableStreamBuffer, stream.Stream); |