(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict'
exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray
var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i]
revLookup[code.charCodeAt(i)] = i
}
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
function placeHoldersCount (b64) {
var len = b64.length
if (len % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
}
function byteLength (b64) {
// base64 is 4/3 + up to two characters of the original data
return b64.length * 3 / 4 - placeHoldersCount(b64)
}
function toByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
var len = b64.length
placeHolders = placeHoldersCount(b64)
arr = new Arr(len * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? len - 4 : len
var L = 0
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
arr[L++] = (tmp >> 16) & 0xFF
arr[L++] = (tmp >> 8) & 0xFF
arr[L++] = tmp & 0xFF
}
if (placeHolders === 2) {
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[L++] = tmp & 0xFF
} else if (placeHolders === 1) {
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[L++] = (tmp >> 8) & 0xFF
arr[L++] = tmp & 0xFF
}
return arr
}
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
}
function encodeChunk (uint8, start, end) {
var tmp
var output = []
for (var i = start; i < end; i += 3) {
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output.push(tripletToBase64(tmp))
}
return output.join('')
}
function fromByteArray (uint8) {
var tmp
var len = uint8.length
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
var output = ''
var parts = []
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1]
output += lookup[tmp >> 2]
output += lookup[(tmp << 4) & 0x3F]
output += '=='
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
output += lookup[tmp >> 10]
output += lookup[(tmp >> 4) & 0x3F]
output += lookup[(tmp << 2) & 0x3F]
output += '='
}
parts.push(output)
return parts.join('')
}
},{}],2:[function(require,module,exports){
(function (global){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
'use strict'
var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('isarray')
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* Due to various browser bugs, sometimes the Object implementation will be used even
* when the browser supports typed arrays.
*
* Note:
*
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
*
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
*
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
* incorrect length in some situations.
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
* get the Object implementation, which is slower but behaves correctly.
*/
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
? global.TYPED_ARRAY_SUPPORT
: typedArraySupport()
/*
* Export kMaxLength after typed array support is determined.
*/
exports.kMaxLength = kMaxLength()
function typedArraySupport () {
try {
var arr = new Uint8Array(1)
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
return arr.foo() === 42 && // typed array instances can be augmented
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) {
return false
}
}
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
function createBuffer (that, length) {
if (kMaxLength() < length) {
throw new RangeError('Invalid typed array length')
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = new Uint8Array(length)
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
if (that === null) {
that = new Buffer(length)
}
that.length = length
}
return that
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer (arg, encodingOrOffset, length) {
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
return new Buffer(arg, encodingOrOffset, length)
}
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new Error(
'If encoding is specified then the first argument must be a string'
)
}
return allocUnsafe(this, arg)
}
return from(this, arg, encodingOrOffset, length)
}
Buffer.poolSize = 8192 // not used by this implementation
// TODO: Legacy, not needed anymore. Remove in next major version.
Buffer._augment = function (arr) {
arr.__proto__ = Buffer.prototype
return arr
}
function from (that, value, encodingOrOffset, length) {
if (typeof value === 'number') {
throw new TypeError('"value" argument must not be a number')
}
if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
return fromArrayBuffer(that, value, encodingOrOffset, length)
}
if (typeof value === 'string') {
return fromString(that, value, encodingOrOffset)
}
return fromObject(that, value)
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(null, value, encodingOrOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
Buffer.prototype.__proto__ = Uint8Array.prototype
Buffer.__proto__ = Uint8Array
if (typeof Symbol !== 'undefined' && Symbol.species &&
Buffer[Symbol.species] === Buffer) {
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
Object.defineProperty(Buffer, Symbol.species, {
value: null,
configurable: true
})
}
}
function assertSize (size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be a number')
} else if (size < 0) {
throw new RangeError('"size" argument must not be negative')
}
}
function alloc (that, size, fill, encoding) {
assertSize(size)
if (size <= 0) {
return createBuffer(that, size)
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpretted as a start offset.
return typeof encoding === 'string'
? createBuffer(that, size).fill(fill, encoding)
: createBuffer(that, size).fill(fill)
}
return createBuffer(that, size)
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(null, size, fill, encoding)
}
function allocUnsafe (that, size) {
assertSize(size)
that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < size; ++i) {
that[i] = 0
}
}
return that
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(null, size)
}
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(null, size)
}
function fromString (that, string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('"encoding" must be a valid string encoding')
}
var length = byteLength(string, encoding) | 0
that = createBuffer(that, length)
var actual = that.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
that = that.slice(0, actual)
}
return that
}
function fromArrayLike (that, array) {
var length = array.length < 0 ? 0 : checked(array.length) | 0
that = createBuffer(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
function fromArrayBuffer (that, array, byteOffset, length) {
array.byteLength // this throws if `array` is not a valid ArrayBuffer
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('\'offset\' is out of bounds')
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('\'length\' is out of bounds')
}
if (byteOffset === undefined && length === undefined) {
array = new Uint8Array(array)
} else if (length === undefined) {
array = new Uint8Array(array, byteOffset)
} else {
array = new Uint8Array(array, byteOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = array
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
that = fromArrayLike(that, array)
}
return that
}
function fromObject (that, obj) {
if (Buffer.isBuffer(obj)) {
var len = checked(obj.length) | 0
that = createBuffer(that, len)
if (that.length === 0) {
return that
}
obj.copy(that, 0, 0, len)
return that
}
if (obj) {
if ((typeof ArrayBuffer !== 'undefined' &&
obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
if (typeof obj.length !== 'number' || isnan(obj.length)) {
return createBuffer(that, 0)
}
return fromArrayLike(that, obj)
}
if (obj.type === 'Buffer' && isArray(obj.data)) {
return fromArrayLike(that, obj.data)
}
}
throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
}
function checked (length) {
// Note: cannot use `length < kMaxLength()` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (length) {
if (+length != length) { // eslint-disable-line eqeqeq
length = 0
}
return Buffer.alloc(+length)
}
Buffer.isBuffer = function isBuffer (b) {
return !!(b != null && b._isBuffer)
}
Buffer.compare = function compare (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('Arguments must be Buffers')
}
if (a === b) return 0
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i]
y = b[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
if (list.length === 0) {
return Buffer.alloc(0)
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; ++i) {
length += list[i].length
}
}
var buffer = Buffer.allocUnsafe(length)
var pos = 0
for (i = 0; i < list.length; ++i) {
var buf = list[i]
if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
buf.copy(buffer, pos)
pos += buf.length
}
return buffer
}
function byteLength (string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length
}
if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
(ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
return string.byteLength
}
if (typeof string !== 'string') {
string = '' + string
}
var len = string.length
if (len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len
case 'utf8':
case 'utf-8':
case undefined:
return utf8ToBytes(string).length
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2
case 'hex':
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.byteLength = byteLength
function slowToString (encoding, start, end) {
var loweredCase = false
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
// This behaves neither like String nor Uint8Array in that we set start/end
// to their upper/lower bounds if the value passed is out of range.
// undefined is handled specially as per ECMA-262 6th Edition,
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
if (start === undefined || start < 0) {
start = 0
}
// Return early if start > this.length. Done here to prevent potential uint32
// coercion fail below.
if (start > this.length) {
return ''
}
if (end === undefined || end > this.length) {
end = this.length
}
if (end <= 0) {
return ''
}
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
end >>>= 0
start >>>= 0
if (end <= start) {
return ''
}
if (!encoding) encoding = 'utf8'
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end)
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end)
case 'ascii':
return asciiSlice(this, start, end)
case 'latin1':
case 'binary':
return latin1Slice(this, start, end)
case 'base64':
return base64Slice(this, start, end)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = (encoding + '').toLowerCase()
loweredCase = true
}
}
}
// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
// Buffer instances.
Buffer.prototype._isBuffer = true
function swap (b, n, m) {
var i = b[n]
b[n] = b[m]
b[m] = i
}
Buffer.prototype.swap16 = function swap16 () {
var len = this.length
if (len % 2 !== 0) {
throw new RangeError('Buffer size must be a multiple of 16-bits')
}
for (var i = 0; i < len; i += 2) {
swap(this, i, i + 1)
}
return this
}
Buffer.prototype.swap32 = function swap32 () {
var len = this.length
if (len % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits')
}
for (var i = 0; i < len; i += 4) {
swap(this, i, i + 3)
swap(this, i + 1, i + 2)
}
return this
}
Buffer.prototype.swap64 = function swap64 () {
var len = this.length
if (len % 8 !== 0) {
throw new RangeError('Buffer size must be a multiple of 64-bits')
}
for (var i = 0; i < len; i += 8) {
swap(this, i, i + 7)
swap(this, i + 1, i + 6)
swap(this, i + 2, i + 5)
swap(this, i + 3, i + 4)
}
return this
}
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function inspect () {
var str = ''
var max = exports.INSPECT_MAX_BYTES
if (this.length > 0) {
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
if (this.length > max) str += ' ... '
}
return '<Buffer ' + str + '>'
}
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
if (!Buffer.isBuffer(target)) {
throw new TypeError('Argument must be a Buffer')
}
if (start === undefined) {
start = 0
}
if (end === undefined) {
end = target ? target.length : 0
}
if (thisStart === undefined) {
thisStart = 0
}
if (thisEnd === undefined) {
thisEnd = this.length
}
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
throw new RangeError('out of range index')
}
if (thisStart >= thisEnd && start >= end) {
return 0
}
if (thisStart >= thisEnd) {
return -1
}
if (start >= end) {
return 1
}
start >>>= 0
end >>>= 0
thisStart >>>= 0
thisEnd >>>= 0
if (this === target) return 0
var x = thisEnd - thisStart
var y = end - start
var len = Math.min(x, y)
var thisCopy = this.slice(thisStart, thisEnd)
var targetCopy = target.slice(start, end)
for (var i = 0; i < len; ++i) {
if (thisCopy[i] !== targetCopy[i]) {
x = thisCopy[i]
y = targetCopy[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
// Empty buffer means no match
if (buffer.length === 0) return -1
// Normalize byteOffset
if (typeof byteOffset === 'string') {
encoding = byteOffset
byteOffset = 0
} else if (byteOffset > 0x7fffffff) {
byteOffset = 0x7fffffff
} else if (byteOffset < -0x80000000) {
byteOffset = -0x80000000
}
byteOffset = +byteOffset // Coerce to Number.
if (isNaN(byteOffset)) {
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
byteOffset = dir ? 0 : (buffer.length - 1)
}
// Normalize byteOffset: negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = buffer.length + byteOffset
if (byteOffset >= buffer.length) {
if (dir) return -1
else byteOffset = buffer.length - 1
} else if (byteOffset < 0) {
if (dir) byteOffset = 0
else return -1
}
// Normalize val
if (typeof val === 'string') {
val = Buffer.from(val, encoding)
}
// Finally, search either indexOf (if dir is true) or lastIndexOf
if (Buffer.isBuffer(val)) {
// Special case: looking for empty string/buffer always fails
if (val.length === 0) {
return -1
}
return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
} else if (typeof val === 'number') {
val = val & 0xFF // Search for a byte value [0-255]
if (Buffer.TYPED_ARRAY_SUPPORT &&
typeof Uint8Array.prototype.indexOf === 'function') {
if (dir) {
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
} else {
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
}
}
return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
}
throw new TypeError('val must be string, number or Buffer')
}
function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
var indexSize = 1
var arrLength = arr.length
var valLength = val.length
if (encoding !== undefined) {
encoding = String(encoding).toLowerCase()
if (encoding === 'ucs2' || encoding === 'ucs-2' ||
encoding === 'utf16le' || encoding === 'utf-16le') {
if (arr.length < 2 || val.length < 2) {
return -1
}
indexSize = 2
arrLength /= 2
valLength /= 2
byteOffset /= 2
}
}
function read (buf, i) {
if (indexSize === 1) {
return buf[i]
} else {
return buf.readUInt16BE(i * indexSize)
}
}
var i
if (dir) {
var foundIndex = -1
for (i = byteOffset; i < arrLength; i++) {
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
if (foundIndex === -1) foundIndex = i
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
} else {
if (foundIndex !== -1) i -= i - foundIndex
foundIndex = -1
}
}
} else {
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
for (i = byteOffset; i >= 0; i--) {
var found = true
for (var j = 0; j < valLength; j++) {
if (read(arr, i + j) !== read(val, j)) {
found = false
break
}
}
if (found) return i
}
}
return -1
}
Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
return this.indexOf(val, byteOffset, encoding) !== -1
}
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}
function hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
// must be an even number of digits
var strLen = string.length
if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; ++i) {
var parsed = parseInt(string.substr(i * 2, 2), 16)
if (isNaN(parsed)) return i
buf[offset + i] = parsed
}
return i
}
function utf8Write (buf, string, offset, length) {
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}
function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}
function latin1Write (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
}
function ucs2Write (buf, string, offset, length) {
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}
Buffer.prototype.write = function write (string, offset, length, encoding) {
// Buffer#write(string)
if (offset === undefined) {
encoding = 'utf8'
length = this.length
offset = 0
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
encoding = offset
length = this.length
offset = 0
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset | 0
if (isFinite(length)) {
length = length | 0
if (encoding === undefined) encoding = 'utf8'
} else {
encoding = length
length = undefined
}
// legacy write(string, encoding, offset, length) - remove in v0.13
} else {
throw new Error(
'Buffer.write(string, encoding, offset[, length]) is no longer supported'
)
}
var remaining = this.length - offset
if (length === undefined || length > remaining) length = remaining
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
throw new RangeError('Attempt to write outside buffer bounds')
}
if (!encoding) encoding = 'utf8'
var loweredCase = false
for (;;) {
switch (encoding) {
case 'hex':
return hexWrite(this, string, offset, length)
case 'utf8':
case 'utf-8':
return utf8Write(this, string, offset, length)
case 'ascii':
return asciiWrite(this, string, offset, length)
case 'latin1':
case 'binary':
return latin1Write(this, string, offset, length)
case 'base64':
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return ucs2Write(this, string, offset, length)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toJSON = function toJSON () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
function base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function utf8Slice (buf, start, end) {
end = Math.min(buf.length, end)
var res = []
var i = start
while (i < end) {
var firstByte = buf[i]
var codePoint = null
var bytesPerSequence = (firstByte > 0xEF) ? 4
: (firstByte > 0xDF) ? 3
: (firstByte > 0xBF) ? 2
: 1
if (i + bytesPerSequence <= end) {
var secondByte, thirdByte, fourthByte, tempCodePoint
switch (bytesPerSequence) {
case 1:
if (firstByte < 0x80) {
codePoint = firstByte
}
break
case 2:
secondByte = buf[i + 1]
if ((secondByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
if (tempCodePoint > 0x7F) {
codePoint = tempCodePoint
}
}
break
case 3:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
codePoint = tempCodePoint
}
}
break
case 4:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
fourthByte = buf[i + 3]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
codePoint = tempCodePoint
}
}
}
}
if (codePoint === null) {
// we did not generate a valid codePoint so insert a
// replacement char (U+FFFD) and advance only 1 byte
codePoint = 0xFFFD
bytesPerSequence = 1
} else if (codePoint > 0xFFFF) {
// encode to utf16 (surrogate pair dance)
codePoint -= 0x10000
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
codePoint = 0xDC00 | codePoint & 0x3FF
}
res.push(codePoint)
i += bytesPerSequence
}
return decodeCodePointsArray(res)
}
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000
function decodeCodePointsArray (codePoints) {
var len = codePoints.length
if (len <= MAX_ARGUMENTS_LENGTH) {
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
}
// Decode in chunks to avoid "call stack size exceeded".
var res = ''
var i = 0
while (i < len) {
res += String.fromCharCode.apply(
String,
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
)
}
return res
}
function asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i] & 0x7F)
}
return ret
}
function latin1Slice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i])
}
return ret
}
function hexSlice (buf, start, end) {
var len = buf.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(buf[i])
}
return out
}
function utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
}
return res
}
Buffer.prototype.slice = function slice (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len
if (start < 0) start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0) end = 0
} else if (end > len) {
end = len
}
if (end < start) end = start
var newBuf
if (Buffer.TYPED_ARRAY_SUPPORT) {
newBuf = this.subarray(start, end)
newBuf.__proto__ = Buffer.prototype
} else {
var sliceLen = end - start
newBuf = new Buffer(sliceLen, undefined)
for (var i = 0; i < sliceLen; ++i) {
newBuf[i] = this[i + start]
}
}
return newBuf
}
/*
* Need to make sure that buffer isn't trying to write out of bounds.
*/
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.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
return val
}
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
checkOffset(offset, byteLength, this.length)
}
var val = this[offset + --byteLength]
var mul = 1
while (byteLength > 0 && (mul *= 0x100)) {
val += this[offset + --byteLength] * mul
}
return val
}
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[offset + 2] << 8) |
this[offset + 3])
}
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var i = byteLength
var mul = 1
var val = this[offset + --i]
while (i > 0 && (mul *= 0x100)) {
val += this[offset + --i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
if (!(this[offset] & 0x80)) return (this[offset])
return ((0xff - this[offset] + 1) * -1)
}
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset] | (this[offset + 1] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset + 1] | (this[offset] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16) |
(this[offset + 3] << 24)
}
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] << 24) |
(this[offset + 1] << 16) |
(this[offset + 2] << 8) |
(this[offset + 3])
}
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, true, 23, 4)
}
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, false, 23, 4)
}
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, true, 52, 8)
}
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, false, 52, 8)
}
function checkInt (buf, value, offset, ext, max, min) {
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
if (offset + ext > buf.length) throw new RangeError('Index out of range')
}
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var mul = 1
var i = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var i = byteLength - 1
var mul = 1
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
this[offset] = (value & 0xff)
return offset + 1
}
function objectWriteUInt16 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
(littleEndian ? i : 1 - i) * 8
}
}
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
function objectWriteUInt32 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffffffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
}
}
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset + 3] = (value >>> 24)
this[offset + 2] = (value >>> 16)
this[offset + 1] = (value >>> 8)
this[offset] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = 0
var mul = 1
var sub = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = byteLength - 1
var mul = 1
var sub = 0
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
if (value < 0) value = 0xff + value + 1
this[offset] = (value & 0xff)
return offset + 1
}
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
this[offset + 2] = (value >>> 16)
this[offset + 3] = (value >>> 24)
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (value < 0) value = 0xffffffff + value + 1
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
function checkIEEE754 (buf, value, offset, ext, max, min) {
if (offset + ext > buf.length) throw new RangeError('Index out of range')
if (offset < 0) throw new RangeError('Index out of range')
}
function writeFloat (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
}
ieee754.write(buf, value, offset, littleEndian, 23, 4)
return offset + 4
}
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
return writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
return writeFloat(this, value, offset, false, noAssert)
}
function writeDouble (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
}
ieee754.write(buf, value, offset, littleEndian, 52, 8)
return offset + 8
}
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
return writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
return writeDouble(this, value, offset, false, noAssert)
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (targetStart >= target.length) targetStart = target.length
if (!targetStart) targetStart = 0
if (end > 0 && end < start) end = start
// Copy 0 bytes; we're done
if (end === start) return 0
if (target.length === 0 || this.length === 0) return 0
// Fatal error conditions
if (targetStart < 0) {
throw new RangeError('targetStart out of bounds')
}
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
if (end < 0) throw new RangeError('sourceEnd out of bounds')
// Are we oob?
if (end > this.length) end = this.length
if (target.length - targetStart < end - start) {
end = target.length - targetStart + start
}
var len = end - start
var i
if (this === target && start < targetStart && targetStart < end) {
// descending copy from end
for (i = len - 1; i >= 0; --i) {
target[i + targetStart] = this[i + start]
}
} else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
// ascending copy from start
for (i = 0; i < len; ++i) {
target[i + targetStart] = this[i + start]
}
} else {
Uint8Array.prototype.set.call(
target,
this.subarray(start, start + len),
targetStart
)
}
return len
}
// Usage:
// buffer.fill(number[, offset[, end]])
// buffer.fill(buffer[, offset[, end]])
// buffer.fill(string[, offset[, end]][, encoding])
Buffer.prototype.fill = function fill (val, start, end, encoding) {
// Handle string cases:
if (typeof val === 'string') {
if (typeof start === 'string') {
encoding = start
start = 0
end = this.length
} else if (typeof end === 'string') {
encoding = end
end = this.length
}
if (val.length === 1) {
var code = val.charCodeAt(0)
if (code < 256) {
val = code
}
}
if (encoding !== undefined && typeof encoding !== 'string') {
throw new TypeError('encoding must be a string')
}
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
} else if (typeof val === 'number') {
val = val & 255
}
// Invalid ranges are not set to a default, so can range check early.
if (start < 0 || this.length < start || this.length < end) {
throw new RangeError('Out of range index')
}
if (end <= start) {
return this
}
start = start >>> 0
end = end === undefined ? this.length : end >>> 0
if (!val) val = 0
var i
if (typeof val === 'number') {
for (i = start; i < end; ++i) {
this[i] = val
}
} else {
var bytes = Buffer.isBuffer(val)
? val
: utf8ToBytes(new Buffer(val, encoding).toString())
var len = bytes.length
for (i = 0; i < end - start; ++i) {
this[i + start] = bytes[i % len]
}
}
return this
}
// HELPER FUNCTIONS
// ================
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
function base64clean (str) {
// Node strips out invalid characters like \n and \t from the string, base64-js does not
str = stringtrim(str).replace(INVALID_BASE64_RE, '')
// Node converts strings with length < 2 to ''
if (str.length < 2) return ''
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
while (str.length % 4 !== 0) {
str = str + '='
}
return str
}
function stringtrim (str) {
if (str.trim) return str.trim()
return str.replace(/^\s+|\s+$/g, '')
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}
function utf8ToBytes (string, units) {
units = units || Infinity
var codePoint
var length = string.length
var leadSurrogate = null
var bytes = []
for (var i = 0; i < length; ++i) {
codePoint = string.charCodeAt(i)
// is surrogate component
if (codePoint > 0xD7FF && codePoint < 0xE000) {
// last char was a lead
if (!leadSurrogate) {
// no lead yet
if (codePoint > 0xDBFF) {
// unexpected trail
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
} else if (i + 1 === length) {
// unpaired lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
}
// valid lead
leadSurrogate = codePoint
continue
}
// 2 leads in a row
if (codePoint < 0xDC00) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = codePoint
continue
}
// valid surrogate pair
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
} else if (leadSurrogate) {
// valid bmp char, but last char was a lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
}
leadSurrogate = null
// encode utf8
if (codePoint < 0x80) {
if ((units -= 1) < 0) break
bytes.push(codePoint)
} else if (codePoint < 0x800) {
if ((units -= 2) < 0) break
bytes.push(
codePoint >> 0x6 | 0xC0,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x10000) {
if ((units -= 3) < 0) break
bytes.push(
codePoint >> 0xC | 0xE0,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x110000) {
if ((units -= 4) < 0) break
bytes.push(
codePoint >> 0x12 | 0xF0,
codePoint >> 0xC & 0x3F | 0x80,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else {
throw new Error('Invalid code point')
}
}
return bytes
}
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 utf16leToBytes (str, units) {
var c, hi, lo
var byteArray = []
for (var i = 0; i < str.length; ++i) {
if ((units -= 2) < 0) break
c = str.charCodeAt(i)
hi = c >> 8
lo = c % 256
byteArray.push(lo)
byteArray.push(hi)
}
return byteArray
}
function base64ToBytes (str) {
return base64.toByteArray(base64clean(str))
}
function blitBuffer (src, dst, offset, length) {
for (var i = 0; i < length; ++i) {
if ((i + offset >= dst.length) || (i >= src.length)) break
dst[i + offset] = src[i]
}
return i
}
function isnan (val) {
return val !== val // eslint-disable-line no-self-compare
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"base64-js":1,"ieee754":3,"isarray":4}],3:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var nBits = -7
var i = isLE ? (nBytes - 1) : 0
var d = isLE ? -1 : 1
var 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.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
var i = isLE ? 0 : (nBytes - 1)
var d = isLE ? 1 : -1
var 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
}
},{}],4:[function(require,module,exports){
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
},{}],5:[function(require,module,exports){
(function (Buffer){
'use strict';
/**
* @file Services Descriptor Bundle encoding and decoding library.
*
* @version 0.2.2
* @author Patrick Bay (Monican Agent)
* @copyright MIT License
*/
/**
* @class Handles encoding and decoding of Services Descriptor Bundle data to / from
* various formats.
*
* @see Ascii85/Base85 encoding and decoding adapted from ascii85.js by Yuri Konotopov -
* <a href="https://github.com/nE0sIghT/ascii85.js">https://github.com/nE0sIghT/ascii85.js</a>
*/
class SDB {
/**
* Creates a new SDB instance.
*/
constructor() {
}
/**
* @property {Number} version=0 The SDB header / data format version
* used with coded binary data.
*/
static get version() {
return (1);
}
/**
* Validates a version 0 SDB entity object to ensure that there are no
* invalid or missing data properties.
*
* @param {Object} entityObj The entity object to validate.
*
* @return {null|String} A <code>null</code> is returned if all validation
* passed, otherwise a string is returned describing the validation failure.
*
* @static
*/
static validateEntityObject (entityObj) {
if (typeof(entityObj) != "object") {
return ("Entity must be an object.");
}
if (entityObj.entity == undefined) {
return ("\"entity\" property is required.");
}
if (typeof(entityObj.entity) != "string") {
return ("\"entity\" property must be a string.");
}
for (var dataType in entityObj) {
switch (dataType) {
case "entity":
var entType = entityObj[dataType];
if ((entType != "api") && (entType != "p2p") && (entType != "peer")) {
return ("\""+entType+"\" is not a recognized entity type.");
}
break;
case "name":
if (typeof(entityObj[dataType]) != "string") {
return ("\"name\" property must be a string.");
}
break;
case "description":
if (typeof(entityObj[dataType]) != "string") {
return ("\"description\" property must be a string.");
}
break;
case "transport":
switch (entityObj[dataType]) {
case "http": break;
case "wss": break;
case "wsst": break;
case "webrtc": break;
default:
return ("\""+entityObj[dataType]+"\" is not a recognized transport.");
break;
}
break;
case "protocol":
switch (entityObj[dataType]) {
case "http": break;
case "https": break;
case "ws": break;
case "wss": break;
default:
return ("\""+entityObj[dataType]+"\" is not a recognized protocol.");
break;
}
break;
case "host":
if (typeof(entityObj[dataType]) != "string") {
return ("\"host\" property must be a string.");
}
break;
case "port":
if (typeof(entityObj[dataType]) != "number") {
return ("\"port\" must be a number.");
}
break;
case "parameters":
if (typeof(entityObj[dataType]) != "string") {
return ("\"parameters\" property must be a string.");
}
break;
}
}
return (null); // everything looks okay
}
/**
* @property {Array} data=null The native JavaScript indexed array containing
* the SDB associated with this instance.
*
* @readonly
*/
get data() {
if (this._data == undefined) {
this._data = null;
}
return (this._data);
}
/**
* @property {Buffer} bin=null The native binary Buffer containing the SDB
* associated with this instance.
*
* @readonly
*/
get bin() {
if (this._bin == undefined) {
this._bin = null;
}
return (this._bin);
}
/**
* Encodes the native SDB [data]{@link SDB@data} object to a compressed
* base85 or base64 string. The processed binary data is also set to the
* [bin]{@link SDB@bin} Buffer.
*
* @param {String} [encoding="base85"] The desired data encoding to use,
* either "base85" or "base64".
* @param {Function} [processPipe=null] An optional processing function
* to be applied to the SDB binary Buffer before applying the <code>encoding</code>.
* If the referenced function is asynchronous (it returns a <code>Promise</code>),
* then This function will also return a <code>Promise</code> that will
* resolve when the <code>processPipe</code> has resolved, otherwise
* this function will be trated as a synchronous inline function.
*
* @return {Promise} An asynchronous promise is returned that resolves withthe
* SDB [data]{@link SDB@data} in the desired encoding.
*
*/
encode(encoding="base85", processPipe=null) {
if (this.data == null) {
throw (new Error("No SDB to encode."));
}
var entitiesBuff = Buffer.alloc(0);
var historyArr = new Array();
for (var count=0; count < this.data.length; count++) {
var entityData = this.data[count];
if (typeof(entityData.entity) != "string") {
throw (new Error ("Missing or wrong type \"+entity+\" property."));
}
var encodedEntity = this.encodeEntity(entityData, count, historyArr);
var newLength = entitiesBuff.length + encodedEntity.length;
entitiesBuff = Buffer.concat([entitiesBuff, encodedEntity], newLength);
}
//prepend version
var versionBuff = Buffer.from([SDB.version]);
newLength = entitiesBuff.length + 1;
entitiesBuff = Buffer.concat([versionBuff, entitiesBuff], newLength);
this._bin = entitiesBuff;
var promise = new Promise((resolve, reject) => {
if (processPipe != null) {
var result = processPipe(entitiesBuff);
if (result instanceof Promise) {
result.then(entitiesBuff => {
if ((encoding == "base85") || (encoding == "ascii85")) {
var returnStr = this.bufferToBase85(entitiesBuff);
} else if (encoding == "base64") {
returnStr = entitiesBuff.toString(encoding);
} else if (encoding == "none") {
returnStr = null;
}
resolve(returnStr);
})
} else {
if ((encoding == "base85") || (encoding == "ascii85")) {
var returnStr = this.bufferToBase85(entitiesBuff);
} else if (encoding == "base64") {
returnStr = entitiesBuff.toString(encoding);
} else if (encoding == "none") {
returnStr = null;
}
resolve(returnStr);
}
} else {
if ((encoding == "base85") || (encoding == "ascii85")) {
var returnStr = this.bufferToBase85(entitiesBuff);
} else if (encoding == "base64") {
returnStr = entitiesBuff.toString(encoding);
} else if (encoding == "none") {
returnStr = null;
}
resolve(returnStr);
}
});
return (promise);
}
/**
* Decodes the supplied SDB data and assigns it to the [data]{@link SDB@data}
* and [bin]{@link SDB@bin} properties if successful.
*
* @param {String|Array|Buffer} SDBData The data to decode. If this is a string,
* it is decoded using either the detected encoding method or the one specified
* by the <code>encoding</code> parameter. If this is an array it's assumed to
* be a native object and assigned to [data]{@link SDB@data} and [data]{@link SDB@data}.
* If this is a Buffer, it's assigned directly to the [data]{@link SDB@data} and
* decoded to [data]{@link SDB@data}.
* @param {String} [encoding=null] The string encoding used for <code>SDBData</code>
* if it's a string. If <code>SDBData</code> is not a string this parameter is ignored.
* If <code>processPipe</code> was supplied and was asynchronous (it returned a
* <code>Promise</code>) then a <code>Promise</code> will also be returned here and
* resolved when the <code>processPipe</code> resolves.
* @param {Function} [processPipe=null] An optional processing function
* to be applied to the decoded but unparsed SDB binary Buffer before applying
* the <code>decoding</code>.
*
* @return {Promise} An asynchronous promise is returned that resolves when the
* decoding process has completed.
*/
decode(SDBData, encoding=null, processPipe=null) {
if (SDBData instanceof Array) {
//no need to parse this
this._data = SDBData;
var promise = new Promise((resolve, reject) => {
this.encode("none").then(result => {
if (processPipe != null) {
if (processPipe instanceof Promise) {
processPipe(this.bin).then(result => {
resolve (this.bin);
})
} else {
result = processPipe(this.bin);
resolve (this.bin);
}
} else {
resolve (this.bin);
}
});
});
return (promise);
} else if (SDBData instanceof Buffer) {
//already native
var decodeBuff = SDBData;
} else if (typeof(SDBData) == "string") {
//either Base85 or Base64
SDBData = SDBData.trim();
if ((SDBData.indexOf("<~") > -1) || (encoding == "base85") || (encoding == "ascii85")) {
decodeBuff = this.base85ToBuffer(SDBData);
} else {
decodeBuff = Buffer.from(SDBData, "base64");
}
} else {
throw (new Error("Data type not recognized."));
}
var promise = new Promise((resolve, reject) => {
if (processPipe != null) {
var response = processPipe(decodeBuff);
if (response instanceof Promise) {
response.then(decodeBuff => {
var sdbVersion = decodeBuff.readUInt8(0);
if (sdbVersion != SDB.version) {
//future revisions may need more comlex checks
throw (new Error("SDB verion "+sdbVersion+ " does not match supported version "+SDB.version));
}
this._data = new Array();
var historyArr = new Array();
var entityIndex = 0;
var offset = 1;
while (offset < decodeBuff.length) {
try {
var entityObj = this.readEntity(decodeBuff, offset);
offset = entityObj.nextOffset;
this._data.push(this.decodeEntity(entityObj, entityIndex, historyArr));
entityIndex++;
} catch (err) {
offset = decodeBuff.length + 1;
}
}
});
resolve(true);
} else {
var sdbVersion = decodeBuff.readUInt8(0);
if (sdbVersion != SDB.version) {
//future revisions may need more comlex checks
throw (new Error("SDB verion "+sdbVersion+ " does not match supported version "+SDB.version));
}
this._data = new Array();
var historyArr = new Array();
var entityIndex = 0;
var offset = 1;
while (offset < decodeBuff.length) {
try {
var entityObj = this.readEntity(decodeBuff, offset);
offset = entityObj.nextOffset;
this._data.push(this.decodeEntity(entityObj, entityIndex, historyArr));
entityIndex++;
} catch (err) {
offset = decodeBuff.length + 1;
}
}
resolve(true);
}
} else {
var sdbVersion = decodeBuff.readUInt8(0);
if (sdbVersion != SDB.version) {
//future revisions may need more comlex checks
throw (new Error("SDB verion "+sdbVersion+ " does not match supported version "+SDB.version));
}
this._data = new Array();
var historyArr = new Array();
var entityIndex = 0;
var offset = 1;
while (offset < decodeBuff.length) {
try {
var entityObj = this.readEntity(decodeBuff, offset);
offset = entityObj.nextOffset;
this._data.push(this.decodeEntity(entityObj, entityIndex, historyArr));
entityIndex++;
} catch (err) {
offset = decodeBuff.length + 1;
}
}
resolve(true);
}
});
return (promise);
}
/**
* Encodes a binary Buffer to a Base85 / Ascii85 string.
*
* @param {Buffer} dataBuff The binary buffer to encode.
* @param {Boolean} [useDelimiters=true] If true, the Base85 <code><~ .. ~></code>
* bookend delimiters are included with the encoded string, otherwise the string
* is returned without them.
*
* @return {String} The Base85 / Ascii85 encoded string representation of the
* <code>dataBuff</code> Buffer.
*/
bufferToBase85(dataBuff, useDelimiters=true) {
var output = new Array();
if (useDelimiters) {
output.push(0x3c);
output.push(0x7e);
}
for (var count = 0; count < dataBuff.length; count += 4) {
let uint32 = Buffer.alloc(4);
let bytes = 4;
for (var count2 = 0; count2 < 4; count2++) {
if ((count + count2) < dataBuff.length) {
uint32[count2] = dataBuff[count + count2];
} else {
uint32[count2] = 0x00;
bytes--;
}
}
var chunk = this.getB85EncChunk(uint32, bytes);
for (count2 = 0; count2 < chunk.length; count2++) {
output.push(chunk[count2]);
}
}
if (useDelimiters) {
output.push(0x7e);
output.push(0x3e);
}
var outBuff = Buffer.from(output);
output = outBuff.toString("ascii");
return (output);
}
/**
* Encodes a Base85 / Ascii85 representation of a 32-bit unsigned integer.
*
* @param {Array} uint32 The data array containing values to encode.
*
* @return {String} A Base85 / Ascii85 representation if the input <code>uint32</code>.
*
* @private
*/
getB85EncChunk(uint32) {
var bytes = 4;
var dataChunk = ((uint32[0] << 24) | (uint32[1] << 16) | (uint32[2] << 8) | uint32[3]) >>> 0;
if (dataChunk === 0 && bytes == 4) {
var output = Buffer.alloc(1);
output[0] = 0x7a;
} else {
output = Buffer.alloc(bytes + 1);
for (var count = 4; count >= 0; count--) {
if (count <= bytes) {
output[count] = dataChunk % 85 + 0x21;
}
dataChunk /= 85;
}
}
return (output);
}
/**
* Converts a native 32-bit value to a multibyte array.
*
* @param {Number} uint32 The 32-bit value to split into 4 bytes.
* @param {Number} bytes The number of bytes in the <code>uint32</code>
* parameter to process.
*
* @return {Array} A byte array containg the binary representation of
* the input <code>uint32</code>
*
* @private
*/
uint32ToArray(uint32, bytes=4) {
var bitArr = [24, 16, 8, 0];
let output = Buffer.alloc(bytes);
for (var count = 0; count < bytes; count++) {
output[count] = (uint32 >> bitArr[count]) & 0x00ff;
}
return (output);
}
/**
* Converts a 32-bit unsigned integer value to a 4-byte array and
* pushes it onto an existing array of 4-byte values.
*
* @param {Number} uint32 The unsigned 32-bit integer value to push.
* @param {Number} uintIndex The number of bytes, minus 1, to convert
* to a byte array from <code>uint32</code>/
* @param {Array} uint32Array The byte array to which to append the byte
* array created from <code>uint32</code>.
*
* @private
*/
pushUint32Array(uint32, uintIndex, uint32Array) {
var byteArray = this.uint32ToArray(uint32, uintIndex - 1);
for (var count = 0; count < byteArray.length; count++) {
uint32Array.push(byteArray[count]);
}
}
/**
* Converts a Base85 / Ascii85 string to a Buffer.
*
* @param {String} b85String The Base58-encoded string to convert.
*
* @return {Buffer} The binary data represented by the <code>b85String</code>.
*
* @private
*/
base85ToBuffer(b85String) {
var pow85Arr = [Math.pow(85,4), Math.pow(85,3), Math.pow(85,2), 85, 1];
var output = new Array();
var stop = false;
var uint32 = 0;
var uint32Index = 0;
var position = 0;
if ((b85String.startsWith("<~") && b85String.length) > 2) {
var position = 2;
}
do {
if (b85String.charAt(position).trim().length === 0) {
//skip whitespace
continue;
}
var charCode = b85String.charCodeAt(position);
switch(charCode) {
case 0x7a:
if (uint32Index != 0) {
throw (new Error("Unexpected 'z' character at position " + i));
}
for (var count = 0; count < 4; count++) {
output.push(0x00);
}
break;
case 0x7e:
var nextChar = '';
var count = position + 1; // Skip whitespace + 1;
while (count < b85String.length && nextChar.trim().length == 0) {
nextChar = b85String.charAt(count++);
}
if (nextChar != '>') {
throw (new Error("Broken EOD at position " + j));
}
if (uint32Index) {
uint32 += pow85Arr[uint32Index - 1];
this.pushUint32Array(uint32, uint32Index, output);
uint32 = uint32Index = 0;
}
stop = true;
break;
default:
if ((charCode < 0x21) || (charCode > 0x75)) {
throw (new Error("Unexpected character with code " + charCode + " at position " + position));
}
uint32 += (charCode - 0x21) * pow85Arr[uint32Index++];
if (uint32Index >= 5) {
this.pushUint32Array(uint32, uint32Index, output);
uint32 = uint32Index = 0;
}
}
} while ((position++ < b85String.length) && (stop == false));
var outputBuff = Buffer.from(output);
return (outputBuff);
}
/**
* Reads a single SDB entity binary object and returns information about it.
*
* @param {Buffer} SDBBuffer The Buffer cotaining the entity to read.
* @param {Number} offset The byte offset at which the SDB entity starts within
* the <code>SDBBuffer</code>
*
* @return {Object} Contains the starting <code>offset</code> of the entity,
* the <code>nextOffset</code> (offset of the next entity), SDB <code>headerSize</code>,
* SDB <code>dataSize</code>, the <code>totalSize</code> (header plus data), the
* SDB entity <code>type</code>, and a pointer Buffer to the entity <code>data</code>.
*
* @private
*/
readEntity(SDBBuffer, offset) {
var headerSize = 5; //includes type and size
var entityType = SDBBuffer.readUInt8(offset + 0);
var dataSize = SDBBuffer.readUInt8(offset + 1) << 24;
dataSize = dataSize | SDBBuffer.readUInt8(offset + 2) << 16;
dataSize = dataSize | (SDBBuffer.readUInt8(offset + 3) << 8);
dataSize = dataSize | SDBBuffer.readUInt8(offset + 4);
var entityData = SDBBuffer.slice(offset + headerSize, offset + headerSize + dataSize); //note that this is a shared reference, not a new instance
var returnObj = new Object();
returnObj.offset = offset;
returnObj.nextOffset = offset + dataSize + headerSize;
returnObj.headerSize = headerSize;
returnObj.dataSize = dataSize;
returnObj.totalSize = dataSize + headerSize;
returnObj.type = entityType;
returnObj.data = entityData;
return (returnObj);
}
/**
* Decodes a single SDB entity and all of the contained data elements.
*
* @param {Object} entityObj An entity information object such as that cerated by
* [readEntity]{@link SDB#readEntity}.
* @param {Number} entityIndex The index of the entity being decoded, usually reflected
* in the entity's position within the [data]{@link SDB#data} array.
* @param {Array} historyArr Array of objects to use to determine reference data.
*
* @return {Object} The native JavaScript object representation of the SDB entity
* stored in <code>entityObj<code>.
*
* @private
*/
decodeEntity(entityObj, entityIndex, historyArr) {
var returnObj = new Object();
switch(entityObj.type) {
case 0:
returnObj.entity = "api";
break;
case 1:
returnObj.entity = "p2p";
break;
case 2:
returnObj.entity = "peer";
break;
default:
break;
}
var offset = 0;
var entityData = this.readEntityData(entityObj.data, offset);
while (entityData != null) {
offset = entityData.offset;
var entPropObj = this.getEntPropHistory(entityData.name, entityData.value, historyArr);
var previousIndex = entPropObj.entityIndex;
if (previousIndex > -1) {
//previous entity property already exists in history
for (var count=0; count < historyArr.length; count++) {
var historyObj = historyArr[count];
if ((historyObj.propName == entityData.name) && (historyObj.entityIndex == previousIndex)) {
entityData.value = historyObj.propValue;
}
}
}
returnObj[entityData.name] = entityData.value;
this.addEntPropHistory (entityData.name, entityData.value, entityIndex, historyArr);
entityData = this.readEntityData(entityObj.data, offset);
}
return (returnObj);
}
/**
* Reads the data, properties, or name-value pair of a SDB entity.
*
* @param {Buffer} entityBuffer The Buffer from which to extract the entity data.
* @param {Number} offset The offset, in bytes, of the data to extract within the
* entity data.
*
* @return {Object} The extracted data <code>name</code>, <code>value</code>,
* and an updated <code>offset</code> pointing to the next entity data object.
*
* @private
*/
readEntityData(entityBuffer, offset) {
if (entityBuffer.length == 0) {
return (null);
}
if (offset >= entityBuffer.length) {
return (null);
}
var returnObj = new Object();
var descriptorType = entityBuffer.readUInt8(offset);
var typeHeaderSize = 1; //1 byte for descriptorType
switch (descriptorType) {
case 0:
//name
var dataLength = entityBuffer.readUInt8(offset + 1) << 8;
dataLength = dataLength | entityBuffer.readUInt8(offset + 2);
typeHeaderSize += 2; //2 bytes for dataLength
var sliceStart = typeHeaderSize + offset;
var sliceEnd = dataLength + typeHeaderSize + offset;
var entityData = entityBuffer.slice(sliceStart, sliceEnd);
returnObj.name = "name";
returnObj.value = entityData.toString("utf8");
returnObj.offset = offset + entityData.length + typeHeaderSize;
break;
case 1:
//description
dataLength = entityBuffer.readUInt8(offset + 1) << 8;
dataLength = dataLength | entityBuffer.readUInt8(offset + 2);
typeHeaderSize += 2; //2 bytes for dataLength
sliceStart = typeHeaderSize + offset;
sliceEnd = dataLength + typeHeaderSize + offset;
entityData = entityBuffer.slice(sliceStart, sliceEnd);
returnObj.name = "description";
returnObj.value = entityData.toString("utf8");
returnObj.offset = offset + dataLength + typeHeaderSize;
break;
case 2:
//type
var typeVal = entityBuffer.readUInt8(offset + 1);
typeHeaderSize += 1;
returnObj.name = "transport";
switch (typeVal) {
case 0:
returnObj.value = "http";
break;
case 1:
returnObj.value = "wss";
break;
case 2:
returnObj.value = "wsst";
break;
case 3:
returnObj.value = "webrtc";
break;
default:
returnObj.value = "";
break;
}
returnObj.offset = offset + typeHeaderSize;
break;
case 3:
//protocol
returnObj.name = "protocol";
typeVal = entityBuffer.readUInt8(offset + 1);
typeHeaderSize += 1;
switch (typeVal) {
case 0:
returnObj.value = "http";
break;
case 1:
returnObj.value = "htps";
break;
case 2:
returnObj.value = "ws";
break;
case 3:
returnObj.value = "wss";
break;
default:
returnObj.value = "";
break;
}
returnObj.offset = offset + typeHeaderSize;
break;
case 4:
//host
returnObj.name = "host";
typeVal = entityBuffer.readUInt8(offset + 1);
typeHeaderSize += 1;
switch (typeVal) {
case 0:
//IPv4
var IPAddr = String(entityBuffer.readUInt8(offset + 2)) + ".";
IPAddr += String(entityBuffer.readUInt8(offset + 3)) + ".";
IPAddr += String(entityBuffer.readUInt8(offset + 4)) + ".";
IPAddr += String(entityBuffer.readUInt8(offset + 5));
typeHeaderSize += 4;
returnObj.value = IPAddr;
returnObj.offset = offset + typeHeaderSize;
break;
case 1:
//IPv6 -- not currently handled
//typeHeaderSize += 16;
returnObj.value = "";
break;
case 2:
//named
dataLength = entityBuffer.readUInt8(offset + 2) << 8;
dataLength = dataLength | entityBuffer.readUInt8(offset + 3);
typeHeaderSize += 2; //2 bytes for dataLength
sliceStart = typeHeaderSize + offset;
sliceEnd = dataLength + typeHeaderSize + offset;
entityData = entityBuffer.slice(sliceStart, sliceEnd);
returnObj.value = entityData.toString("utf8");
returnObj.offset = offset + dataLength + typeHeaderSize;
break;
default:
break;
}
break;
case 5:
//port
returnObj.name = "port";
entityData = entityBuffer.readUInt8(offset + 1) << 8;
entityData = entityData | entityBuffer.readUInt8(offset + 2);
typeHeaderSize += 2;
returnObj.value = entityData;
returnObj.offset = offset + typeHeaderSize;
break;
case 6:
//parameters
returnObj.name = "parameters";
dataLength = entityBuffer.readUInt8(offset + 1) << 16;
dataLength = dataLength | (entityBuffer.readUInt8(offset + 2) << 8);
dataLength = dataLength | entityBuffer.readUInt8(offset + 3);
typeHeaderSize += 3;
sliceStart = typeHeaderSize + offset;
sliceEnd = dataLength + typeHeaderSize + offset;
entityData = entityBuffer.slice(sliceStart, sliceEnd);
returnObj.value = entityData.toString("utf8");
returnObj.offset = offset + dataLength + typeHeaderSize;
break;
case 7:
//name reference
returnObj.name = "name";
var refIndex = entityBuffer.readUInt8(offset + 1) << 8;
refIndex = refIndex | entityBuffer.readUInt8(offset + 2);
//get history ref here
typeHeaderSize += 2;
returnObj.value = null;
returnObj.offset = offset + typeHeaderSize;
break;
case 8:
//description reference
returnObj.name = "description";
var refIndex = entityBuffer.readUInt8(offset + 1) << 8;
refIndex = refIndex | entityBuffer.readUInt8(offset + 2);
//get history ref here
typeHeaderSize += 2;
returnObj.value = null;
returnObj.offset = offset + typeHeaderSize;
break;
case 9:
//host reference
returnObj.name = "host";
var refIndex = entityBuffer.readUInt8(offset + 1) << 8;
refIndex = refIndex | entityBuffer.readUInt8(offset + 2);
//get history ref here
typeHeaderSize += 2;
returnObj.value = null;
returnObj.offset = offset + typeHeaderSize;
break;
case 10:
//port reference
returnObj.name = "port";
var refIndex = entityBuffer.readUInt8(offset + 1) << 8;
refIndex = refIndex | entityBuffer.readUInt8(offset + 2);
//get history ref here
typeHeaderSize += 2;
returnObj.value = null;
returnObj.offset = offset + typeHeaderSize;
break;
case 11:
//parameters reference
returnObj.name = "parameters";
var refIndex = entityBuffer.readUInt8(offset + 1) << 8;
refIndex = refIndex | entityBuffer.readUInt8(offset + 2);
//get history ref here
typeHeaderSize += 2;
returnObj.value = null;
returnObj.offset = offset + typeHeaderSize;
break;
default:
break;
}
return (returnObj);
}
/**
* Converts a native JavaScript SDB entity to a compressed binary one.
*
* @param {Object} entityData The native JavaScript entity object to convert
* @param {Number} entityIndex The index of the entitiy object, usually as found
* within the [data]{@link SDB#data} array.
* @param {Array} historyArr The history array to use to create reference
* data entries.
*
* @return {Buffer} The compressed binary representaion of the <code>entityData</code>
* including all headers.
*
* @private
*/
encodeEntity(entityData, entityIndex, historyArr) {
var returnBuff = Buffer.alloc(0);
var header = Buffer.alloc(0);
for (var entityProperty in entityData) {
var entityValue = entityData[entityProperty];
switch (entityProperty) {
case "entity":
//assign to header instead of returnBuff
var header = this.encodeSDBEntityData(entityProperty, entityValue, entityIndex, historyArr);
break;
case "url":
//parse compact form url
var urlObj = new URL(entityValue);
var protocol = urlObj.protocol;
protocol = protocol.split(":")[0]; //no trailing ":"
if (protocol == "") {
throw (new Error("Entity URL \""+entityValue+"\" uses an invalid protocol"));
}
var entityBuff = this.encodeSDBEntityData("protocol", protocol, entityIndex, historyArr);
var newLength = returnBuff.length + entityBuff.length;
returnBuff = Buffer.concat([returnBuff, entityBuff], newLength);
var host = urlObj.hostname;
//strip out IPv6 URL enclosure, as per https://tools.ietf.org/html/rfc2732
host = host.split("[").join("").split("]").join("");
entityBuff = this.encodeSDBEntityData("host", host, entityIndex, historyArr);
newLength = returnBuff.length + entityBuff.length;
returnBuff = Buffer.concat([returnBuff, entityBuff], newLength);
var port = Number(urlObj.port);
if (port != "") {
entityBuff = this.encodeSDBEntityData("port", port, entityIndex, historyArr);
newLength = returnBuff.length + entityBuff.length;
returnBuff = Buffer.concat([returnBuff, entityBuff], newLength);
}
var search = urlObj.search;
if (search != "") {
entityBuff = this.encodeSDBEntityData("parameters", search, entityIndex, historyArr);
newLength = returnBuff.length + entityBuff.length;
returnBuff = Buffer.concat([returnBuff, entityBuff], newLength);
}
break;
default:
//all other entity properties encoded as-is
var entityBuff = this.encodeSDBEntityData(entityProperty, entityValue, entityIndex, historyArr);
newLength = returnBuff.length + entityBuff.length;
returnBuff = Buffer.concat([returnBuff, entityBuff], newLength);
break;
}
}
//concatenate entity length to header
var lengthHeader = new Array();
lengthHeader.push((returnBuff.length & 0xFF000000) >> 24);
lengthHeader.push((returnBuff.length & 0xFF0000) >> 16);
lengthHeader.push((returnBuff.length & 0xFF00) >> 8);
lengthHeader.push(returnBuff.length & 0xFF);
var entityLength = Buffer.from(lengthHeader);
newLength = header.length + entityLength.length;
header = Buffer.concat([header, entityLength], newLength);
newLength = header.length + returnBuff.length;
//concatenate entity data to header
returnBuff = Buffer.concat([header, returnBuff], newLength);
return (returnBuff);
}
/**
* Encodes an entity's data to compressed SDB-formatted binary data.
*
* @param {String} propName The name of the data property to encode.
* @param {*} propValue The value of the data property to encode.
* @param {Number} entityIndex The index of containing entity, usually within
* the [data]{@link SDB@data} array.
* @param {Array} historyArr The history array to add the data to.
*
* @return {Buffer} The SDB-encoded binary data representation of the
* input data.
*
* @private
*/
encodeSDBEntityData(propName, propValue, propIndex, historyArr) {
var entPropObj = this.getEntPropHistory(propName, propValue, historyArr);
propName = entPropObj.propName;
propValue = entPropObj.propValue;
var encData = new Array();
switch (propName) {
case "entity":
switch (propValue) {
case "api":
encData.push(0);
break;
case "p2p":
encData.push(1);
break;
case "peer":
encData.push(2);
break;
default:
break;
}
break;
case "name":
encData.push(0);
var propLength = propValue.length;
if (propLength > 65535) {
//too long, cut off remainder
propValue = propValue.substring(0, 65535);
}
encData.push ((propLength & 0xFF00) >> 8);
encData.push (propLength & 0xFF);
for (var count=0; count < propValue.length; count++) {
encData.push(propValue.charCodeAt(count));
}
break;
case "description":
encData.push(1);
var propLength = propValue.length;
if (propLength > 65535) {
//too long, cut off remainder
propValue = propValue.substring(0, 65535);
}
encData.push ((propLength & 0xFF00) >> 8);
encData.push (propLength & 0xFF);
for (count=0; count < propValue.length; count++) {
encData.push(propValue.charCodeAt(count));
}
break;
case "transport":
encData.push(2);
switch (propValue) {
case "http":
encData.push(0);
break;
case "wss":
encData.push(1);
break;
case "wsst":
encData.push(2);
break;
case "webrtc":
encData.push(3);
break;
default:
break;
}
break;
case "protocol":
encData.push(3);
switch (propValue) {
case "http":
encData.push(0);
break;
case "https":
encData.push(1);
break;
case "ws":
encData.push(2);
break;
case "wss":
encData.push(3);
break;
default:
break;
}
break;
case "host":
encData.push(4);
if (this.isIPv4(propValue)) {
//resolved IPv4 host
encData.push(0);
var IPSplit = propValue.split(".");
for (count = 0; count < IPSplit.length; count++) {
encData.push(parseInt(IPSplit[count]));
}
} else if (this.isIPv6(propValue)) {
//resolved IPv6 host -- not currently handled
// encData.push(1);
} else {
//named host
encData.push(2);
var propLength = propValue.length;
if (propLength > 65535) {
//too long, cut off remainder
propValue = propValue.substring(0, 65535);
}
encData.push ((propLength & 0xFF00) >> 8);
encData.push (propLength & 0xFF);
for (count=0; count < propValue.length; count++) {
encData.push(propValue.charCodeAt(count));
}
}
break;
case "port":
encData.push(5);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
case "parameters":
encData.push(6);
var propLength = propValue.length;
if (propLength > 16777215) {
//too long, cut off remainder
propValue = propValue.substring(0, 16777215);
}
encData.push ((propLength & 0xFF0000) >> 16);
encData.push ((propLength & 0xFF00) >> 8);
encData.push (propLength & 0xFF);
for (count=0; count < propValue.length; count++) {
encData.push(propValue.charCodeAt(count));
}
break;
case "_nameref":
encData.push(7);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
case "_descref":
encData.push(8);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
case "_hostref":
encData.push(9);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
case "_portref":
encData.push(10);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
case "_paramref":
encData.push(11);
encData.push((propValue & 0xFF00) >> 8);
encData.push(propValue & 0xFF);
break;
default:
break;
}
this.addEntPropHistory(propName, propValue, propIndex, historyArr);
var returnBuff = Buffer.from(encData);
return (returnBuff);
}
/**
* Adds an entity's data property to a history array <i>if</i> it hasn't
* already been added.
*
* @param {String} propName The name of the property to add.
* @param {String} propValue The value of the property to add.
* @param {Number} entityIndex The index of containing entity, usually within
* the [data]{@link SDB@data} array.
* @param {Array} historyArr The history array to add the data to.
*
* @return {Boolean} True if the data was added successfully, false if
* it already existed.
*
* @private
*/
addEntPropHistory (propName, propValue, entityIndex, historyArr) {
for (var count = 0; count < historyArr.length; count++) {
var historyObj = historyArr[count];
if ((historyObj.propName == propName) && (historyObj.propValue == propValue)) {
//already exists
return (false);
}
}
//not found, add it
historyObj = new Object();
historyObj.propName = propName;
historyObj.propValue = propValue;
historyObj.entityIndex = entityIndex;
historyArr.push(historyObj);
return (true);
}
/**
* Retrieves entity reference data from a history array if available.
*
* @param {String} entityProperty The matching entity data property to retrieve.
* @param {*} entityValue The matching entity value to retrieve.
* @param {Array} historyArr The history array from which to retrieve the matching
* reference data.
*
* @return {Object} Contains the <code>propName</code>, <code>propValue</code>
* <code>entityIndex</code>, and <code>oldPropName</code> of the matching
* reference data (i.e. previously stored in the history array), or
* <code>oldPropName</code> will be null and <code>entityIndex</code> will be -1
* if no matching reference exists (i.e. this is unique data).
*
* @private
*/
getEntPropHistory(entityProperty, entityValue, historyArr) {
var returnObj = new Object();
for (var count = 0; count < historyArr.length; count++) {
var historyObj = historyArr[count];
if (historyObj.propName == entityProperty) {
if ((historyObj.propValue == entityValue) || (entityValue == null)) {
switch (historyObj.propName) {
case "name":
returnObj.propName = "_nameref";
returnObj.oldPropName = historyObj.propName;
returnObj.propValue = count;
returnObj.entityIndex = historyObj.entityIndex;
return (returnObj);
break;
case "description":
returnObj.propName = "_descref";
returnObj.oldPropName = historyObj.propName;
returnObj.propValue = count;
returnObj.entityIndex = historyObj.entityIndex;
return (returnObj);
break;
case "host":
returnObj.propName = "_hostref";
returnObj.oldPropName = historyObj.propName;
returnObj.propValue = count;
returnObj.entityIndex = historyObj.entityIndex;
return (returnObj);
break;
case "port":
returnObj.propName = "_portref";
returnObj.oldPropName = historyObj.propName;
returnObj.propValue = count;
returnObj.entityIndex = historyObj.entityIndex;
return (returnObj);
break;
case "parameters":
returnObj.propName = "_paramref";
returnObj.oldPropName = historyObj.propName;
returnObj.propValue = count;
returnObj.entityIndex = historyObj.entityIndex;
return (returnObj);
break;
}
}
}
}
returnObj.propName = entityProperty;
returnObj.oldPropName = null;
returnObj.propValue = entityValue;
returnObj.entityIndex = -1;
return (returnObj);
}
/**
* Checks whether a given string is a valid IPv4 address,
*
* @param {String} address The address string to evaluate.
*
* @return {Boolean} True if <code>address</code> is a valid IPv4 adress, false
* otherwise.
*
* @private
*/
isIPv4 (address) {
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(address)) {
return (true);
}
return (false);
}
/**
* Checks whether a given string is a valid IPv6 address,
*
* @param {String} address The address string to evaluate.
*
* @return {Boolean} True if <code>address</code> is a valid IPv6 adress, false
* otherwise.
*
* @private
*/
isIPv6 (address) {
if (/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(address)) {
return (true);
}
return (false);
}
}
window.SDB = SDB;
}).call(this,require("buffer").Buffer)
},{"buffer":2}]},{},[5]);