From d69a26b9650df7dc1f210c3c59df74ec4245dff3 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Mon, 18 Feb 2013 23:52:34 -0800 Subject: [PATCH] buffer: check logic simplification Checks have been simplified and optimized for most-used cases. Calling Buffer with another Buffer as the subject will now use the SlowBuffer Copy method instead of the for loop. No need to call for value coercion, just place the ternary inline. --- lib/buffer.js | 53 ++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index ca4fedf517..3378dcebfc 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -30,7 +30,7 @@ SlowBuffer.prototype.__proto__ = Buffer.prototype; function clamp(index, len, defaultValue) { - if (typeof index === 'undefined') return defaultValue; + if (typeof index !== 'number') return defaultValue; index = ~~index; // Coerce to integer. if (index >= len) return len; if (index >= 0) return index; @@ -49,7 +49,7 @@ function toHex(n) { SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; - if (typeof end == 'undefined') end = this.length; + if (typeof end !== 'number') end = this.length; // Fastpath empty strings if (+end == start) { @@ -150,15 +150,6 @@ SlowBuffer.prototype.slice = function(start, end) { }; -function coerce(length) { - // Coerce length to a number (possibly NaN), round up - // in case it's fractional (e.g. 123.456). Since NaN - // comparisons are always false, use to return zero. - length = Math.ceil(+length); - return length > 0 ? length : 0; -} - - var zeroBuffer = new SlowBuffer(0); // Buffer @@ -175,22 +166,22 @@ function Buffer(subject, encoding, offset) { throw new TypeError('First argument must be a Buffer when slicing'); } - this.length = coerce(encoding); + this.length = +encoding > 0 ? Math.ceil(encoding) : 0; this.parent = subject.parent ? subject.parent : subject; this.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': - this.length = coerce(subject); + this.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': this.length = Buffer.byteLength(subject, encoding); break; - case 'object': // Assume object is an array - this.length = coerce(subject.length); + case 'object': // Assume object is array-ish + this.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: @@ -217,14 +208,24 @@ function Buffer(subject, encoding, offset) { this.offset = 0; } - // Treat array-ish objects as a byte array. - if (isArrayIsh(subject)) { - for (var i = 0; i < this.length; i++) { - this.parent[i + this.offset] = subject[i]; + // optimize by branching logic for new allocations + if (typeof subject !== 'number') { + if (type === 'string') { + // We are a string + this.length = this.write(subject, 0, encoding); + // if subject is buffer then use built-in copy method + } else if (Buffer.isBuffer(subject)) { + if (subject.parent) + subject.parent.copy(this.parent, + this.offset, + subject.offset, + this.length + subject.offset); + else + subject.copy(this.parent, this.offset, 0, this.length); + } else if (isArrayIsh(subject)) { + for (var i = 0; i < this.length; i++) + this.parent[i + this.offset] = subject[i]; } - } else if (type == 'string') { - // We are a string - this.length = this.write(subject, 0, encoding); } } @@ -232,7 +233,7 @@ function Buffer(subject, encoding, offset) { } function isArrayIsh(subject) { - return Array.isArray(subject) || Buffer.isBuffer(subject) || + return Array.isArray(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } @@ -388,13 +389,13 @@ Buffer.prototype.toJSON = function() { Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); - if (typeof start == 'undefined' || start < 0) { + if (typeof start !== 'number' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } - if (typeof end == 'undefined' || end > this.length) { + if (typeof end !== 'number' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; @@ -445,7 +446,7 @@ Buffer.prototype.fill = function fill(value, start, end) { if (typeof value === 'string') { value = value.charCodeAt(0); } - if (!(typeof value === 'number') || isNaN(value)) { + if (typeof value !== 'number' || isNaN(value)) { throw new TypeError('value is not a number'); }