/* * By Benvie https://gist.github.com/Benvie/5020656 */ void function(global){ if ('DataView' in global && 'ArrayBuffer' in global) { return; } var hide = (function(){ // check if we're in ES5 if (typeof Object.getOwnPropertyNames === 'function' && !('prototype' in Object.getOwnPropertyNames)) { var hidden = { enumerable: false }; return function(object, key){ Object.defineProperty(object, key, hidden); }; } // noop for ES3 return function(){}; })(); function define(object, props){ for (var key in props) { object[key] = props[key]; } } var ArrayBuffer = global.ArrayBuffer = (function(){ var min = Math.min, max = Math.max, char = String.fromCharCode; var chars = {}, indices = []; // create cached mapping of characters to char codes and back void function(){ for (var i = 0; i < 0x100; ++i) { chars[indices[i] = char(i)] = i; if (i >= 0x80) { chars[char(0xf700 + i)] = i; } } }(); // read a string into an array of bytes function readString(string){ var array = [], cycles = string.length % 8, index = 0; while (cycles--) { array[index] = chars[string[index++]]; } cycles = string.length >> 3; while (cycles--) { array.push( chars[string[index]], chars[string[index+1]], chars[string[index+2]], chars[string[index+3]], chars[string[index+4]], chars[string[index+5]], chars[string[index+6]], chars[string[index+7]] ); index += 8; } return array; } // write an array of bytes to a string function writeString(array){ try { return char.apply(null, array) } catch (e) {} var string = '', cycles = array.length % 8, index = 0; while (cycles--) { string += indices[array[index++]]; } cycles = array.length >> 3; while (cycles--) { string += indices[array[index]] + indices[array[index+1]] + indices[array[index+2]] + indices[array[index+3]] + indices[array[index+4]] + indices[array[index+5]] + indices[array[index+6]] + indices[array[index+7]]; index += 8; } return string; } // create a new array of given size where each element is 0 function zerodArray(size){ var data = new Array(size); for (var i=0; i < size; i++) { data[i] = 0; } return data; } // ################### // ### ArrayBuffer ### // ################### function ArrayBuffer(length){ if (length instanceof ArrayBuffer) { this._data = length._data.slice(); } else if (typeof length === 'string') { this._data = readString(length); } else { if ((length >>= 0) < 0) { throw new RangeError('ArrayBuffer length must be non-negative'); } this._data = zerodArray(length); } this.byteLength = this._data.length; hide(this, '_data'); } define(ArrayBuffer, { toByteString: function toByteString(arraybuffer){ if (!(arraybuffer instanceof ArrayBuffer)) { throw new TypeError('ArrayBuffer.toByteString requires an ArrayBuffer'); } return writeString(arraybuffer._data); } }); define(ArrayBuffer.prototype, { slice: function slice(begin, end){ var arraybuffer = new ArrayBuffer(0); arraybuffer._data = this._data.slice(begin, end); arraybuffer.byteLength = arraybuffer._data.length; return arraybuffer; } }); return ArrayBuffer; })(); global.DataView = (function(){ var log = Math.log, pow = Math.pow, LN2 = Math.LN2; // Joyent copyright applies to readFloat and writeFloat // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function readFloat(dataview, offset, littleEndian, mLen, bytes){ var buffer = dataview.buffer._data, offset = dataview.byteOffset + offset, e, m, eLen = bytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, nBits = -7, i = littleEndian ? bytes - 1 : 0 , d = littleEndian ? -1 : 1, s = buffer[offset + i]; i += d; e = s & ((1 << (-nBits)) - 1); s >>= (-nBits); nBits += eLen; for (; nBits > 0; e = e * 0x100 + buffer[offset + i], i += d, nBits -= 8); m = e & ((1 << (-nBits)) - 1); e >>= (-nBits); nBits += mLen; for (; nBits > 0; m = m * 0x100 + buffer[offset + i], i += d, nBits -= 8); if (e === 0) { e = 1 - eBias; } else if (e === eMax) { return m ? NaN : s ? -Infinity : Infinity; } else { m = m + pow(2, mLen); e = e - eBias; } return (s ? -1 : 1) * m * pow(2, e - mLen); } function writeFloat(dataview, offset, value, littleEndian, mLen, bytes){ var buffer = dataview.buffer._data, offset = dataview.byteOffset + offset, e, m, c, eLen = bytes * 8 - mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1, rt = (mLen === 23 ? pow(2, -24) - pow(2, -77) : 0), i = littleEndian ? 0 : bytes - 1, d = littleEndian ? 1 : -1, s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; value < 0 && (value = -value); if (value !== value || value === Infinity) { m = value !== value ? 1 : 0; e = eMax; } else { e = (log(value) / LN2) | 0; if (value * (c = pow(2, -e)) < 1) { e--; c *= 2; } if (e + eBias >= 1) { value += rt / c; } else { value += rt * 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) * pow(2, mLen); e = e + eBias; } else { m = value * pow(2, eBias - 1) * pow(2, mLen); e = 0; } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 0x100, mLen -= 8); e = (e << mLen) | m; eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 0x100, eLen -= 8); buffer[offset + i - d] |= s * 0x80; } var le2 = [1, 0], le4 = [3, 2, 1, 0], be2 = [0, 1], be4 = [0, 1, 2, 3]; function readUint8(dataview, byteOffset){ var buffer = dataview.buffer._data, offset = byteOffset + dataview.byteOffset; return buffer[offset]; } function readUint16(dataview, byteOffset, littleEndian){ var buffer = dataview.buffer._data, offset = byteOffset + dataview.byteOffset, order = littleEndian ? le2 : be2; var b0 = buffer[offset + order[0]], b1 = buffer[offset + order[1]] << 8; return b0 | b1; } function readUint32(dataview, byteOffset, littleEndian){ var buffer = dataview.buffer._data, offset = byteOffset + dataview.byteOffset, order = littleEndian ? le4 : be4; var b0 = buffer[offset + order[0]], b1 = buffer[offset + order[1]] << 8, b2 = buffer[offset + order[2]] << 16, b3 = buffer[offset + order[3]] << 24; return b0 | b1 | b2 | b3; } function boundsCheck(offset, size, max){ if (offset < 0) { throw new RangeError('Tried to write to a negative index'); } else if (offset + size > max) { throw new RangeError('Tried to write '+size+' bytes past the end of a buffer at index '+offset+' of '+max); } } function writeUint8(dataview, byteOffset, value){ var buffer = dataview.buffer._data, offset = byteOffset + dataview.byteOffset; boundsCheck(offset, 1, buffer.length); buffer[offset] = value & 0xff; } function writeUint16(dataview, byteOffset, value, littleEndian){ var buffer = dataview.buffer._data, order = littleEndian ? le2 : be2, offset = byteOffset + dataview.byteOffset; boundsCheck(offset, 2, buffer.length); buffer[offset + order[0]] = value & 0xff; buffer[offset + order[1]] = value >>> 8 & 0xff; } function writeUint32(dataview, byteOffset, value, littleEndian){ var buffer = dataview.buffer._data, order = littleEndian ? le4 : be4, offset = byteOffset + dataview.byteOffset; boundsCheck(offset, 4, buffer.length); buffer[offset + order[0]] = value & 0xff; buffer[offset + order[1]] = value >>> 8 & 0xff; buffer[offset + order[2]] = value >>> 16 & 0xff; buffer[offset + order[3]] = value >>> 24 & 0xff; } // ################ // ### DataView ### // ################ function DataView(buffer, byteOffset, byteLength){ if (!(buffer instanceof ArrayBuffer)) { throw new TypeError('DataView must be initialized with an ArrayBuffer'); } if (byteOffset === undefined) { this.byteOffset = buffer.byteOffset >> 0; } else { this.byteOffset = byteOffset >> 0; } if (this.byteOffset < 0) { throw new RangeError('DataView byteOffset must be non-negative'); } if (byteLength === undefined) { this.byteLength = (buffer.byteLength - this.byteOffset) >> 0; } else { this.byteLength = byteLength >> 0; } if (this.byteLength < 0) { throw new RangeError('DataView byteLength must be non-negative'); } if (this.byteOffset + this.byteLength > buffer.byteLength) { throw new RangeError('DataView byteOffset and byteLength greater than ArrayBuffer byteLength'); } this.buffer = buffer; } define(DataView.prototype, { getFloat32: function getFloat32(byteOffset, littleEndian){ return readFloat(this, byteOffset, littleEndian, 23, 4); }, getFloat64: function getFloat64(byteOffset, littleEndian){ return readFloat(this, byteOffset, littleEndian, 52, 8); }, getInt8: function getInt8(byteOffset){ var n = readUint8(this, byteOffset); return n & 0x80 ? n ^ -0x100 : n; }, getInt16: function getInt16(byteOffset, littleEndian){ var n = readUint16(this, byteOffset, littleEndian); return n & 0x8000 ? n ^ -0x10000 : n; }, getInt32: function getInt32(byteOffset, littleEndian){ var n = readUint32(this, byteOffset, littleEndian); return n & 0x80000000 ? n ^ -0x100000000 : n; }, getUint8: function getUint8(byteOffset){ return readUint8(this, byteOffset); }, getUint16: function getUint16(byteOffset, littleEndian){ return readUint16(this, byteOffset, littleEndian); }, getUint32: function getUint32(byteOffset, littleEndian){ return readUint32(this, byteOffset, littleEndian); }, setFloat32: function setFloat32(byteOffset, value, littleEndian){ writeFloat(this, byteOffset, value, littleEndian, 23, 4); }, setFloat64: function setFloat64(byteOffset, value, littleEndian){ writeFloat(this, byteOffset, value, littleEndian, 52, 8); }, setInt8: function setInt8(byteOffset, value){ writeUint8(this, byteOffset, value < 0 ? value | 0x100 : value); }, setInt16: function setInt16(byteOffset, value, littleEndian){ writeUint16(this, byteOffset, value < 0 ? value | 0x10000 : value, littleEndian); }, setInt32: function setInt32(byteOffset, value, littleEndian){ writeUint32(this, byteOffset, value < 0 ? value | 0x100000000 : value, littleEndian); }, setUint8: function setUint8(byteOffset, value){ writeUint8(this, byteOffset, value); }, setUint16: function setUint16(byteOffset, value, littleEndian){ writeUint16(this, byteOffset, value, littleEndian); }, setUint32: function setUint32(byteOffset, value, littleEndian){ writeUint32(this, byteOffset, value, littleEndian); } }); return DataView; })(); }((0,eval)('this'));