diff --git a/LICENSE b/LICENSE
index 8c7b54c7bf..494e37a766 100644
--- a/LICENSE
+++ b/LICENSE
@@ -252,38 +252,6 @@ maintained libraries. The externally maintained libraries used by Node are:
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
-- lib/buffer_ieee754.js. Its license follows:
- """
- // Copyright (c) 2008, Fair Oaks Labs, Inc.
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- //
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
- // may be used to endorse or promote products derived from this software
- // without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- """
-
- lib/punycode.js is copyright 2011 Mathias Bynens
and released under the MIT license.
"""
diff --git a/benchmark/_bench_timer.js b/benchmark/_bench_timer.js
new file mode 100644
index 0000000000..43460945fb
--- /dev/null
+++ b/benchmark/_bench_timer.js
@@ -0,0 +1,88 @@
+/*
+ * This is a simple addition to allow for higher resolution timers.
+ * It can be used to track time for both synchronous or asynchronous
+ * calls. For synchronous calls pass a callback function like so:
+ *
+ * var timer = require('./_bench_timer');
+ *
+ * timer('myTest', function() {
+ * for (var i = 0; i < 1e6; i++)
+ * // ... run something here
+ * }
+ * });
+ *
+ * For asynchronous timers just pass the name. Then run it again with
+ * the same name to finish it:
+ *
+ * timer('checkAsync');
+ * setTimeout(function() {
+ * timer('checkAsync');
+ * }, 300);
+ *
+ * When this happens all currently queued benchmarks will be paused
+ * until the asynchronous benchmark has completed.
+ *
+ * If the benchmark has been run with --expose_gc then the garbage
+ * collector will be run between each test.
+ *
+ * The setTimeout delay can also be changed by passing a value to
+ * timer.delay.
+ */
+
+
+var store = {};
+var order = [];
+var maxLength = 0;
+var processing = false;
+var asyncQueue = 0;
+var GCd = typeof gc !== 'function' ? false : true;
+
+function timer(name, fn) {
+ if (maxLength < name.length)
+ maxLength = name.length;
+ if (!fn) {
+ processing = false;
+ if (!store[name]) {
+ asyncQueue++;
+ store[name] = process.hrtime();
+ return;
+ }
+ displayTime(name, process.hrtime(store[name]));
+ asyncQueue--;
+ } else {
+ store[name] = fn;
+ order.push(name);
+ }
+ if (!processing && asyncQueue <= 0) {
+ processing = true;
+ setTimeout(run, timer.delay);
+ }
+}
+
+timer.delay = 100;
+
+function run() {
+ if (asyncQueue > 0 || order.length <= 0)
+ return;
+ if (GCd) gc();
+ setTimeout(function() {
+ var name = order.shift();
+ var fn = store[name];
+ var ini = process.hrtime();
+ fn();
+ ini = process.hrtime(ini);
+ displayTime(name, ini);
+ run();
+ }, timer.delay);
+}
+
+function displayTime(name, ini) {
+ name += ': ';
+ while (name.length < maxLength + 2)
+ name += ' ';
+ console.log(name + '%s \u00b5s',
+ (~~((ini[0] * 1e6) + (ini[1] / 1e3)))
+ .toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"));
+}
+
+module.exports = timer;
diff --git a/benchmark/buffer_read.js b/benchmark/buffer_read.js
new file mode 100644
index 0000000000..f128bf2226
--- /dev/null
+++ b/benchmark/buffer_read.js
@@ -0,0 +1,97 @@
+const LEN = 1e7;
+const noAssert = process.argv[3] == 'true' ? true
+ : process.argv[3] == 'false' ? false
+ : undefined;
+
+var timer = require('./_bench_timer');
+
+var buff = (process.argv[2] == 'slow') ?
+ (new require('buffer').SlowBuffer(8)) :
+ (new Buffer(8));
+var i;
+
+buff.writeDoubleLE(0, 0, noAssert);
+
+timer('readUInt8', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readUInt8(0, noAssert);
+ }
+});
+
+timer('readUInt16LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readUInt16LE(0, noAssert);
+ }
+});
+
+timer('readUInt16BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readUInt16BE(0, noAssert);
+ }
+});
+
+timer('readUInt32LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readUInt32LE(0, noAssert);
+ }
+});
+
+timer('readUInt32BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readUInt32BE(0, noAssert);
+ }
+});
+
+timer('readInt8', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readInt8(0, noAssert);
+ }
+});
+
+timer('readInt16LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readInt16LE(0, noAssert);
+ }
+});
+
+timer('readInt16BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readInt16BE(0, noAssert);
+ }
+});
+
+timer('readInt32LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readInt32LE(0, noAssert);
+ }
+});
+
+timer('readInt32BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readInt32BE(0, noAssert);
+ }
+});
+
+timer('readFloatLE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readFloatLE(0, noAssert);
+ }
+});
+
+timer('readFloatBE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readFloatBE(0, noAssert);
+ }
+});
+
+timer('readDoubleLE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readDoubleLE(0, noAssert);
+ }
+});
+
+timer('readDoubleBE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.readDoubleBE(0, noAssert);
+ }
+});
diff --git a/benchmark/buffer_write.js b/benchmark/buffer_write.js
new file mode 100644
index 0000000000..70f9926563
--- /dev/null
+++ b/benchmark/buffer_write.js
@@ -0,0 +1,103 @@
+const LEN = 1e7;
+
+const INT8 = 0x7f;
+const INT16 = 0x7fff;
+const INT32 = 0x7fffffff;
+const UINT8 = INT8 * 2;
+const UINT16 = INT16 * 2;
+const UINT32 = INT32 * 2;
+
+const noAssert = process.argv[3] == 'true' ? true
+ : process.argv[3] == 'false' ? false
+ : undefined;
+
+var timer = require('./_bench_timer');
+
+var buff = (process.argv[2] == 'slow') ?
+ (new require('buffer').SlowBuffer(8)) :
+ (new Buffer(8));
+var i;
+
+timer('writeUInt8', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeUInt8(i % UINT8, 0, noAssert);
+ }
+});
+
+timer('writeUInt16LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeUInt16LE(i % UINT16, 0, noAssert);
+ }
+});
+
+timer('writeUInt16BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeUInt16BE(i % UINT16, 0, noAssert);
+ }
+});
+
+timer('writeUInt32LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeUInt32LE(i % UINT32, 0, noAssert);
+ }
+});
+
+timer('writeUInt32BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeUInt32BE(i % UINT32, 0, noAssert);
+ }
+});
+
+timer('writeInt8', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeInt8(i % INT8, 0, noAssert);
+ }
+});
+
+timer('writeInt16LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeInt16LE(i % INT16, 0, noAssert);
+ }
+});
+
+timer('writeInt16BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeInt16BE(i % INT16, 0, noAssert);
+ }
+});
+
+timer('writeInt32LE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeInt32LE(i % INT32, 0, noAssert);
+ }
+});
+
+timer('writeInt32BE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeInt32BE(i % INT32, 0, noAssert);
+ }
+});
+
+timer('writeFloatLE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeFloatLE(i * 0.1, 0, noAssert);
+ }
+});
+
+timer('writeFloatBE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeFloatBE(i * 0.1, 0, noAssert);
+ }
+});
+
+timer('writeDoubleLE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeDoubleLE(i * 0.1, 0, noAssert);
+ }
+});
+
+timer('writeDoubleBE', function() {
+ for (i = 0; i < LEN; i++) {
+ buff.writeDoubleBE(i * 0.1, 0, noAssert);
+ }
+});
diff --git a/benchmark/dataview_set.js b/benchmark/dataview_set.js
new file mode 100644
index 0000000000..d0eca61515
--- /dev/null
+++ b/benchmark/dataview_set.js
@@ -0,0 +1,104 @@
+const LEN = 1e7;
+
+const INT8 = 0x7f;
+const INT16 = 0x7fff;
+const INT32 = 0x7fffffff;
+const UINT8 = INT8 * 2;
+const UINT16 = INT16 * 2;
+const UINT32 = INT32 * 2;
+
+const noAssert = process.argv[3] == 'true' ? true
+ : process.argv[3] == 'false' ? false
+ : undefined;
+
+var timer = require('./_bench_timer');
+
+var buff = (process.argv[2] == 'slow') ?
+ (new require('buffer').SlowBuffer(8)) :
+ (new Buffer(8));
+var dv = new DataView(buff);
+var i;
+
+timer('setUint8', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setUint8(0, i % UINT8);
+ }
+});
+
+timer('setUint16 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setUint16(0, i % UINT16, true);
+ }
+});
+
+timer('setUint16 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setUint16(0, i % UINT16);
+ }
+});
+
+timer('setUint32 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setUint32(0, i % UINT32, true);
+ }
+});
+
+timer('setUint32 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setUint32(0, i % UINT32);
+ }
+});
+
+timer('setInt8', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setInt8(0, i % INT8);
+ }
+});
+
+timer('setInt16 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setInt16(0, i % INT16, true);
+ }
+});
+
+timer('setInt16 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setInt16(0, i % INT16);
+ }
+});
+
+timer('setInt32 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setInt32(0, i % INT32, true);
+ }
+});
+
+timer('setInt32 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setInt32(0, i % INT32);
+ }
+});
+
+timer('setFloat32 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setFloat32(0, i * 0.1, true);
+ }
+});
+
+timer('setFloat32 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setFloat32(0, i * 0.1);
+ }
+});
+
+timer('setFloat64 - LE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setFloat64(0, i * 0.1, true);
+ }
+});
+
+timer('setFloat64 - BE', function() {
+ for (i = 0; i < LEN; i++) {
+ dv.setFloat64(0, i * 0.1);
+ }
+});
diff --git a/lib/buffer.js b/lib/buffer.js
index 4958b31d3a..6fb7a6d993 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -829,46 +829,35 @@ Buffer.prototype.readInt32BE = function(offset, noAssert) {
return readInt32(this, offset, true, noAssert);
};
-function readFloat(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 23, 4);
+function checkOffset(offset, ext, length) {
+ if ((offset % 1) !== 0 || offset < 0)
+ throw new RangeError('offset is not uint');
+ if (offset + ext > length)
+ throw new RangeError('Trying to access beyond buffer length');
}
Buffer.prototype.readFloatLE = function(offset, noAssert) {
- return readFloat(this, offset, false, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 4, this.length);
+ return this.parent.readFloatLE(this.offset + offset, !!noAssert);
};
Buffer.prototype.readFloatBE = function(offset, noAssert) {
- return readFloat(this, offset, true, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 4, this.length);
+ return this.parent.readFloatBE(this.offset + offset, !!noAssert);
};
-function readDouble(buffer, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to read beyond buffer length');
- }
-
- return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
- 52, 8);
-}
-
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
- return readDouble(this, offset, false, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 8, this.length);
+ return this.parent.readDoubleLE(this.offset + offset, !!noAssert);
};
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
- return readDouble(this, offset, true, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 8, this.length);
+ return this.parent.readDoubleBE(this.offset + offset, !!noAssert);
};
@@ -1036,19 +1025,6 @@ function verifsint(value, max, min) {
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
-function verifyIEEE754(value, max, min) {
- assert.ok(typeof (value) == 'number',
- 'cannot write a non-number as a number');
-
- if (isNaN(value) || value === Infinity || value === -Infinity) {
- return;
- }
-
- assert.ok(value <= max, 'value larger than maximum allowed value');
-
- assert.ok(value >= min, 'value smaller than minimum allowed value');
-}
-
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
var buffer = this;
@@ -1103,60 +1079,26 @@ Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
writeInt32(this, value, offset, true, noAssert);
};
-function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 3 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifyIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
- }
-
- require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 23, 4);
-}
-
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, false, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 4, this.length);
+ this.parent.writeFloatLE(value, this.offset + offset, !!noAssert);
};
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
- writeFloat(this, value, offset, true, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 4, this.length);
+ this.parent.writeFloatBE(value, this.offset + offset, !!noAssert);
};
-function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
- if (!noAssert) {
- assert.ok(value !== undefined && value !== null,
- 'missing value');
-
- assert.ok(typeof (isBigEndian) === 'boolean',
- 'missing or invalid endian');
-
- assert.ok(offset !== undefined && offset !== null,
- 'missing offset');
-
- assert.ok(offset + 7 < buffer.length,
- 'Trying to write beyond buffer length');
-
- verifyIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
- }
-
- require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
- 52, 8);
-}
-
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, false, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 8, this.length);
+ this.parent.writeDoubleLE(value, this.offset + offset, !!noAssert);
};
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
- writeDouble(this, value, offset, true, noAssert);
+ if (!noAssert)
+ checkOffset(offset, 8, this.length);
+ this.parent.writeDoubleBE(value, this.offset + offset, !!noAssert);
};
diff --git a/lib/buffer_ieee754.js b/lib/buffer_ieee754.js
deleted file mode 100644
index 943ce7acdf..0000000000
--- a/lib/buffer_ieee754.js
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2008, Fair Oaks Labs, Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-//
-// Modifications to writeIEEE754 to support negative zeroes made by Brian White
-
-exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
- var e, m,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- nBits = -7,
- i = isBE ? 0 : (nBytes - 1),
- d = isBE ? 1 : -1,
- s = buffer[offset + i];
-
- i += d;
-
- e = s & ((1 << (-nBits)) - 1);
- s >>= (-nBits);
- nBits += eLen;
- for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- m = e & ((1 << (-nBits)) - 1);
- e >>= (-nBits);
- nBits += mLen;
- for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
-
- if (e === 0) {
- e = 1 - eBias;
- } else if (e === eMax) {
- return m ? NaN : ((s ? -1 : 1) * Infinity);
- } else {
- m = m + Math.pow(2, mLen);
- e = e - eBias;
- }
- return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
-};
-
-exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
- var e, m, c,
- eLen = nBytes * 8 - mLen - 1,
- eMax = (1 << eLen) - 1,
- eBias = eMax >> 1,
- rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
- i = isBE ? (nBytes - 1) : 0,
- d = isBE ? -1 : 1,
- s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
-
- value = Math.abs(value);
-
- if (isNaN(value) || value === Infinity) {
- m = isNaN(value) ? 1 : 0;
- e = eMax;
- } else {
- e = Math.floor(Math.log(value) / Math.LN2);
- if (value * (c = Math.pow(2, -e)) < 1) {
- e--;
- c *= 2;
- }
- if (e + eBias >= 1) {
- value += rt / c;
- } else {
- value += rt * Math.pow(2, 1 - eBias);
- }
- if (value * c >= 2) {
- e++;
- c /= 2;
- }
-
- if (e + eBias >= eMax) {
- m = 0;
- e = eMax;
- } else if (e + eBias >= 1) {
- m = (value * c - 1) * Math.pow(2, mLen);
- e = e + eBias;
- } else {
- m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
- e = 0;
- }
- }
-
- for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
-
- e = (e << mLen) | m;
- eLen += mLen;
- for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
-
- buffer[offset + i - d] |= s * 128;
-};
diff --git a/node.gyp b/node.gyp
index 64a4ab62ff..b07a1e0cab 100644
--- a/node.gyp
+++ b/node.gyp
@@ -22,7 +22,6 @@
'lib/_linklist.js',
'lib/assert.js',
'lib/buffer.js',
- 'lib/buffer_ieee754.js',
'lib/child_process.js',
'lib/console.js',
'lib/constants.js',
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
index ff7f451a3e..f49524774c 100644
--- a/src/node_buffer.cc
+++ b/src/node_buffer.cc
@@ -28,6 +28,8 @@
#include
#include // memcpy
+#include // float limits
+#include // infinity
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -671,6 +673,137 @@ Handle Buffer::BinaryWrite(const Arguments &args) {
}
+static bool is_big_endian() {
+ const union { uint8_t u8[2]; uint16_t u16; } u = {{0, 1}};
+ return u.u16 == 1 ? true : false;
+}
+
+
+static void swizzle(char* buf, size_t len) {
+ char t;
+ for (size_t i = 0; i < len / 2; ++i) {
+ t = buf[i];
+ buf[i] = buf[len - i - 1];
+ buf[len - i - 1] = t;
+ }
+}
+
+
+inline bool OutOfRangeCheck(float val, double val_tmp) {
+ if ((val_tmp > 0 && (val_tmp > FLT_MAX || val_tmp < FLT_MIN)
+ && val_tmp != INFINITY) ||
+ ((val_tmp < 0 && (val_tmp < -FLT_MAX || val_tmp > -FLT_MIN)
+ && val_tmp != -INFINITY)))
+ return true;
+ return false;
+}
+
+
+template
+Handle ReadFloatGeneric(const Arguments& args) {
+ double offset_tmp = args[0]->NumberValue();
+ int64_t offset = static_cast(offset_tmp);
+ bool doAssert = !args[1]->BooleanValue();
+
+ if (doAssert) {
+ if (offset_tmp != offset || offset < 0)
+ return ThrowTypeError("offset is not uint");
+ size_t len = static_cast(
+ args.This()->GetIndexedPropertiesExternalArrayDataLength());
+ if (offset + sizeof(T) > len)
+ return ThrowRangeError("Trying to read beyond buffer length");
+ }
+
+ T val;
+ char* data = static_cast(
+ args.This()->GetIndexedPropertiesExternalArrayData());
+ char* ptr = data + offset;
+
+ memcpy(&val, ptr, sizeof(T));
+ if (ENDIANNESS != is_big_endian())
+ swizzle(reinterpret_cast(&val), sizeof(T));
+
+ // TODO: when Number::New is updated to accept an Isolate, make the change
+ return Number::New(val);
+}
+
+
+Handle Buffer::ReadFloatLE(const Arguments& args) {
+ return ReadFloatGeneric(args);
+}
+
+
+Handle Buffer::ReadFloatBE(const Arguments& args) {
+ return ReadFloatGeneric(args);
+}
+
+
+Handle Buffer::ReadDoubleLE(const Arguments& args) {
+ return ReadFloatGeneric(args);
+}
+
+
+Handle Buffer::ReadDoubleBE(const Arguments& args) {
+ return ReadFloatGeneric(args);
+}
+
+
+template
+Handle WriteFloatGeneric(const Arguments& args) {
+ bool doAssert = !args[2]->BooleanValue();
+
+ if (doAssert) {
+ if (!args[0]->IsNumber())
+ return ThrowTypeError("value not a number");
+ }
+
+ double val_tmp = args[0]->NumberValue();
+ T val = static_cast(val_tmp);
+ double offset_tmp = args[1]->NumberValue();
+ int64_t offset = static_cast(offset_tmp);
+ char* data = static_cast(
+ args.This()->GetIndexedPropertiesExternalArrayData());
+ char* ptr = data + offset;
+
+ if (doAssert) {
+ if (offset_tmp != offset || offset < 0)
+ return ThrowTypeError("offset is not uint");
+ if (sizeof(T) == 4 && OutOfRangeCheck(val, val_tmp))
+ return ThrowRangeError("value is out of type range");
+ size_t len = static_cast(
+ args.This()->GetIndexedPropertiesExternalArrayDataLength());
+ if (offset + sizeof(T) > len)
+ return ThrowRangeError("Trying to write beyond buffer length");
+ }
+
+ memcpy(ptr, &val, sizeof(T));
+ if (ENDIANNESS != is_big_endian())
+ swizzle(ptr, sizeof(T));
+
+ return Undefined(node_isolate);
+}
+
+
+Handle Buffer::WriteFloatLE(const Arguments& args) {
+ return WriteFloatGeneric(args);
+}
+
+
+Handle Buffer::WriteFloatBE(const Arguments& args) {
+ return WriteFloatGeneric(args);
+}
+
+
+Handle Buffer::WriteDoubleLE(const Arguments& args) {
+ return WriteFloatGeneric(args);
+}
+
+
+Handle Buffer::WriteDoubleBE(const Arguments& args) {
+ return WriteFloatGeneric(args);
+}
+
+
// var nbytes = Buffer.byteLength("string", "utf8")
Handle Buffer::ByteLength(const Arguments &args) {
HandleScope scope;
@@ -814,6 +947,14 @@ void Buffer::Initialize(Handle