]> zoso.dev Git - buffer.git/commitdiff
Buffer backed by Uint8Array for insane performance!
authorFeross Aboukhadijeh <feross@feross.org>
Mon, 18 Nov 2013 09:44:50 +0000 (01:44 -0800)
committerFeross Aboukhadijeh <feross@feross.org>
Mon, 18 Nov 2013 09:44:50 +0000 (01:44 -0800)
buffer_ieee754.js [deleted file]
index.js
package.json
test/basic.js [new file with mode: 0644]
test/buffer.js

diff --git a/buffer_ieee754.js b/buffer_ieee754.js
deleted file mode 100644 (file)
index fb295c0..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-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;
-};
index 89c5d27862dc56a33b8ea01be355deb7483db7d0..f46a91a2131cee02eb1007e307cef169ac584dc4 100644 (file)
--- a/index.js
+++ b/index.js
-var assert;
-exports.Buffer = Buffer;
-exports.SlowBuffer = Buffer;
-Buffer.poolSize = 8192;
-exports.INSPECT_MAX_BYTES = 50;
+var assert
+exports.Buffer = Buffer
+exports.SlowBuffer = Buffer
+exports.INSPECT_MAX_BYTES = 50
+Buffer.poolSize = 8192
 
-function stringtrim(str) {
-  if (str.trim) return str.trim();
-  return str.replace(/^\s+|\s+$/g, '');
-}
+// TODO: throw the correct exception type on errors (look at node source)
 
-function Buffer(subject, encoding, offset) {
-  if(!assert) assert= require('assert');
-  if (!(this instanceof Buffer)) {
-    return new Buffer(subject, encoding, offset);
-  }
-  this.parent = this;
-  this.offset = 0;
+function Buffer (subject, encoding) {
+  if (!assert) assert = require('assert')
 
   // Work-around: node's base64 implementation
   // allows for non-padded strings while base64-js
   // does not..
   if (encoding == "base64" && typeof subject == "string") {
-    subject = stringtrim(subject);
-    while (subject.length % 4 != 0) {
-      subject = subject + "="
+    subject = stringtrim(subject)
+    while (subject.length % 4 !== 0) {
+      subject = subject + "="
     }
   }
 
-  var type;
+  // Find the length
+  var type = typeof subject
+  var length
+  if (type === 'number')
+    length = coerce(subject)
+  else if (type === 'string')
+    length = Buffer.byteLength(subject, encoding)
+  else if (type === 'object')
+    length = coerce(subject.length); // Assume object is an array
+  else
+    throw new Error('First argument needs to be a number, array or string.')
 
-  // Are we slicing?
-  if (typeof offset === 'number') {
-    this.length = coerce(encoding);
-    // slicing works, with limitations (no parent tracking/update)
-    // check https://github.com/toots/buffer-browserify/issues/19
-    for (var i = 0; i < this.length; i++) {
-        this[i] = subject.get(i+offset);
-    }
-  } else {
-    // Find the length
-    switch (type = typeof subject) {
-      case 'number':
-        this.length = coerce(subject);
-        break;
-
-      case 'string':
-        this.length = Buffer.byteLength(subject, encoding);
-        break;
-
-      case 'object': // Assume object is an array
-        this.length = coerce(subject.length);
-        break;
-
-      default:
-        throw new Error('First argument needs to be a number, ' +
-                        'array or string.');
-    }
+  var buf = augment(new Uint8Array(length))
 
+  if (isArrayIsh(subject)) {
     // Treat array-ish objects as a byte array.
-    if (isArrayIsh(subject)) {
-      for (var i = 0; i < this.length; i++) {
-        if (subject instanceof Buffer) {
-          this[i] = subject.readUInt8(i);
-        }
-        else {
-          this[i] = subject[i];
-        }
-      }
-    } else if (type == 'string') {
-      // We are a string
-      this.length = this.write(subject, 0, encoding);
-    } else if (type === 'number') {
-      for (var i = 0; i < this.length; i++) {
-        this[i] = 0;
-      }
+    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)
   }
-}
 
-Buffer.prototype.get = function get(i) {
-  if (i < 0 || i >= this.length) throw new Error('oob');
-  return this[i];
-};
+  return buf
+}
 
-Buffer.prototype.set = function set(i, v) {
-  if (i < 0 || i >= this.length) throw new Error('oob');
-  return this[i] = v;
-};
+// STATIC METHODS
+// ==============
 
-Buffer.byteLength = function (str, encoding) {
-  switch (encoding || "utf8") {
+Buffer.isEncoding = function(encoding) {
+  switch ((encoding + '').toLowerCase()) {
     case 'hex':
-      return str.length / 2;
-
     case 'utf8':
     case 'utf-8':
-      return utf8ToBytes(str).length;
-
     case 'ascii':
     case 'binary':
-      return str.length;
-
     case 'base64':
-      return base64ToBytes(str).length;
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+    case 'raw':
+      return true
 
     default:
-      throw new Error('Unknown encoding');
+      return false
   }
-};
-
-Buffer.prototype.utf8Write = function (string, offset, length) {
-  var bytes, pos;
-  return Buffer._charsWritten =  blitBuffer(utf8ToBytes(string), this, offset, length);
-};
-
-Buffer.prototype.asciiWrite = function (string, offset, length) {
-  var bytes, pos;
-  return Buffer._charsWritten =  blitBuffer(asciiToBytes(string), this, offset, length);
-};
-
-Buffer.prototype.binaryWrite = Buffer.prototype.asciiWrite;
-
-Buffer.prototype.base64Write = function (string, offset, length) {
-  var bytes, pos;
-  return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
-};
-
-Buffer.prototype.base64Slice = function (start, end) {
-  var bytes = Array.prototype.slice.apply(this, arguments)
-  return require("base64-js").fromByteArray(bytes);
-};
-
-Buffer.prototype.utf8Slice = function () {
-  var bytes = Array.prototype.slice.apply(this, arguments);
-  var res = "";
-  var tmp = "";
-  var i = 0;
-  while (i < bytes.length) {
-    if (bytes[i] <= 0x7F) {
-      res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
-      tmp = "";
-    } else
-      tmp += "%" + bytes[i].toString(16);
-
-    i++;
-  }
-
-  return res + decodeUtf8Char(tmp);
 }
 
-Buffer.prototype.asciiSlice = function () {
-  var bytes = Array.prototype.slice.apply(this, arguments);
-  var ret = "";
-  for (var i = 0; i < bytes.length; i++)
-    ret += String.fromCharCode(bytes[i]);
-  return ret;
+Buffer.isBuffer = function isBuffer (b) {
+  return b instanceof Uint8Array && b._isBuffer
 }
 
-Buffer.prototype.binarySlice = Buffer.prototype.asciiSlice;
-
-Buffer.prototype.inspect = function() {
-  var out = [],
-      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 '<Buffer ' + out.join(' ') + '>';
-};
-
-
-Buffer.prototype.hexSlice = function(start, end) {
-  var len = this.length;
-
-  if (!start || start < 0) start = 0;
-  if (!end || end < 0 || end > len) end = len;
-
-  var out = '';
-  for (var i = start; i < end; i++) {
-    out += toHex(this[i]);
-  }
-  return out;
-};
-
-
-Buffer.prototype.toString = function(encoding, start, end) {
-  encoding = String(encoding || 'utf8').toLowerCase();
-  start = +start || 0;
-  if (typeof end == 'undefined') end = this.length;
-
-  // Fastpath empty strings
-  if (+end == start) {
-    return '';
-  }
-
-  switch (encoding) {
+Buffer.byteLength = function (str, encoding) {
+  switch (encoding || "utf8") {
     case 'hex':
-      return this.hexSlice(start, end);
+      return str.length / 2
 
     case 'utf8':
     case 'utf-8':
-      return this.utf8Slice(start, end);
+      return utf8ToBytes(str).length
 
     case 'ascii':
-      return this.asciiSlice(start, end);
-
     case 'binary':
-      return this.binarySlice(start, end);
+      return str.length
 
     case 'base64':
-      return this.base64Slice(start, end);
-
-    case 'ucs2':
-    case 'ucs-2':
-      return this.ucs2Slice(start, end);
+      return base64ToBytes(str).length
 
     default:
-      throw new Error('Unknown encoding');
+      throw new Error('Unknown encoding')
+  }
+}
+
+Buffer.concat = function (list, totalLength) {
+  if (!Array.isArray(list)) {
+    throw new Error('Usage: Buffer.concat(list, [totalLength])\n' +
+        'list should be an Array.')
   }
-};
 
+  var i
+  var buf
 
-Buffer.prototype.hexWrite = function(string, offset, length) {
-  offset = +offset || 0;
-  var remaining = this.length - offset;
+  if (list.length === 0) {
+    return new Buffer(0)
+  } else if (list.length === 1) {
+    return list[0]
+  }
+
+  if (typeof totalLength !== 'number') {
+    totalLength = 0
+    for (i = 0; i < list.length; i++) {
+      buf = list[i]
+      totalLength += buf.length
+    }
+  }
+
+  var buffer = new Buffer(totalLength)
+  var pos = 0
+  for (i = 0; i < list.length; i++) {
+    buf = list[i]
+    buf.copy(buffer, pos)
+    pos += buf.length
+  }
+  return buffer
+}
+
+// INSTANCE METHODS
+// ================
+
+function _hexWrite (buf, string, offset, length) {
+  offset = Number(offset) || 0
+  var remaining = buf.length - offset
   if (!length) {
-    length = remaining;
+    length = remaining
   } else {
-    length = +length;
+    length = Number(length)
     if (length > remaining) {
-      length = remaining;
+      length = remaining
     }
   }
 
   // must be an even number of digits
-  var strLen = string.length;
-  if (strLen % 2) {
-    throw new Error('Invalid hex string');
+  var strLen = string.length
+  if (strLen % 2 !== 0) {
+    throw new Error('Invalid hex string')
   }
   if (length > strLen / 2) {
-    length = strLen / 2;
+    length = strLen / 2
   }
   for (var i = 0; i < length; i++) {
-    var byte = parseInt(string.substr(i * 2, 2), 16);
-    if (isNaN(byte)) throw new Error('Invalid hex string');
-    this[offset + i] = byte;
+    var byte = parseInt(string.substr(i * 2, 2), 16)
+    if (isNaN(byte)) throw new Error('Invalid hex string')
+    buf[offset + i] = byte
   }
-  Buffer._charsWritten = i * 2;
-  return i;
-};
+  Buffer._charsWritten = i * 2
+  return i
+}
+
+function _utf8Write (buf, string, offset, length) {
+  var bytes, pos
+  return Buffer._charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length)
+}
 
+function _asciiWrite (buf, string, offset, length) {
+  var bytes, pos
+  return Buffer._charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function _binaryWrite (buf, string, offset, length) {
+  return _asciiWrite(buf, string, offset, length)
+}
 
-Buffer.prototype.write = function(string, offset, length, encoding) {
+function _base64Write (buf, string, offset, length) {
+  var bytes, pos
+  return Buffer._charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function BufferWrite (string, offset, length, encoding) {
   // Support both (string, offset, length, encoding)
   // and the legacy (string, encoding, offset, length)
   if (isFinite(offset)) {
     if (!isFinite(length)) {
-      encoding = length;
-      length = undefined;
+      encoding = length
+      length = undefined
     }
   } else {  // legacy
-    var swap = encoding;
-    encoding = offset;
-    offset = length;
-    length = swap;
+    var swap = encoding
+    encoding = offset
+    offset = length
+    length = swap
   }
 
-  offset = +offset || 0;
-  var remaining = this.length - offset;
+  offset = Number(offset) || 0
+  var remaining = this.length - offset
   if (!length) {
-    length = remaining;
+    length = remaining
   } else {
-    length = +length;
+    length = Number(length)
     if (length > remaining) {
-      length = remaining;
+      length = remaining
     }
   }
-  encoding = String(encoding || 'utf8').toLowerCase();
+  encoding = String(encoding || 'utf8').toLowerCase()
 
   switch (encoding) {
     case 'hex':
-      return this.hexWrite(string, offset, length);
+      return _hexWrite(this, string, offset, length)
 
     case 'utf8':
     case 'utf-8':
-      return this.utf8Write(string, offset, length);
+      return _utf8Write(this, string, offset, length)
 
     case 'ascii':
-      return this.asciiWrite(string, offset, length);
+      return _asciiWrite(this, string, offset, length)
 
     case 'binary':
-      return this.binaryWrite(string, offset, length);
+      return _binaryWrite(this, string, offset, length)
 
     case 'base64':
-      return this.base64Write(string, offset, length);
-
-    case 'ucs2':
-    case 'ucs-2':
-      return this.ucs2Write(string, offset, length);
+      return _base64Write(this, string, offset, length)
 
     default:
-      throw new Error('Unknown encoding');
+      throw new Error('Unknown encoding')
   }
-};
-
-// slice(start, end)
-function clamp(index, len, defaultValue) {
-  if (typeof index !== 'number') return defaultValue;
-  index = ~~index;  // Coerce to integer.
-  if (index >= len) return len;
-  if (index >= 0) return index;
-  index += len;
-  if (index >= 0) return index;
-  return 0;
 }
 
-Buffer.prototype.slice = function(start, end) {
-  var len = this.length;
-  start = clamp(start, len, 0);
-  end = clamp(end, len, len);
-  return new Buffer(this, end - start, +start);
-};
-
-// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
-Buffer.prototype.copy = function(target, target_start, start, end) {
-  var source = this;
-  start || (start = 0);
-  if (end === undefined || isNaN(end)) {
-    end = this.length;
-  }
-  target_start || (target_start = 0);
+function BufferToString (encoding, start, end) {
+  encoding = String(encoding || 'utf8').toLowerCase()
+  start = Number(start) || 0
+  end = Number(end) || this.length
 
-  if (end < start) throw new Error('sourceEnd < sourceStart');
+  // Fastpath empty strings
+  if (end === start)
+    return ''
 
-  // Copy 0 bytes; we're done
-  if (end === start) return 0;
-  if (target.length == 0 || source.length == 0) return 0;
+  switch (encoding) {
+    case 'hex':
+      return _hexSlice(this, start, end)
 
-  if (target_start < 0 || target_start >= target.length) {
-    throw new Error('targetStart out of bounds');
-  }
+    case 'utf8':
+    case 'utf-8':
+      return _utf8Slice(this, start, end)
 
-  if (start < 0 || start >= source.length) {
-    throw new Error('sourceStart out of bounds');
-  }
+    case 'ascii':
+      return _asciiSlice(this, start, end)
 
-  if (end < 0 || end > source.length) {
-    throw new Error('sourceEnd out of bounds');
-  }
+    case 'binary':
+      return _binarySlice(this, start, end)
 
-  // Are we oob?
-  if (end > this.length) {
-    end = this.length;
-  }
+    case 'base64':
+      return _base64Slice(this, start, end)
 
-  if (target.length - target_start < end - start) {
-    end = target.length - target_start + start;
+    default:
+      throw new Error('Unknown encoding')
   }
+}
 
-  var temp = [];
-  for (var i=start; i<end; i++) {
-    assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
-    temp.push(this[i]);
-  }
+function BufferToJSON () {
+  return Array.prototype.slice.call(this, 0)
+}
 
-  for (var i=target_start; i<target_start+temp.length; i++) {
-    target[i] = temp[i-target_start];
-  }
-};
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+function BufferCopy (target, target_start, start, end) {
+  var source = this
 
-// fill(value, start=0, end=buffer.length)
-Buffer.prototype.fill = function fill(value, start, end) {
-  value || (value = 0);
-  start || (start = 0);
-  end || (end = this.length);
+  if (!start) start = 0
+  if (!end && end !== 0) end = this.length
+  if (!target_start) target_start = 0
 
-  if (typeof value === 'string') {
-    value = value.charCodeAt(0);
-  }
-  if (!(typeof value === 'number') || isNaN(value)) {
-    throw new Error('value is not a number');
-  }
+  // 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')
 
-  if (end < start) throw new Error('end < start');
+  // Are we oob?
+  if (end > this.length)
+    end = this.length
+  if (target.length - target_start < end - start)
+    end = target.length - target_start + start
+
+  // copy!
+  for (var i = 0; i < end - start; i++)
+    target[i + target_start] = this[i + start]
+}
 
-  // Fill 0 bytes; we're done
-  if (end === start) return 0;
-  if (this.length == 0) return 0;
+function _base64Slice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  return require('base64-js').fromByteArray(bytes)
+}
 
-  if (start < 0 || start >= this.length) {
-    throw new Error('start out of bounds');
-  }
+function _utf8Slice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var res = ''
+  var tmp = ''
+  var i = 0
+  while (i < bytes.length) {
+    if (bytes[i] <= 0x7F) {
+      res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i])
+      tmp = ''
+    } else {
+      tmp += '%' + bytes[i].toString(16)
+    }
 
-  if (end < 0 || end > this.length) {
-    throw new Error('end out of bounds');
+    i++
   }
 
-  for (var i = start; i < end; i++) {
-    this[i] = value;
-  }
+  return res + decodeUtf8Char(tmp)
 }
 
-// Static methods
-Buffer.isBuffer = function isBuffer(b) {
-  return b instanceof Buffer;
-};
+function _asciiSlice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var ret = ''
+  for (var i = 0; i < bytes.length; i++)
+    ret += String.fromCharCode(bytes[i])
+  return ret
+}
 
-Buffer.concat = function (list, totalLength) {
-  if (!isArray(list)) {
-    throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
-      list should be an Array.");
-  }
+function _binarySlice (buf, start, end) {
+  return _asciiSlice(buf, start, end)
+}
 
-  if (list.length === 0) {
-    return new Buffer(0);
-  } else if (list.length === 1) {
-    return list[0];
-  }
+function _hexSlice (buf, start, end) {
+  var len = buf.length
 
-  if (typeof totalLength !== 'number') {
-    totalLength = 0;
-    for (var i = 0; i < list.length; i++) {
-      var buf = list[i];
-      totalLength += buf.length;
-    }
-  }
+  if (!start || start < 0) start = 0
+  if (!end || end < 0 || end > len) end = len
 
-  var buffer = new Buffer(totalLength);
-  var pos = 0;
-  for (var i = 0; i < list.length; i++) {
-    var buf = list[i];
-    buf.copy(buffer, pos);
-    pos += buf.length;
+  var out = ''
+  for (var i = start; i < end; i++) {
+    out += toHex(buf[i])
   }
-  return buffer;
-};
+  return out
+}
 
-Buffer.isEncoding = function(encoding) {
-  switch ((encoding + '').toLowerCase()) {
-    case 'hex':
-    case 'utf8':
-    case 'utf-8':
-    case 'ascii':
-    case 'binary':
-    case 'base64':
-    case 'ucs2':
-    case 'ucs-2':
-    case 'utf16le':
-    case 'utf-16le':
-    case 'raw':
-      return true;
+// 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) {
+  var len = this.length
+  start = clamp(start, len, 0)
+  end = clamp(end, len, len)
+  return augment(this.subarray(start, end)) // Uint8Array built-in method
+}
 
-    default:
-      return false;
+function BufferReadUInt8 (offset, noAssert) {
+  var buf = this
+  if (!noAssert) {
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset < buf.length, 'Trying to read beyond buffer length')
   }
-};
 
-// helpers
+  if (offset >= buf.length)
+    return
 
-function coerce(length) {
-  // Coerce length to a number (possibly NaN), round up
-  // in case it's fractional (e.g. 123.456) then do a
-  // double negate to coerce a NaN to 0. Easy, right?
-  length = ~~Math.ceil(+length);
-  return length < 0 ? 0 : length;
+  return buf[offset]
 }
 
-function isArray(subject) {
-  return (Array.isArray ||
-    function(subject){
-      return {}.toString.apply(subject) == '[object Array]'
-    })
-    (subject)
+function _readUInt16 (buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 1 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  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)
+  } else {
+    return buf._dataview.getUint16(offset, littleEndian)
+  }
 }
 
-function isArrayIsh(subject) {
-  return isArray(subject) || Buffer.isBuffer(subject) ||
-         subject && typeof subject === 'object' &&
-         typeof subject.length === 'number';
+function BufferReadUInt16LE (offset, noAssert) {
+  return _readUInt16(this, offset, true, noAssert)
 }
 
-function toHex(n) {
-  if (n < 16) return '0' + n.toString(16);
-  return n.toString(16);
+function BufferReadUInt16BE (offset, noAssert) {
+  return _readUInt16(this, offset, false, noAssert)
 }
 
-function utf8ToBytes(str) {
-  var byteArray = [];
-  for (var i = 0; i < str.length; i++)
-    if (str.charCodeAt(i) <= 0x7F)
-      byteArray.push(str.charCodeAt(i));
-    else {
-      var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
-      for (var j = 0; j < h.length; j++)
-        byteArray.push(parseInt(h[j], 16));
+function _readUInt32 (buf, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  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])
     }
-
-  return byteArray;
-}
-
-function asciiToBytes(str) {
-  var byteArray = []
-  for (var i = 0; i < str.length; i++ )
-    // Node's code seems to be doing this and not & 0x7F..
-    byteArray.push( str.charCodeAt(i) & 0xFF );
-
-  return byteArray;
-}
-
-function base64ToBytes(str) {
-  return require("base64-js").toByteArray(str);
-}
-
-function blitBuffer(src, dst, offset, length) {
-  var pos, i = 0;
-  while (i < length) {
-    if ((i+offset >= dst.length) || (i >= src.length))
-      break;
-
-    dst[i + offset] = src[i];
-    i++;
+    return dv.getUint32(0, littleEndian)
+  } else {
+    return buf._dataview.getUint32(offset, littleEndian)
   }
-  return i;
 }
 
-function decodeUtf8Char(str) {
-  try {
-    return decodeURIComponent(str);
-  } catch (err) {
-    return String.fromCharCode(0xFFFD); // UTF 8 invalid char
-  }
+function BufferReadUInt32LE (offset, noAssert) {
+  return _readUInt32(this, offset, true, noAssert)
 }
 
-// read/write bit-twiddling
-
-Buffer.prototype.readUInt8 = function(offset, noAssert) {
-  var buffer = this;
+function BufferReadUInt32BE (offset, noAssert) {
+  return _readUInt32(this, offset, false, noAssert)
+}
 
+function BufferReadInt8 (offset, noAssert) {
+  var buf = this
   if (!noAssert) {
     assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
-
-    assert.ok(offset < buffer.length,
-        'Trying to read beyond buffer length');
+        'missing offset')
+    assert.ok(offset < buf.length, 'Trying to read beyond buffer length')
   }
 
-  if (offset >= buffer.length) return;
-
-  return buffer[offset];
-};
-
-function readUInt16(buffer, offset, isBigEndian, noAssert) {
-  var val = 0;
+  if (offset >= buf.length)
+    return
 
+  return buf._dataview.getInt8(offset)
+}
 
+function _readInt16 (buf, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
-
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
     assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
-
-    assert.ok(offset + 1 < buffer.length,
-        'Trying to read beyond buffer length');
+        'missing offset')
+    assert.ok(offset + 1 < buf.length, 'Trying to read beyond buffer length')
   }
 
-  if (offset >= buffer.length) return 0;
-
-  if (isBigEndian) {
-    val = buffer[offset] << 8;
-    if (offset + 1 < buffer.length) {
-      val |= buffer[offset + 1];
-    }
+  var len = buf.length
+  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)
   } else {
-    val = buffer[offset];
-    if (offset + 1 < buffer.length) {
-      val |= buffer[offset + 1] << 8;
-    }
+    return buf._dataview.getInt16(offset, littleEndian)
   }
-
-  return val;
 }
 
-Buffer.prototype.readUInt16LE = function(offset, noAssert) {
-  return readUInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt16BE = function(offset, noAssert) {
-  return readUInt16(this, offset, true, noAssert);
-};
+function BufferReadInt16LE (offset, noAssert) {
+  return _readInt16(this, offset, true, noAssert)
+}
 
-function readUInt32(buffer, offset, isBigEndian, noAssert) {
-  var val = 0;
+function BufferReadInt16BE (offset, noAssert) {
+  return _readInt16(this, offset, false, noAssert)
+}
 
+function _readInt32 (buf, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    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 read beyond buffer length');
-  }
-
-  if (offset >= buffer.length) return 0;
-
-  if (isBigEndian) {
-    if (offset + 1 < buffer.length)
-      val = buffer[offset + 1] << 16;
-    if (offset + 2 < buffer.length)
-      val |= buffer[offset + 2] << 8;
-    if (offset + 3 < buffer.length)
-      val |= buffer[offset + 3];
-    val = val + (buffer[offset] << 24 >>> 0);
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 3 < buf.length, 'Trying to read beyond buffer length')
+  }
+
+  var len = buf.length
+  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])
+    }
+    return dv.getInt32(0, littleEndian)
   } else {
-    if (offset + 2 < buffer.length)
-      val = buffer[offset + 2] << 16;
-    if (offset + 1 < buffer.length)
-      val |= buffer[offset + 1] << 8;
-    val |= buffer[offset];
-    if (offset + 3 < buffer.length)
-      val = val + (buffer[offset + 3] << 24 >>> 0);
+    return buf._dataview.getInt32(offset, littleEndian)
   }
-
-  return val;
 }
 
-Buffer.prototype.readUInt32LE = function(offset, noAssert) {
-  return readUInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readUInt32BE = function(offset, noAssert) {
-  return readUInt32(this, offset, true, noAssert);
-};
-
+function BufferReadInt32LE (offset, noAssert) {
+  return _readInt32(this, offset, true, noAssert)
+}
 
-/*
- * Signed integer types, yay team! A reminder on how two's complement actually
- * works. The first bit is the signed bit, i.e. tells us whether or not the
- * number should be positive or negative. If the two's complement value is
- * positive, then we're done, as it's equivalent to the unsigned representation.
- *
- * Now if the number is positive, you're pretty much done, you can just leverage
- * the unsigned translations and return those. Unfortunately, negative numbers
- * aren't quite that straightforward.
- *
- * At first glance, one might be inclined to use the traditional formula to
- * translate binary numbers between the positive and negative values in two's
- * complement. (Though it doesn't quite work for the most negative value)
- * Mainly:
- *  - invert all the bits
- *  - add one to the result
- *
- * Of course, this doesn't quite work in Javascript. Take for example the value
- * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
- * course, Javascript will do the following:
- *
- * > ~0xff80
- * -65409
- *
- * Whoh there, Javascript, that's not quite right. But wait, according to
- * Javascript that's perfectly correct. When Javascript ends up seeing the
- * constant 0xff80, it has no notion that it is actually a signed number. It
- * assumes that we've input the unsigned value 0xff80. Thus, when it does the
- * binary negation, it casts it into a signed value, (positive 0xff80). Then
- * when you perform binary negation on that, it turns it into a negative number.
- *
- * Instead, we're going to have to use the following general formula, that works
- * in a rather Javascript friendly way. I'm glad we don't support this kind of
- * weird numbering scheme in the kernel.
- *
- * (BIT-MAX - (unsigned)val + 1) * -1
- *
- * The astute observer, may think that this doesn't make sense for 8-bit numbers
- * (really it isn't necessary for them). However, when you get 16-bit numbers,
- * you do. Let's go back to our prior example and see how this will look:
- *
- * (0xffff - 0xff80 + 1) * -1
- * (0x007f + 1) * -1
- * (0x0080) * -1
- */
-Buffer.prototype.readInt8 = function(offset, noAssert) {
-  var buffer = this;
-  var neg;
+function BufferReadInt32BE (offset, noAssert) {
+  return _readInt32(this, offset, false, noAssert)
+}
 
+function _readFloat (buf, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
-
-    assert.ok(offset < buffer.length,
-        'Trying to read beyond buffer length');
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset + 3 < buf.length, 'Trying to read beyond buffer length')
   }
 
-  if (offset >= buffer.length) return;
-
-  neg = buffer[offset] & 0x80;
-  if (!neg) {
-    return (buffer[offset]);
-  }
+  return buf._dataview.getFloat32(offset, littleEndian)
+}
 
-  return ((0xff - buffer[offset] + 1) * -1);
-};
+function BufferReadFloatLE (offset, noAssert) {
+  return _readFloat(this, offset, true, noAssert)
+}
 
-function readInt16(buffer, offset, isBigEndian, noAssert) {
-  var neg, val;
+function BufferReadFloatBE (offset, noAssert) {
+  return _readFloat(this, offset, false, noAssert)
+}
 
+function _readDouble (buf, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
-
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
-
-    assert.ok(offset + 1 < buffer.length,
-        'Trying to read beyond buffer length');
-  }
-
-  val = readUInt16(buffer, offset, isBigEndian, noAssert);
-  neg = val & 0x8000;
-  if (!neg) {
-    return val;
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset + 7 < buf.length, 'Trying to read beyond buffer length')
   }
 
-  return (0xffff - val + 1) * -1;
+  return buf._dataview.getFloat64(offset, littleEndian)
 }
 
-Buffer.prototype.readInt16LE = function(offset, noAssert) {
-  return readInt16(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt16BE = function(offset, noAssert) {
-  return readInt16(this, offset, true, noAssert);
-};
+function BufferReadDoubleLE (offset, noAssert) {
+  return _readDouble(this, offset, true, noAssert)
+}
 
-function readInt32(buffer, offset, isBigEndian, noAssert) {
-  var neg, val;
+function BufferReadDoubleBE (offset, noAssert) {
+  return _readDouble(this, offset, false, noAssert)
+}
 
+function BufferWriteUInt8 (value, offset, noAssert) {
+  var buf = this
   if (!noAssert) {
-    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 read beyond buffer length');
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset < buf.length, 'trying to write beyond buffer length')
+    verifuint(value, 0xff)
   }
 
-  val = readUInt32(buffer, offset, isBigEndian, noAssert);
-  neg = val & 0x80000000;
-  if (!neg) {
-    return (val);
-  }
+  if (offset >= buf.length) return
 
-  return (0xffffffff - val + 1) * -1;
+  buf[offset] = value
 }
 
-Buffer.prototype.readInt32LE = function(offset, noAssert) {
-  return readInt32(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readInt32BE = function(offset, noAssert) {
-  return readInt32(this, offset, true, noAssert);
-};
-
-function readFloat(buffer, offset, isBigEndian, noAssert) {
+function _writeUInt16 (buf, value, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
-
-    assert.ok(offset + 3 < buffer.length,
-        'Trying to read beyond buffer length');
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 1 < buf.length, 'trying to write beyond buffer length')
+    verifuint(value, 0xffff)
+  }
+
+  var len = buf.length
+  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)
+  } else {
+    buf._dataview.setUint16(offset, value, littleEndian)
   }
-
-  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
-      23, 4);
 }
 
-Buffer.prototype.readFloatLE = function(offset, noAssert) {
-  return readFloat(this, offset, false, noAssert);
-};
+function BufferWriteUInt16LE (value, offset, noAssert) {
+  _writeUInt16(this, value, offset, true, noAssert)
+}
 
-Buffer.prototype.readFloatBE = function(offset, noAssert) {
-  return readFloat(this, offset, true, noAssert);
-};
+function BufferWriteUInt16BE (value, offset, noAssert) {
+  _writeUInt16(this, value, offset, false, noAssert)
+}
 
-function readDouble(buffer, offset, isBigEndian, noAssert) {
+function _writeUInt32 (buf, value, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
-
-    assert.ok(offset + 7 < buffer.length,
-        'Trying to read beyond buffer length');
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 3 < buf.length, 'trying to write beyond buffer length')
+    verifuint(value, 0xffffffff)
+  }
+
+  var len = buf.length
+  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)
+    }
+  } else {
+    buf._dataview.setUint32(offset, value, littleEndian)
   }
-
-  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
-      52, 8);
 }
 
-Buffer.prototype.readDoubleLE = function(offset, noAssert) {
-  return readDouble(this, offset, false, noAssert);
-};
-
-Buffer.prototype.readDoubleBE = function(offset, noAssert) {
-  return readDouble(this, offset, true, noAssert);
-};
-
+function BufferWriteUInt32LE (value, offset, noAssert) {
+  _writeUInt32(this, value, offset, true, noAssert)
+}
 
-/*
- * We have to make sure that the value is a valid integer. This means that it is
- * non-negative. It has no fractional component and that it does not exceed the
- * maximum allowed value.
- *
- *      value           The number to check for validity
- *
- *      max             The maximum value
- */
-function verifuint(value, max) {
-  assert.ok(typeof (value) == 'number',
-      'cannot write a non-number as a number');
+function BufferWriteUInt32BE (value, offset, noAssert) {
+  _writeUInt32(this, value, offset, false, noAssert)
+}
 
-  assert.ok(value >= 0,
-      'specified a negative value for writing an unsigned value');
+function BufferWriteInt8 (value, offset, noAssert) {
+  var buf = this
+  if (!noAssert) {
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset < buf.length, 'Trying to write beyond buffer length')
+    verifsint(value, 0x7f, -0x80)
+  }
 
-  assert.ok(value <= max, 'value is larger than maximum value for type');
+  if (offset >= buf.length) return
 
-  assert.ok(Math.floor(value) === value, 'value has a fractional component');
+  buf._dataview.setInt8(offset, value)
 }
 
-Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
-  var buffer = this;
-
+function _writeInt16 (buf, value, offset, littleEndian, noAssert) {
   if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 1 < buf.length, 'Trying to write beyond buffer length')
+    verifsint(value, 0x7fff, -0x8000)
+  }
+
+  var len = buf.length
+  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)
+  } else {
+    buf._dataview.setInt16(offset, value, littleEndian)
+  }
+}
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+function BufferWriteInt16LE (value, offset, noAssert) {
+  _writeInt16(this, value, offset, true, noAssert)
+}
 
-    assert.ok(offset < buffer.length,
-        'trying to write beyond buffer length');
+function BufferWriteInt16BE (value, offset, noAssert) {
+  _writeInt16(this, value, offset, false, noAssert)
+}
 
-    verifuint(value, 0xff);
+function _writeInt32 (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 3 < buf.length, 'Trying to write beyond buffer length')
+    verifsint(value, 0x7fffffff, -0x80000000)
+  }
+
+  var len = buf.length
+  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)
+    }
+  } else {
+    buf._dataview.setInt32(offset, value, littleEndian)
   }
+}
 
-  if (offset < buffer.length) {
-    buffer[offset] = value;
-  }
-};
+function BufferWriteInt32LE (value, offset, noAssert) {
+  _writeInt32(this, value, offset, true, noAssert)
+}
 
-function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+function BufferWriteInt32BE (value, offset, noAssert) {
+  _writeInt32(this, value, offset, false, noAssert)
+}
 
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
+function _writeFloat (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(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) {
+    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)
+    }
+  } else {
+    buf._dataview.setFloat32(offset, value, littleEndian)
+  }
+}
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+function BufferWriteFloatLE (value, offset, noAssert) {
+  _writeFloat(this, value, offset, true, noAssert)
+}
 
-    assert.ok(offset + 1 < buffer.length,
-        'trying to write beyond buffer length');
+function BufferWriteFloatBE (value, offset, noAssert) {
+  _writeFloat(this, value, offset, false, noAssert)
+}
 
-    verifuint(value, 0xffff);
+function _writeDouble (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    assert.ok(value !== undefined && value !== null, 'missing value')
+    assert.ok(typeof (littleEndian) === 'boolean',
+        'missing or invalid endian')
+    assert.ok(offset !== undefined && offset !== null, 'missing offset')
+    assert.ok(offset + 7 < buf.length,
+        'Trying to write beyond buffer length')
+    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
+  }
+
+  var len = buf.length
+  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)
+    }
+  } else {
+    buf._dataview.setFloat64(offset, value, littleEndian)
   }
+}
 
-  for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
-    buffer[offset + i] =
-        (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
-            (isBigEndian ? 1 - i : i) * 8;
-  }
+function BufferWriteDoubleLE (value, offset, noAssert) {
+  _writeDouble(this, value, offset, true, noAssert)
+}
 
+function BufferWriteDoubleBE (value, offset, noAssert) {
+  _writeDouble(this, value, offset, false, noAssert)
 }
 
-Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
-  writeUInt16(this, value, offset, false, noAssert);
-};
+// fill(value, start=0, end=buffer.length)
+function BufferFill (value, start, end) {
+  if (!value) value = 0
+  if (!start) start = 0
+  if (!end) end = this.length
 
-Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
-  writeUInt16(this, value, offset, true, noAssert);
-};
+  if (typeof value === 'string') {
+    value = value.charCodeAt(0)
+  }
 
-function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+  if (typeof value !== 'number' || isNaN(value)) {
+    throw new Error('value is not a number')
+  }
 
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
+  if (end < start) throw new Error('end < start')
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+  // Fill 0 bytes; we're done
+  if (end === start) return
+  if (this.length === 0) return
 
-    assert.ok(offset + 3 < buffer.length,
-        'trying to write beyond buffer length');
+  if (start < 0 || start >= this.length) {
+    throw new Error('start out of bounds')
+  }
 
-    verifuint(value, 0xffffffff);
+  if (end < 0 || end > this.length) {
+    throw new Error('end out of bounds')
   }
 
-  for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
-    buffer[offset + i] =
-        (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
+  for (var i = start; i < end; i++) {
+    this[i] = value
   }
 }
 
-Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
-  writeUInt32(this, value, offset, false, noAssert);
-};
-
-Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
-  writeUInt32(this, value, offset, true, noAssert);
-};
-
-
-/*
- * We now move onto our friends in the signed number category. Unlike unsigned
- * numbers, we're going to have to worry a bit more about how we put values into
- * arrays. Since we are only worrying about signed 32-bit values, we're in
- * slightly better shape. Unfortunately, we really can't do our favorite binary
- * & in this system. It really seems to do the wrong thing. For example:
- *
- * > -32 & 0xff
- * 224
- *
- * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
- * this aren't treated as a signed number. Ultimately a bad thing.
- *
- * What we're going to want to do is basically create the unsigned equivalent of
- * our representation and pass that off to the wuint* functions. To do that
- * we're going to do the following:
- *
- *  - if the value is positive
- *      we can pass it directly off to the equivalent wuint
- *  - if the value is negative
- *      we do the following computation:
- *         mb + val + 1, where
- *         mb   is the maximum unsigned value in that byte size
- *         val  is the Javascript negative integer
- *
- *
- * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
- * you do out the computations:
- *
- * 0xffff - 128 + 1
- * 0xffff - 127
- * 0xff80
- *
- * You can then encode this value as the signed version. This is really rather
- * hacky, but it should work and get the job done which is our goal here.
- */
+function BufferInspect () {
+  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 '<Buffer ' + out.join(' ') + '>'
+}
 
-/*
- * A series of checks to make sure we actually have a signed 32-bit number
- */
-function verifsint(value, max, min) {
-  assert.ok(typeof (value) == 'number',
-      'cannot write a non-number as a number');
+// Creates a new `ArrayBuffer` with the copied memory of the buffer instance.
+// Added in Node 0.12.
+function BufferToArrayBuffer () {
+  return (new Buffer(this)).buffer
+}
 
-  assert.ok(value <= max, 'value larger than maximum allowed value');
 
-  assert.ok(value >= min, 'value smaller than minimum allowed value');
+// HELPER FUNCTIONS
+// ================
 
-  assert.ok(Math.floor(value) === value, 'value has a fractional component');
+function stringtrim (str) {
+  if (str.trim) return str.trim()
+  return str.replace(/^\s+|\s+$/g, '')
 }
 
-function verifIEEE754(value, max, min) {
-  assert.ok(typeof (value) == 'number',
-      'cannot write a non-number as a number');
-
-  assert.ok(value <= max, 'value larger than maximum allowed value');
+function augment (arr) {
+  if (arr._isBuffer) return arr // do not augment an Uint8Array twice
 
-  assert.ok(value >= min, 'value smaller than minimum allowed value');
-}
+  // Augment the Uint8Array *instance* (not the class!) with Buffer methods
+  arr.write = BufferWrite
 
-Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
-  var buffer = this;
+  arr.toString = BufferToString
+  arr.toLocaleString = BufferToString
+  arr.toJSON = BufferToJSON
 
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+  arr.copy = BufferCopy
+  arr.slice = BufferSlice
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+  arr.readUInt8 = BufferReadUInt8
+  arr.readUInt16LE = BufferReadUInt16LE
+  arr.readUInt16BE = BufferReadUInt16BE
+  arr.readUInt32LE = BufferReadUInt32LE
+  arr.readUInt32BE = BufferReadUInt32BE
 
-    assert.ok(offset < buffer.length,
-        'Trying to write beyond buffer length');
+  arr.readInt8 = BufferReadInt8
+  arr.readInt16LE = BufferReadInt16LE
+  arr.readInt16BE = BufferReadInt16BE
+  arr.readInt32LE = BufferReadInt32LE
+  arr.readInt32BE = BufferReadInt32BE
 
-    verifsint(value, 0x7f, -0x80);
-  }
+  arr.readFloatLE = BufferReadFloatLE
+  arr.readFloatBE = BufferReadFloatBE
+  arr.readDoubleLE = BufferReadDoubleLE
+  arr.readDoubleBE = BufferReadDoubleBE
 
-  if (value >= 0) {
-    buffer.writeUInt8(value, offset, noAssert);
-  } else {
-    buffer.writeUInt8(0xff + value + 1, offset, noAssert);
-  }
-};
+  arr.writeUInt8 = BufferWriteUInt8
+  arr.writeUInt16LE = BufferWriteUInt16LE
+  arr.writeUInt16BE = BufferWriteUInt16BE
+  arr.writeUInt32LE = BufferWriteUInt32LE
+  arr.writeUInt32BE = BufferWriteUInt32BE
 
-function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+  arr.writeInt8 = BufferWriteInt8
+  arr.writeInt16LE = BufferWriteInt16LE
+  arr.writeInt16BE = BufferWriteInt16BE
+  arr.writeInt32LE = BufferWriteInt32LE
+  arr.writeInt32BE = BufferWriteInt32BE
 
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
+  arr.writeFloatLE = BufferWriteFloatLE
+  arr.writeFloatBE = BufferWriteFloatBE
+  arr.writeDoubleLE = BufferWriteDoubleLE
+  arr.writeDoubleBE = BufferWriteDoubleBE
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+  arr.fill = BufferFill
+  arr.inspect = BufferInspect
+  arr.toArrayBuffer = BufferToArrayBuffer // Node 0.12
 
-    assert.ok(offset + 1 < buffer.length,
-        'Trying to write beyond buffer length');
+  // Private
+  arr._isBuffer = true
 
-    verifsint(value, 0x7fff, -0x8000);
-  }
+  if (arr.byteLength !== 0)
+    arr._dataview = new DataView(arr.buffer, arr.byteOffset, arr.byteLength)
 
-  if (value >= 0) {
-    writeUInt16(buffer, value, offset, isBigEndian, noAssert);
-  } else {
-    writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
-  }
+  return arr
 }
 
-Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
-  writeInt16(this, value, offset, false, noAssert);
-};
+// slice(start, end)
+function clamp (index, len, defaultValue) {
+  if (typeof index !== 'number') return defaultValue
+  index = ~~index;  // Coerce to integer.
+  if (index >= len) return len
+  if (index >= 0) return index
+  index += len
+  if (index >= 0) return index
+  return 0
+}
 
-Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
-  writeInt16(this, value, offset, true, noAssert);
-};
+function coerce (length) {
+  // Coerce length to a number (possibly NaN), round up
+  // in case it's fractional (e.g. 123.456) then do a
+  // double negate to coerce a NaN to 0. Easy, right?
+  length = ~~Math.ceil(+length)
+  return length < 0 ? 0 : length
+}
 
-function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+function isArrayIsh (subject) {
+  return Array.isArray(subject) || Buffer.isBuffer(subject) ||
+      subject && typeof subject === 'object' &&
+      typeof subject.length === 'number'
+}
 
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
+function toHex (n) {
+  if (n < 16) return '0' + n.toString(16)
+  return n.toString(16)
+}
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+function utf8ToBytes (str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++)
+    if (str.charCodeAt(i) <= 0x7F)
+      byteArray.push(str.charCodeAt(i))
+    else {
+      var h = encodeURIComponent(str.charAt(i)).substr(1).split('%')
+      for (var j = 0; j < h.length; j++)
+        byteArray.push(parseInt(h[j], 16))
+    }
 
-    assert.ok(offset + 3 < buffer.length,
-        'Trying to write beyond buffer length');
+  return byteArray
+}
 
-    verifsint(value, 0x7fffffff, -0x80000000);
+function asciiToBytes (str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    // Node's code seems to be doing this and not & 0x7F..
+    byteArray.push(str.charCodeAt(i) & 0xFF)
   }
 
-  if (value >= 0) {
-    writeUInt32(buffer, value, offset, isBigEndian, noAssert);
-  } else {
-    writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
-  }
+  return byteArray
 }
 
-Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
-  writeInt32(this, value, offset, false, noAssert);
-};
-
-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');
+function base64ToBytes (str) {
+  return require('base64-js').toByteArray(str)
+}
 
-    assert.ok(offset + 3 < buffer.length,
-        'Trying to write beyond buffer length');
+function blitBuffer (src, dst, offset, length) {
+  var pos, i = 0
+  while (i < length) {
+    if ((i + offset >= dst.length) || (i >= src.length))
+      break
 
-    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
+    dst[i + offset] = src[i]
+    i++
   }
+  return i
+}
 
-  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
-      23, 4);
+function decodeUtf8Char (str) {
+  try {
+    return decodeURIComponent(str)
+  } catch (err) {
+    return String.fromCharCode(0xFFFD); // UTF 8 invalid char
+  }
 }
 
-Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
-  writeFloat(this, value, offset, false, noAssert);
-};
+/*
+ * We have to make sure that the value is a valid integer. This means that it
+ * is non-negative. It has no fractional component and that it does not
+ * exceed the maximum allowed value.
+ *
+ *      value           The number to check for validity
+ *
+ *      max             The maximum value
+ */
+function verifuint (value, max) {
+  assert.ok(typeof (value) == 'number',
+      'cannot write a non-number as a number')
 
-Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
-  writeFloat(this, value, offset, true, noAssert);
-};
+  assert.ok(value >= 0,
+      'specified a negative value for writing an unsigned value')
 
-function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
-  if (!noAssert) {
-    assert.ok(value !== undefined && value !== null,
-        'missing value');
+  assert.ok(value <= max, 'value is larger than maximum value for type')
 
-    assert.ok(typeof (isBigEndian) === 'boolean',
-        'missing or invalid endian');
+  assert.ok(Math.floor(value) === value, 'value has a fractional component')
+}
 
-    assert.ok(offset !== undefined && offset !== null,
-        'missing offset');
+/*
+ * A series of checks to make sure we actually have a signed 32-bit number
+ */
+function verifsint(value, max, min) {
+  assert.ok(typeof (value) == 'number', 'cannot write a non-number as a number')
 
-    assert.ok(offset + 7 < buffer.length,
-        'Trying to write beyond buffer length');
+  assert.ok(value <= max, 'value larger than maximum allowed value')
 
-    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
-  }
+  assert.ok(value >= min, 'value smaller than minimum allowed value')
 
-  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
-      52, 8);
+  assert.ok(Math.floor(value) === value, 'value has a fractional component')
 }
 
-Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
-  writeDouble(this, value, offset, false, noAssert);
-};
+function verifIEEE754(value, max, min) {
+  assert.ok(typeof (value) == 'number', 'cannot write a non-number as a number')
+
+  assert.ok(value <= max, 'value larger than maximum allowed value')
 
-Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
-  writeDouble(this, value, offset, true, noAssert);
-};
+  assert.ok(value >= min, 'value smaller than minimum allowed value')
+}
index f8e696ae579392fc5e711ec672408b394ee9dd76..9bae6182a918269b0632c22cf9cdf6729878c9c3 100644 (file)
@@ -41,7 +41,7 @@
         "email" : "toots@rastageeks.org"
     },
     "scripts" : {
-        "test" : "tap test/*.js"
+        "test" : "tape test/*.js"
     },
     "license" : "MIT/X11",
     "engine" : { "node" : ">=0.6" }
diff --git a/test/basic.js b/test/basic.js
new file mode 100644 (file)
index 0000000..f53e7fc
--- /dev/null
@@ -0,0 +1,64 @@
+var B = require('../index.js').Buffer
+var test = require('tape')
+
+test('new buffer from array', function (t) {
+    t.plan(1)
+    t.equal(
+        new B([1, 2, 3]).toString(),
+        new Buffer([1, 2, 3]).toString()
+    )
+    t.end()
+})
+
+test('new buffer from string', function (t) {
+    t.plan(1)
+    t.equal(
+        new B('hey', 'utf8').toString(),
+        new Buffer('hey', 'utf8').toString()
+    )
+    t.end()
+})
+
+function arraybufferToString (arraybuffer) {
+  return String.fromCharCode.apply(null, new Uint16Array(arraybuffer))
+}
+
+test('buffer toArrayBuffer()', function (t) {
+    t.plan(1)
+    var data = [1, 2, 3, 4, 5, 6, 7, 8]
+    t.equal(
+        arraybufferToString(new B(data).slice(4).toArrayBuffer()),
+        arraybufferToString(new Uint8Array(new Uint8Array(data).subarray(4)).buffer)
+    )
+    t.end()
+})
+
+test('buffer toJSON()', function (t) {
+    t.plan(1)
+    var data = [1, 2, 3, 4]
+    t.deepEqual(
+      new B(data).toJSON(),
+      new Buffer(data).toJSON()
+    )
+    t.end()
+})
+
+test('buffer copy example', function (t) {
+    t.plan(1)
+
+    buf1 = new B(26)
+    buf2 = new B(26)
+
+    for (var i = 0 ; i < 26 ; i++) {
+      buf1[i] = i + 97; // 97 is ASCII a
+      buf2[i] = 33; // ASCII !
+    }
+
+    buf1.copy(buf2, 8, 16, 20)
+
+    t.equal(
+      buf2.toString('ascii', 0, 25),
+      '!!!!!!!!qrst!!!!!!!!!!!!!'
+    )
+    t.end()
+})
index 34ca567adddd8b2beddca032bf35e13e35265082..0d8ff7b8b118334f292313e13dd8294e3d842c0c 100644 (file)
@@ -257,5 +257,5 @@ test('buffer.slice out of range', function (t) {
 test('base64 strings without padding', function (t) {
   t.plan(1);
   t.equal((new B('YW9ldQ', 'base64').toString()), 'aoeu');
-  t.end(); 
+  t.end();
 });