From 4f1ba54fa333f07cc73f5930fdca3bd270780717 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Fri, 12 Sep 2014 12:17:36 +0100 Subject: [PATCH] significant code reshuffling to match node core style - check for kMaxLength - throw specific Error types (TypeError, RangeError, etc.) - order methods same as in node core - match implementation of some methods better, like toString --- index.js | 358 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 181 insertions(+), 177 deletions(-) diff --git a/index.js b/index.js index 79b8555..40d4ae0 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,9 @@ var isArray = require('is-array') exports.Buffer = Buffer exports.SlowBuffer = Buffer exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff /** * If `Buffer.TYPED_ARRAY_SUPPORT`: @@ -80,7 +82,11 @@ function Buffer (subject, encoding, noZero) { subject = subject.data length = +subject.length > 0 ? Math.floor(+subject.length) : 0 } else - throw new Error('First argument needs to be a number, array or string.') + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') var buf if (Buffer.TYPED_ARRAY_SUPPORT) { @@ -117,8 +123,25 @@ function Buffer (subject, encoding, noZero) { return buf } -// STATIC METHODS -// ============== +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} Buffer.isEncoding = function (encoding) { switch (String(encoding).toLowerCase()) { @@ -139,43 +162,8 @@ Buffer.isEncoding = function (encoding) { } } -Buffer.isBuffer = function (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str.toString() - switch (encoding || 'utf8') { - case 'hex': - ret = str.length / 2 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'base64': - ret = base64ToBytes(str).length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - default: - throw new Error('Unknown encoding') - } - return ret -} - Buffer.concat = function (list, totalLength) { - if (!isArray(list)) throw new Error('Usage: Buffer.concat(list[, length])') + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') if (list.length === 0) { return new Buffer(0) @@ -201,26 +189,118 @@ Buffer.concat = function (list, totalLength) { return buf } -Buffer.compare = function (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) throw new Error('Arguments must be Buffers') - var x = a.length - var y = b.length - for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} - if (i !== len) { - x = a[i] - y = b[i] +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length } - if (x < y) { - return -1 + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } } - if (y < x) { - return 1 +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' } - return 0 + return '' } -// BUFFER INSTANCE METHODS -// ======================= +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 @@ -325,48 +405,7 @@ Buffer.prototype.write = function (string, offset, length, encoding) { ret = utf16leWrite(this, string, offset, length) break default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.prototype.toString = function (encoding, start, end) { - var self = this - - encoding = String(encoding || 'utf8').toLowerCase() - start = Number(start) || 0 - end = (end === undefined) ? self.length : Number(end) - - // Fastpath empty strings - if (end === start) - return '' - - var ret - switch (encoding) { - case 'hex': - ret = hexSlice(self, start, end) - break - case 'utf8': - case 'utf-8': - ret = utf8Slice(self, start, end) - break - case 'ascii': - ret = asciiSlice(self, start, end) - break - case 'binary': - ret = binarySlice(self, start, end) - break - case 'base64': - ret = base64Slice(self, start, end) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = utf16leSlice(self, start, end) - break - default: - throw new Error('Unknown encoding') + throw new TypeError('Unknown encoding: ' + encoding) } return ret } @@ -378,52 +417,6 @@ Buffer.prototype.toJSON = function () { } } -Buffer.prototype.equals = function (b) { - if(!Buffer.isBuffer(b)) throw new Error('Argument must be a Buffer') - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.compare = function (b) { - if (!Buffer.isBuffer(b)) throw new Error('Argument must be a Buffer') - return Buffer.compare(this, b) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (!target_start) target_start = 0 - - // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return - - // Fatal error conditions - if (end < start) throw new Error('sourceEnd < sourceStart') - if (target_start < 0 || target_start >= target.length) - throw new Error('targetStart out of bounds') - if (start < 0 || start >= source.length) throw new Error('sourceStart out of bounds') - if (end < 0 || end > source.length) throw new Error('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 100 || !Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < len; i++) { - target[i + target_start] = this[i + start] - } - } else { - target._set(this.subarray(start, start + len), target_start) - } -} - function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) @@ -521,18 +514,6 @@ Buffer.prototype.slice = function (start, end) { } } -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) -} - /* * Need to make sure that buffer isn't trying to write out of bounds. */ @@ -648,9 +629,9 @@ Buffer.prototype.readDoubleBE = function (offset, noAssert) { } function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new Error('buffer must be a Buffer instance') - if (value > max || value < min) throw new Error('value is out of bounds') - if (offset + ext > buf.length) throw new Error('index out of range') + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') } Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { @@ -795,8 +776,8 @@ Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { } function checkIEEE754 (buf, value, offset, ext, max, min) { - if (value > max || value < min) throw new Error('value is out of bounds') - if (offset + ext > buf.length) throw new Error('index out of range') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { @@ -829,20 +810,56 @@ Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 100 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length - if (end < start) throw new Error('end < start') + if (end < start) throw new TypeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return - if (start < 0 || start >= this.length) throw new Error('start out of bounds') - if (end < 0 || end > this.length) throw new Error('end out of bounds') + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') var i if (typeof value === 'number') { @@ -860,19 +877,6 @@ Buffer.prototype.fill = function (value, start, end) { return this } -Buffer.prototype.inspect = function () { - var out = [] - var len = this.length - for (var i = 0; i < len; i++) { - out[i] = toHex(this[i]) - if (i === exports.INSPECT_MAX_BYTES) { - out[i + 1] = '...' - break - } - } - return '' -} - /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. @@ -889,7 +893,7 @@ Buffer.prototype.toArrayBuffer = function () { return buf.buffer } } else { - throw new Error('Buffer.toArrayBuffer not supported in this browser') + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') } } -- 2.34.1