From 8d8d049bc181b18abc76f4ea5acfb40466847fa7 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Sat, 28 Dec 2013 02:52:43 -0800 Subject: [PATCH] Use an Object-based implementation as fallback (close #7, #10) --- index.js | 590 +++++++++++++++++++++++++++++++-------------------- package.json | 3 +- 2 files changed, 364 insertions(+), 229 deletions(-) diff --git a/index.js b/index.js index 950aca9..892c99f 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ var base64 = require('base64-js') +var ieee754 = require('ieee754') exports.Buffer = Buffer exports.SlowBuffer = Buffer @@ -6,20 +7,21 @@ exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 /** - * Detect if browser supports Typed Arrays. Supported browsers are IE 10+, - * Firefox 4+, Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. + * If `browserSupport`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (compatible down to IE6) */ -var browserSupport = (typeof Uint8Array !== 'undefined' - && typeof ArrayBuffer !== 'undefined' && typeof DataView !== 'undefined') +var browserSupport = (function () { + // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, + // Firefox 4+, Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. + if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined' || + typeof DataView === 'undefined') + return false -/** - * Does the browser support adding properties to `Uint8Array` instances? If - * not, then that's the same as no `Uint8Array` support. We need to be able to - * add all the node Buffer API methods. - * - * Relevant Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 - */ -if (!function () { + // Does the browser support adding properties to `Uint8Array` instances? If + // not, then that's the same as no `Uint8Array` support. We need to be able to + // add all the node Buffer API methods. + // Relevant Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 try { var arr = new Uint8Array(0) arr.foo = function () { return 42 } @@ -27,9 +29,8 @@ if (!function () { } catch (e) { return false } -}()) { - browserSupport = false -} +})() + /** * Class: Buffer @@ -43,7 +44,10 @@ if (!function () { * By augmenting the instances, we can avoid modifying the `Uint8Array` * prototype. */ -function Buffer (subject, encoding) { +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + var type = typeof subject // Workaround: node's base64 implementation allows for non-padded strings @@ -66,35 +70,44 @@ function Buffer (subject, encoding) { else throw new Error('First argument needs to be a number, array or string.') + var buf if (browserSupport) { - var buf = augment(new Uint8Array(length)) - - if (Buffer.isBuffer(subject)) { - // Speed optimization -- use set if we're copying from a Uint8Array - buf.set(subject) - } else if (isArrayish(subject)) { - // Treat array-ish objects as a byte array. - for (var i = 0; i < length; i++) { - if (Buffer.isBuffer(subject)) - buf[i] = subject.readUInt8(i) - else - buf[i] = subject[i] - } - } else if (type === 'string') { - buf.write(subject, 0, encoding) - } - - return buf + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = augment(new Uint8Array(length)) } else { - throw new Error('TODO: no support') + // Fallback: Return this instance of Buffer + buf = this + buf.length = length + } + + var i + if (Buffer.isBuffer(subject)) { + // Speed optimization -- use set if we're copying from a Uint8Array + buf.set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + for (i = 0; i < length; i++) { + if (Buffer.isBuffer(subject)) + buf[i] = subject.readUInt8(i) + else + buf[i] = subject[i] + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !browserSupport && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } } + + return buf } // STATIC METHODS // ============== -Buffer.isEncoding = function(encoding) { - switch ((encoding + '').toLowerCase()) { +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': @@ -140,31 +153,28 @@ Buffer.concat = function (list, totalLength) { 'list should be an Array.') } - var i - var buf - if (list.length === 0) { return new Buffer(0) } else if (list.length === 1) { return list[0] } + var i if (typeof totalLength !== 'number') { totalLength = 0 for (i = 0; i < list.length; i++) { - buf = list[i] - totalLength += buf.length + totalLength += list[i].length } } - var buffer = new Buffer(totalLength) + var buf = new Buffer(totalLength) var pos = 0 for (i = 0; i < list.length; i++) { - buf = list[i] - buf.copy(buffer, pos) - pos += buf.length + var item = list[i] + item.copy(buf, pos) + pos += item.length } - return buffer + return buf } // BUFFER INSTANCE METHODS @@ -218,7 +228,7 @@ function _base64Write (buf, string, offset, length) { return Buffer._charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) } -function BufferWrite (string, offset, length, encoding) { +Buffer.prototype.write = function (string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { @@ -267,7 +277,7 @@ function BufferWrite (string, offset, length, encoding) { } } -function BufferToString (encoding, start, end) { +Buffer.prototype.toString = function (encoding, start, end) { var self = this encoding = String(encoding || 'utf8').toLowerCase() @@ -302,7 +312,7 @@ function BufferToString (encoding, start, end) { } } -function BufferToJSON () { +Buffer.prototype.toJSON = function () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) @@ -310,7 +320,7 @@ function BufferToJSON () { } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -function BufferCopy (target, target_start, start, end) { +Buffer.prototype.copy = function (target, target_start, start, end) { var source = this if (!start) start = 0 @@ -396,14 +406,26 @@ function _hexSlice (buf, start, end) { // TODO: add test that modifying the new buffer slice will modify memory in the // original buffer! Use code from: // http://nodejs.org/api/buffer.html#buffer_buf_slice_start_end -function BufferSlice (start, end) { +Buffer.prototype.slice = function (start, end) { var len = this.length start = clamp(start, len, 0) end = clamp(end, len, len) - return augment(this.subarray(start, end)) // Uint8Array built-in method + + if (browserSupport) { + return augment(this.subarray(start, end)) + } else { + // TODO: slicing works, with limitations (no parent tracking/update) + // https://github.com/feross/native-buffer-browserify/issues/9 + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } } -function BufferReadUInt8 (offset, noAssert) { +Buffer.prototype.readUInt8 = function (offset, noAssert) { var buf = this if (!noAssert) { assert(offset !== undefined && offset !== null, 'missing offset') @@ -418,63 +440,99 @@ function BufferReadUInt8 (offset, noAssert) { function _readUInt16 (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 1 === len) { - var dv = new DataView(new ArrayBuffer(2)) - dv.setUint8(0, buf[len - 1]) - return dv.getUint16(0, littleEndian) + + if (browserSupport) { + if (offset + 1 < len) { + return buf._dataview.getUint16(offset, littleEndian) + } else { + var dv = new DataView(new ArrayBuffer(2)) + dv.setUint8(0, buf[len - 1]) + return dv.getUint16(0, littleEndian) + } } else { - return buf._dataview.getUint16(offset, littleEndian) + var val + if (littleEndian) { + val = buf[offset] + if (offset + 1 < len) + val |= buf[offset + 1] << 8 + } else { + val = buf[offset] << 8 + if (offset + 1 < len) + val |= buf[offset + 1] + } + return val } } -function BufferReadUInt16LE (offset, noAssert) { +Buffer.prototype.readUInt16LE = function (offset, noAssert) { return _readUInt16(this, offset, true, noAssert) } -function BufferReadUInt16BE (offset, noAssert) { +Buffer.prototype.readUInt16BE = function (offset, noAssert) { return _readUInt16(this, offset, false, noAssert) } function _readUInt32 (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 3 >= len) { - var dv = new DataView(new ArrayBuffer(4)) - for (var i = 0; i + offset < len; i++) { - dv.setUint8(i, buf[i + offset]) + + if (browserSupport) { + if (offset + 3 < len) { + return buf._dataview.getUint32(offset, littleEndian) + } else { + var dv = new DataView(new ArrayBuffer(4)) + for (var i = 0; i + offset < len; i++) { + dv.setUint8(i, buf[i + offset]) + } + return dv.getUint32(0, littleEndian) } - return dv.getUint32(0, littleEndian) } else { - return buf._dataview.getUint32(offset, littleEndian) + var val + if (littleEndian) { + if (offset + 2 < len) + val = buf[offset + 2] << 16 + if (offset + 1 < len) + val |= buf[offset + 1] << 8 + val |= buf[offset] + if (offset + 3 < len) + val = val + (buf[offset + 3] << 24 >>> 0) + } else { + if (offset + 1 < len) + val = buf[offset + 1] << 16 + if (offset + 2 < len) + val |= buf[offset + 2] << 8 + if (offset + 3 < len) + val |= buf[offset + 3] + val = val + (buf[offset] << 24 >>> 0) + } + return val } } -function BufferReadUInt32LE (offset, noAssert) { +Buffer.prototype.readUInt32LE = function (offset, noAssert) { return _readUInt32(this, offset, true, noAssert) } -function BufferReadUInt32BE (offset, noAssert) { +Buffer.prototype.readUInt32BE = function (offset, noAssert) { return _readUInt32(this, offset, false, noAssert) } -function BufferReadInt8 (offset, noAssert) { +Buffer.prototype.readInt8 = function (offset, noAssert) { var buf = this if (!noAssert) { assert(offset !== undefined && offset !== null, @@ -485,105 +543,136 @@ function BufferReadInt8 (offset, noAssert) { if (offset >= buf.length) return - return buf._dataview.getInt8(offset) + if (browserSupport) { + return buf._dataview.getInt8(offset) + } else { + var neg = buf[offset] & 0x80 + if (neg) + return (0xff - buf[offset] + 1) * -1 + else + return buf[offset] + } } function _readInt16 (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') - assert(offset !== undefined && offset !== null, - 'missing offset') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 1 === len) { - var dv = new DataView(new ArrayBuffer(2)) - dv.setUint8(0, buf[len - 1]) - return dv.getInt16(0, littleEndian) + + if (browserSupport) { + if (offset + 1 === len) { + var dv = new DataView(new ArrayBuffer(2)) + dv.setUint8(0, buf[len - 1]) + return dv.getInt16(0, littleEndian) + } else { + return buf._dataview.getInt16(offset, littleEndian) + } } else { - return buf._dataview.getInt16(offset, littleEndian) + var val = _readUInt16(buf, offset, littleEndian, true) + var neg = val & 0x8000 + if (neg) + return (0xffff - val + 1) * -1 + else + return val } } -function BufferReadInt16LE (offset, noAssert) { +Buffer.prototype.readInt16LE = function (offset, noAssert) { return _readInt16(this, offset, true, noAssert) } -function BufferReadInt16BE (offset, noAssert) { +Buffer.prototype.readInt16BE = function (offset, noAssert) { return _readInt16(this, offset, false, noAssert) } function _readInt32 (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 3 >= len) { - var dv = new DataView(new ArrayBuffer(4)) - for (var i = 0; i + offset < len; i++) { - dv.setUint8(i, buf[i + offset]) + + if (browserSupport) { + if (offset + 3 >= len) { + var dv = new DataView(new ArrayBuffer(4)) + for (var i = 0; i + offset < len; i++) { + dv.setUint8(i, buf[i + offset]) + } + return dv.getInt32(0, littleEndian) + } else { + return buf._dataview.getInt32(offset, littleEndian) } - return dv.getInt32(0, littleEndian) } else { - return buf._dataview.getInt32(offset, littleEndian) + var val = _readUInt32(buf, offset, littleEndian, true) + var neg = val & 0x80000000 + if (neg) + return (0xffffffff - val + 1) * -1 + else + return val } } -function BufferReadInt32LE (offset, noAssert) { +Buffer.prototype.readInt32LE = function (offset, noAssert) { return _readInt32(this, offset, true, noAssert) } -function BufferReadInt32BE (offset, noAssert) { +Buffer.prototype.readInt32BE = function (offset, noAssert) { return _readInt32(this, offset, false, noAssert) } function _readFloat (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') } - return buf._dataview.getFloat32(offset, littleEndian) + if (browserSupport) { + return buf._dataview.getFloat32(offset, littleEndian) + } else { + return ieee754.read(buf, offset, littleEndian, 23, 4) + } } -function BufferReadFloatLE (offset, noAssert) { +Buffer.prototype.readFloatLE = function (offset, noAssert) { return _readFloat(this, offset, true, noAssert) } -function BufferReadFloatBE (offset, noAssert) { +Buffer.prototype.readFloatBE = function (offset, noAssert) { return _readFloat(this, offset, false, noAssert) } function _readDouble (buf, offset, littleEndian, noAssert) { if (!noAssert) { - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') } - return buf._dataview.getFloat64(offset, littleEndian) + if (browserSupport) { + return buf._dataview.getFloat64(offset, littleEndian) + } else { + return ieee754.read(buf, offset, littleEndian, 52, 8) + } } -function BufferReadDoubleLE (offset, noAssert) { +Buffer.prototype.readDoubleLE = function (offset, noAssert) { return _readDouble(this, offset, true, noAssert) } -function BufferReadDoubleBE (offset, noAssert) { +Buffer.prototype.readDoubleBE = function (offset, noAssert) { return _readDouble(this, offset, false, noAssert) } -function BufferWriteUInt8 (value, offset, noAssert) { +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { var buf = this if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') @@ -600,66 +689,82 @@ function BufferWriteUInt8 (value, offset, noAssert) { function _writeUInt16 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'trying to write beyond buffer length') verifuint(value, 0xffff) } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 1 === len) { - var dv = new DataView(new ArrayBuffer(2)) - dv.setUint16(0, value, littleEndian) - buf[offset] = dv.getUint8(0) + + if (browserSupport) { + if (offset + 1 === len) { + var dv = new DataView(new ArrayBuffer(2)) + dv.setUint16(0, value, littleEndian) + buf[offset] = dv.getUint8(0) + } else { + buf._dataview.setUint16(offset, value, littleEndian) + } } else { - buf._dataview.setUint16(offset, value, littleEndian) + for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { + buf[offset + i] = + (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } } } -function BufferWriteUInt16LE (value, offset, noAssert) { +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { _writeUInt16(this, value, offset, true, noAssert) } -function BufferWriteUInt16BE (value, offset, noAssert) { +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { _writeUInt16(this, value, offset, false, noAssert) } function _writeUInt32 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'trying to write beyond buffer length') verifuint(value, 0xffffffff) } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 3 >= len) { - var dv = new DataView(new ArrayBuffer(4)) - dv.setUint32(0, value, littleEndian) - for (var i = 0; i + offset < len; i++) { - buf[i + offset] = dv.getUint8(i) + + var i + if (browserSupport) { + if (offset + 3 >= len) { + var dv = new DataView(new ArrayBuffer(4)) + dv.setUint32(0, value, littleEndian) + for (i = 0; i + offset < len; i++) { + buf[i + offset] = dv.getUint8(i) + } + } else { + buf._dataview.setUint32(offset, value, littleEndian) } } else { - buf._dataview.setUint32(offset, value, littleEndian) + for (i = 0, j = Math.min(len - offset, 4); i < j; i++) { + buf[offset + i] = + (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } } } -function BufferWriteUInt32LE (value, offset, noAssert) { +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { _writeUInt32(this, value, offset, true, noAssert) } -function BufferWriteUInt32BE (value, offset, noAssert) { +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { _writeUInt32(this, value, offset, false, noAssert) } -function BufferWriteInt8 (value, offset, noAssert) { +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { var buf = this if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') @@ -668,110 +773,135 @@ function BufferWriteInt8 (value, offset, noAssert) { verifsint(value, 0x7f, -0x80) } - if (offset >= buf.length) return + if (offset >= buf.length) + return - buf._dataview.setInt8(offset, value) + if (browserSupport) { + buf._dataview.setInt8(offset, value) + } else { + if (value >= 0) + buf.writeUInt8(value, offset, noAssert) + else + buf.writeUInt8(0xff + value + 1, offset, noAssert) + } } function _writeInt16 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') verifsint(value, 0x7fff, -0x8000) } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 1 === len) { - var dv = new DataView(new ArrayBuffer(2)) - dv.setInt16(0, value, littleEndian) - buf[offset] = dv.getUint8(0) + + if (browserSupport) { + if (offset + 1 === len) { + var dv = new DataView(new ArrayBuffer(2)) + dv.setInt16(0, value, littleEndian) + buf[offset] = dv.getUint8(0) + } else { + buf._dataview.setInt16(offset, value, littleEndian) + } } else { - buf._dataview.setInt16(offset, value, littleEndian) + if (value >= 0) + _writeUInt16(buf, value, offset, littleEndian, noAssert) + else + _writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) } } -function BufferWriteInt16LE (value, offset, noAssert) { +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { _writeInt16(this, value, offset, true, noAssert) } -function BufferWriteInt16BE (value, offset, noAssert) { +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { _writeInt16(this, value, offset, false, noAssert) } function _writeInt32 (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') verifsint(value, 0x7fffffff, -0x80000000) } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 3 >= len) { - var dv = new DataView(new ArrayBuffer(4)) - dv.setInt32(0, value, littleEndian) - for (var i = 0; i + offset < len; i++) { - buf[i + offset] = dv.getUint8(i) + + if (browserSupport) { + if (offset + 3 >= len) { + var dv = new DataView(new ArrayBuffer(4)) + dv.setInt32(0, value, littleEndian) + for (var i = 0; i + offset < len; i++) { + buf[i + offset] = dv.getUint8(i) + } + } else { + buf._dataview.setInt32(offset, value, littleEndian) } } else { - buf._dataview.setInt32(offset, value, littleEndian) + if (value >= 0) + _writeUInt32(buf, value, offset, littleEndian, noAssert) + else + _writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) } } -function BufferWriteInt32LE (value, offset, noAssert) { +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { _writeInt32(this, value, offset, true, noAssert) } -function BufferWriteInt32BE (value, offset, noAssert) { +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { _writeInt32(this, value, offset, false, noAssert) } function _writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 3 >= len) { - var dv = new DataView(new ArrayBuffer(4)) - dv.setFloat32(0, value, littleEndian) - for (var i = 0; i + offset < len; i++) { - buf[i + offset] = dv.getUint8(i) + + if (browserSupport) { + if (offset + 3 >= len) { + var dv = new DataView(new ArrayBuffer(4)) + dv.setFloat32(0, value, littleEndian) + for (var i = 0; i + offset < len; i++) { + buf[i + offset] = dv.getUint8(i) + } + } else { + buf._dataview.setFloat32(offset, value, littleEndian) } } else { - buf._dataview.setFloat32(offset, value, littleEndian) + ieee754.write(buf, value, offset, littleEndian, 23, 4) } } -function BufferWriteFloatLE (value, offset, noAssert) { +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { _writeFloat(this, value, offset, true, noAssert) } -function BufferWriteFloatBE (value, offset, noAssert) { +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { _writeFloat(this, value, offset, false, noAssert) } function _writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { assert(value !== undefined && value !== null, 'missing value') - assert(typeof (littleEndian) === 'boolean', - 'missing or invalid endian') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') assert(offset !== undefined && offset !== null, 'missing offset') assert(offset + 7 < buf.length, 'Trying to write beyond buffer length') @@ -779,29 +909,34 @@ function _writeDouble (buf, value, offset, littleEndian, noAssert) { } var len = buf.length - if (offset >= len) { + if (offset >= len) return - } else if (offset + 7 >= len) { - var dv = new DataView(new ArrayBuffer(8)) - dv.setFloat64(0, value, littleEndian) - for (var i = 0; i + offset < len; i++) { - buf[i + offset] = dv.getUint8(i) + + if (browserSupport) { + if (offset + 7 >= len) { + var dv = new DataView(new ArrayBuffer(8)) + dv.setFloat64(0, value, littleEndian) + for (var i = 0; i + offset < len; i++) { + buf[i + offset] = dv.getUint8(i) + } + } else { + buf._dataview.setFloat64(offset, value, littleEndian) } } else { - buf._dataview.setFloat64(offset, value, littleEndian) + ieee754.write(buf, value, offset, littleEndian, 52, 8) } } -function BufferWriteDoubleLE (value, offset, noAssert) { +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { _writeDouble(this, value, offset, true, noAssert) } -function BufferWriteDoubleBE (value, offset, noAssert) { +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { _writeDouble(this, value, offset, false, noAssert) } // fill(value, start=0, end=buffer.length) -function BufferFill (value, start, end) { +Buffer.prototype.fill = function (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length @@ -833,7 +968,7 @@ function BufferFill (value, start, end) { } } -function BufferInspect () { +Buffer.prototype.inspect = function () { var out = [] var len = this.length for (var i = 0; i < len; i++) { @@ -846,8 +981,11 @@ function BufferInspect () { return '' } -// Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. -// Added in Node 0.12. +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Not added to Buffer.prototype since it should only + * be available in browsers that support ArrayBuffer. + */ function BufferToArrayBuffer () { return (new Buffer(this)).buffer } @@ -860,50 +998,49 @@ function stringtrim (str) { return str.replace(/^\s+|\s+$/g, '') } +var BP = Buffer.prototype + function augment (arr) { arr._isBuffer = true // Augment the Uint8Array *instance* (not the class!) with Buffer methods - arr.write = BufferWrite - arr.toString = BufferToString - arr.toLocaleString = BufferToString - arr.toJSON = BufferToJSON - arr.copy = BufferCopy - arr.slice = BufferSlice - arr.readUInt8 = BufferReadUInt8 - arr.readUInt16LE = BufferReadUInt16LE - arr.readUInt16BE = BufferReadUInt16BE - arr.readUInt32LE = BufferReadUInt32LE - arr.readUInt32BE = BufferReadUInt32BE - arr.readInt8 = BufferReadInt8 - arr.readInt16LE = BufferReadInt16LE - arr.readInt16BE = BufferReadInt16BE - arr.readInt32LE = BufferReadInt32LE - arr.readInt32BE = BufferReadInt32BE - arr.readFloatLE = BufferReadFloatLE - arr.readFloatBE = BufferReadFloatBE - arr.readDoubleLE = BufferReadDoubleLE - arr.readDoubleBE = BufferReadDoubleBE - arr.writeUInt8 = BufferWriteUInt8 - arr.writeUInt16LE = BufferWriteUInt16LE - arr.writeUInt16BE = BufferWriteUInt16BE - arr.writeUInt32LE = BufferWriteUInt32LE - arr.writeUInt32BE = BufferWriteUInt32BE - arr.writeInt8 = BufferWriteInt8 - arr.writeInt16LE = BufferWriteInt16LE - arr.writeInt16BE = BufferWriteInt16BE - arr.writeInt32LE = BufferWriteInt32LE - arr.writeInt32BE = BufferWriteInt32BE - arr.writeFloatLE = BufferWriteFloatLE - arr.writeFloatBE = BufferWriteFloatBE - arr.writeDoubleLE = BufferWriteDoubleLE - arr.writeDoubleBE = BufferWriteDoubleBE - arr.fill = BufferFill - arr.inspect = BufferInspect - - // Only add `toArrayBuffer` if the browser supports ArrayBuffer natively - if (browserSupport) - arr.toArrayBuffer = BufferToArrayBuffer + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BufferToArrayBuffer if (arr.byteLength !== 0) arr._dataview = new DataView(arr.buffer, arr.byteOffset, arr.byteLength) @@ -997,25 +1134,22 @@ function decodeUtf8Char (str) { * exceed the maximum allowed value. */ function verifuint (value, max) { - assert(typeof (value) == 'number', 'cannot write a non-number as a number') + assert(typeof value == 'number', 'cannot write a non-number as a number') assert(value >= 0, 'specified a negative value for writing an unsigned value') assert(value <= max, 'value is larger than maximum value for type') assert(Math.floor(value) === value, 'value has a fractional component') } -/* - * A series of checks to make sure we actually have a signed 32-bit number - */ function verifsint(value, max, min) { - assert(typeof (value) == 'number', 'cannot write a non-number as a number') + assert(typeof value == 'number', 'cannot write a non-number as a number') assert(value <= max, 'value larger than maximum allowed value') assert(value >= min, 'value smaller than minimum allowed value') assert(Math.floor(value) === value, 'value has a fractional component') } function verifIEEE754(value, max, min) { - assert(typeof (value) == 'number', 'cannot write a non-number as a number') + assert(typeof value == 'number', 'cannot write a non-number as a number') assert(value <= max, 'value larger than maximum allowed value') assert(value >= min, 'value smaller than minimum allowed value') } diff --git a/package.json b/package.json index cb45469..40a7d85 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "buffer module compatibility for browserify (backed by ArrayBuffer so its fast!)", "main": "index.js", "dependencies": { - "base64-js": "feross/base64-js" + "base64-js": "feross/base64-js", + "ieee754": "~1.1.1" }, "devDependencies": { "benchmark": "*", -- 2.34.1