diff --git a/assets/js/dash.mediaplayer.debug.js b/assets/js/dash.mediaplayer.debug.js new file mode 100644 index 00000000..14a2f7ef --- /dev/null +++ b/assets/js/dash.mediaplayer.debug.js @@ -0,0 +1,48919 @@ +(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> 6); + u.push(0x80 | 63 & c); + } else if (c < 0x10000) { + u.push(0xE0 | c >> 12); + u.push(0x80 | 63 & c >> 6); + u.push(0x80 | 63 & c); + } else { + u.push(0xF0 | c >> 18); + u.push(0x80 | 63 & c >> 12); + u.push(0x80 | 63 & c >> 6); + u.push(0x80 | 63 & c); + } + } + return u; +}; +UTF8.decode = function (u) { + var a = []; + var i = 0; + while (i < u.length) { + var v = u[i++]; + if (v < 0x80) { + // no need to mask byte + } else if (v < 0xE0) { + v = (31 & v) << 6; + v |= 63 & u[i++]; + } else if (v < 0xF0) { + v = (15 & v) << 12; + v |= (63 & u[i++]) << 6; + v |= 63 & u[i++]; + } else { + v = (7 & v) << 18; + v |= (63 & u[i++]) << 12; + v |= (63 & u[i++]) << 6; + v |= 63 & u[i++]; + } + a.push(String.fromCharCode(v)); + } + return a.join(''); +}; + +var BASE64 = {}; +(function (T) { + var encodeArray = function encodeArray(u) { + var i = 0; + var a = []; + var n = 0 | u.length / 3; + while (0 < n--) { + var v = (u[i] << 16) + (u[i + 1] << 8) + u[i + 2]; + i += 3; + a.push(T.charAt(63 & v >> 18)); + a.push(T.charAt(63 & v >> 12)); + a.push(T.charAt(63 & v >> 6)); + a.push(T.charAt(63 & v)); + } + if (2 == u.length - i) { + var v = (u[i] << 16) + (u[i + 1] << 8); + a.push(T.charAt(63 & v >> 18)); + a.push(T.charAt(63 & v >> 12)); + a.push(T.charAt(63 & v >> 6)); + a.push('='); + } else if (1 == u.length - i) { + var v = u[i] << 16; + a.push(T.charAt(63 & v >> 18)); + a.push(T.charAt(63 & v >> 12)); + a.push('=='); + } + return a.join(''); + }; + var R = (function () { + var a = []; + for (var i = 0; i < T.length; ++i) { + a[T.charCodeAt(i)] = i; + } + a['='.charCodeAt(0)] = 0; + return a; + })(); + var decodeArray = function decodeArray(s) { + var i = 0; + var u = []; + var n = 0 | s.length / 4; + while (0 < n--) { + var v = (R[s.charCodeAt(i)] << 18) + (R[s.charCodeAt(i + 1)] << 12) + (R[s.charCodeAt(i + 2)] << 6) + R[s.charCodeAt(i + 3)]; + u.push(255 & v >> 16); + u.push(255 & v >> 8); + u.push(255 & v); + i += 4; + } + if (u) { + if ('=' == s.charAt(i - 2)) { + u.pop(); + u.pop(); + } else if ('=' == s.charAt(i - 1)) { + u.pop(); + } + } + return u; + }; + var ASCII = {}; + ASCII.encode = function (s) { + var u = []; + for (var i = 0; i < s.length; ++i) { + u.push(s.charCodeAt(i)); + } + return u; + }; + ASCII.decode = function (u) { + for (var i = 0; i < s.length; ++i) { + a[i] = String.fromCharCode(a[i]); + } + return a.join(''); + }; + BASE64.decodeArray = function (s) { + var u = decodeArray(s); + return new Uint8Array(u); + }; + BASE64.encodeASCII = function (s) { + var u = ASCII.encode(s); + return encodeArray(u); + }; + BASE64.decodeASCII = function (s) { + var a = decodeArray(s); + return ASCII.decode(a); + }; + BASE64.encode = function (s) { + var u = UTF8.encode(s); + return encodeArray(u); + }; + BASE64.decode = function (s) { + var u = decodeArray(s); + return UTF8.decode(u); + }; +})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); + +/*The following polyfills are not used in dash.js but have caused multiplayer integration issues. + Therefore commenting them out. +if (undefined === btoa) { + var btoa = BASE64.encode; +} +if (undefined === atob) { + var atob = BASE64.decode; +} +*/ + +if (typeof exports !== 'undefined') { + exports.decode = BASE64.decode; + exports.decodeArray = BASE64.decodeArray; + exports.encode = BASE64.encode; + exports.encodeASCII = BASE64.encodeASCII; +} + +},{}],2:[function(_dereq_,module,exports){ +/** + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and contributor + * rights, including patent rights, and no such rights are granted under this license. + * + * Copyright (c) 2015-2016, DASH Industry Forum. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * 2. Neither the name of Dash Industry Forum nor the names of its + * contributors may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +'use strict'; + +(function (exports) { + + "use strict"; + + /** + * Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes + */ + + var specialCea608CharsCodes = { + 0x2a: 0xe1, // lowercase a, acute accent + 0x5c: 0xe9, // lowercase e, acute accent + 0x5e: 0xed, // lowercase i, acute accent + 0x5f: 0xf3, // lowercase o, acute accent + 0x60: 0xfa, // lowercase u, acute accent + 0x7b: 0xe7, // lowercase c with cedilla + 0x7c: 0xf7, // division symbol + 0x7d: 0xd1, // uppercase N tilde + 0x7e: 0xf1, // lowercase n tilde + 0x7f: 0x2588, // Full block + // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS + // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F + // THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES + 0x80: 0xae, // Registered symbol (R) + 0x81: 0xb0, // degree sign + 0x82: 0xbd, // 1/2 symbol + 0x83: 0xbf, // Inverted (open) question mark + 0x84: 0x2122, // Trademark symbol (TM) + 0x85: 0xa2, // Cents symbol + 0x86: 0xa3, // Pounds sterling + 0x87: 0x266a, // Music 8'th note + 0x88: 0xe0, // lowercase a, grave accent + 0x89: 0x20, // transparent space (regular) + 0x8a: 0xe8, // lowercase e, grave accent + 0x8b: 0xe2, // lowercase a, circumflex accent + 0x8c: 0xea, // lowercase e, circumflex accent + 0x8d: 0xee, // lowercase i, circumflex accent + 0x8e: 0xf4, // lowercase o, circumflex accent + 0x8f: 0xfb, // lowercase u, circumflex accent + // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS + // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F + 0x90: 0xc1, // capital letter A with acute + 0x91: 0xc9, // capital letter E with acute + 0x92: 0xd3, // capital letter O with acute + 0x93: 0xda, // capital letter U with acute + 0x94: 0xdc, // capital letter U with diaresis + 0x95: 0xfc, // lowercase letter U with diaeresis + 0x96: 0x2018, // opening single quote + 0x97: 0xa1, // inverted exclamation mark + 0x98: 0x2a, // asterisk + 0x99: 0x2019, // closing single quote + 0x9a: 0x2501, // box drawings heavy horizontal + 0x9b: 0xa9, // copyright sign + 0x9c: 0x2120, // Service mark + 0x9d: 0x2022, // (round) bullet + 0x9e: 0x201c, // Left double quotation mark + 0x9f: 0x201d, // Right double quotation mark + 0xa0: 0xc0, // uppercase A, grave accent + 0xa1: 0xc2, // uppercase A, circumflex + 0xa2: 0xc7, // uppercase C with cedilla + 0xa3: 0xc8, // uppercase E, grave accent + 0xa4: 0xca, // uppercase E, circumflex + 0xa5: 0xcb, // capital letter E with diaresis + 0xa6: 0xeb, // lowercase letter e with diaresis + 0xa7: 0xce, // uppercase I, circumflex + 0xa8: 0xcf, // uppercase I, with diaresis + 0xa9: 0xef, // lowercase i, with diaresis + 0xaa: 0xd4, // uppercase O, circumflex + 0xab: 0xd9, // uppercase U, grave accent + 0xac: 0xf9, // lowercase u, grave accent + 0xad: 0xdb, // uppercase U, circumflex + 0xae: 0xab, // left-pointing double angle quotation mark + 0xaf: 0xbb, // right-pointing double angle quotation mark + // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS + // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F + 0xb0: 0xc3, // Uppercase A, tilde + 0xb1: 0xe3, // Lowercase a, tilde + 0xb2: 0xcd, // Uppercase I, acute accent + 0xb3: 0xcc, // Uppercase I, grave accent + 0xb4: 0xec, // Lowercase i, grave accent + 0xb5: 0xd2, // Uppercase O, grave accent + 0xb6: 0xf2, // Lowercase o, grave accent + 0xb7: 0xd5, // Uppercase O, tilde + 0xb8: 0xf5, // Lowercase o, tilde + 0xb9: 0x7b, // Open curly brace + 0xba: 0x7d, // Closing curly brace + 0xbb: 0x5c, // Backslash + 0xbc: 0x5e, // Caret + 0xbd: 0x5f, // Underscore + 0xbe: 0x7c, // Pipe (vertical line) + 0xbf: 0x223c, // Tilde operator + 0xc0: 0xc4, // Uppercase A, umlaut + 0xc1: 0xe4, // Lowercase A, umlaut + 0xc2: 0xd6, // Uppercase O, umlaut + 0xc3: 0xf6, // Lowercase o, umlaut + 0xc4: 0xdf, // Esszett (sharp S) + 0xc5: 0xa5, // Yen symbol + 0xc6: 0xa4, // Generic currency sign + 0xc7: 0x2503, // Box drawings heavy vertical + 0xc8: 0xc5, // Uppercase A, ring + 0xc9: 0xe5, // Lowercase A, ring + 0xca: 0xd8, // Uppercase O, stroke + 0xcb: 0xf8, // Lowercase o, strok + 0xcc: 0x250f, // Box drawings heavy down and right + 0xcd: 0x2513, // Box drawings heavy down and left + 0xce: 0x2517, // Box drawings heavy up and right + 0xcf: 0x251b // Box drawings heavy up and left + }; + + /** + * Get Unicode Character from CEA-608 byte code + */ + var getCharForByte = function getCharForByte(byte) { + var charCode = byte; + if (specialCea608CharsCodes.hasOwnProperty(byte)) { + charCode = specialCea608CharsCodes[byte]; + } + return String.fromCharCode(charCode); + }; + + var NR_ROWS = 15, + NR_COLS = 32; + // Tables to look up row from PAC data + var rowsLowCh1 = { 0x11: 1, 0x12: 3, 0x15: 5, 0x16: 7, 0x17: 9, 0x10: 11, 0x13: 12, 0x14: 14 }; + var rowsHighCh1 = { 0x11: 2, 0x12: 4, 0x15: 6, 0x16: 8, 0x17: 10, 0x13: 13, 0x14: 15 }; + var rowsLowCh2 = { 0x19: 1, 0x1A: 3, 0x1D: 5, 0x1E: 7, 0x1F: 9, 0x18: 11, 0x1B: 12, 0x1C: 14 }; + var rowsHighCh2 = { 0x19: 2, 0x1A: 4, 0x1D: 6, 0x1E: 8, 0x1F: 10, 0x1B: 13, 0x1C: 15 }; + + var backgroundColors = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'black', 'transparent']; + + /** + * Simple logger class to be able to write with time-stamps and filter on level. + */ + var logger = { + verboseFilter: { 'DATA': 3, 'DEBUG': 3, 'INFO': 2, 'WARNING': 2, 'TEXT': 1, 'ERROR': 0 }, + time: null, + verboseLevel: 0, // Only write errors + setTime: function setTime(newTime) { + this.time = newTime; + }, + log: function log(severity, msg) { + var minLevel = this.verboseFilter[severity]; + if (this.verboseLevel >= minLevel) { + console.log(this.time + " [" + severity + "] " + msg); + } + } + }; + + var numArrayToHexArray = function numArrayToHexArray(numArray) { + var hexArray = []; + for (var j = 0; j < numArray.length; j++) { + hexArray.push(numArray[j].toString(16)); + } + return hexArray; + }; + + /** + * State of CEA-608 pen or character + * @constructor + */ + var PenState = function PenState(foreground, underline, italics, background, flash) { + this.foreground = foreground || "white"; + this.underline = underline || false; + this.italics = italics || false; + this.background = background || "black"; + this.flash = flash || false; + }; + + PenState.prototype = { + + reset: function reset() { + this.foreground = "white"; + this.underline = false; + this.italics = false; + this.background = "black"; + this.flash = false; + }, + + setStyles: function setStyles(styles) { + var attribs = ["foreground", "underline", "italics", "background", "flash"]; + for (var i = 0; i < attribs.length; i++) { + var style = attribs[i]; + if (styles.hasOwnProperty(style)) { + this[style] = styles[style]; + } + } + }, + + isDefault: function isDefault() { + return this.foreground === "white" && !this.underline && !this.italics && this.background === "black" && !this.flash; + }, + + equals: function equals(other) { + return this.foreground === other.foreground && this.underline === other.underline && this.italics === other.italics && this.background === other.background && this.flash === other.flash; + }, + + copy: function copy(newPenState) { + this.foreground = newPenState.foreground; + this.underline = newPenState.underline; + this.italics = newPenState.italics; + this.background = newPenState.background; + this.flash = newPenState.flash; + }, + + toString: function toString() { + return "color=" + this.foreground + ", underline=" + this.underline + ", italics=" + this.italics + ", background=" + this.background + ", flash=" + this.flash; + } + }; + + /** + * Unicode character with styling and background. + * @constructor + */ + var StyledUnicodeChar = function StyledUnicodeChar(uchar, foreground, underline, italics, background, flash) { + this.uchar = uchar || ' '; // unicode character + this.penState = new PenState(foreground, underline, italics, background, flash); + }; + + StyledUnicodeChar.prototype = { + + reset: function reset() { + this.uchar = ' '; + this.penState.reset(); + }, + + setChar: function setChar(uchar, newPenState) { + this.uchar = uchar; + this.penState.copy(newPenState); + }, + + setPenState: function setPenState(newPenState) { + this.penState.copy(newPenState); + }, + + equals: function equals(other) { + return this.uchar === other.uchar && this.penState.equals(other.penState); + }, + + copy: function copy(newChar) { + this.uchar = newChar.uchar; + this.penState.copy(newChar.penState); + }, + + isEmpty: function isEmpty() { + return this.uchar === ' ' && this.penState.isDefault(); + } + }; + + /** + * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar. + * @constructor + */ + var Row = function Row() { + this.chars = []; + for (var i = 0; i < NR_COLS; i++) { + this.chars.push(new StyledUnicodeChar()); + } + this.pos = 0; + this.currPenState = new PenState(); + }; + + Row.prototype = { + + equals: function equals(other) { + var equal = true; + for (var i = 0; i < NR_COLS; i++) { + if (!this.chars[i].equals(other.chars[i])) { + equal = false; + break; + } + } + return equal; + }, + + copy: function copy(other) { + for (var i = 0; i < NR_COLS; i++) { + this.chars[i].copy(other.chars[i]); + } + }, + + isEmpty: function isEmpty() { + var empty = true; + for (var i = 0; i < NR_COLS; i++) { + if (!this.chars[i].isEmpty()) { + empty = false; + break; + } + } + return empty; + }, + + /** + * Set the cursor to a valid column. + */ + setCursor: function setCursor(absPos) { + if (this.pos !== absPos) { + this.pos = absPos; + } + if (this.pos < 0) { + logger.log("ERROR", "Negative cursor position " + this.pos); + this.pos = 0; + } else if (this.pos > NR_COLS) { + logger.log("ERROR", "Too large cursor position " + this.pos); + this.pos = NR_COLS; + } + }, + + /** + * Move the cursor relative to current position. + */ + moveCursor: function moveCursor(relPos) { + var newPos = this.pos + relPos; + if (relPos > 1) { + for (var i = this.pos + 1; i < newPos + 1; i++) { + this.chars[i].setPenState(this.currPenState); + } + } + this.setCursor(newPos); + }, + + /** + * Backspace, move one step back and clear character. + */ + backSpace: function backSpace() { + this.moveCursor(-1); + this.chars[this.pos].setChar(' ', this.currPenState); + }, + + insertChar: function insertChar(byte) { + if (byte >= 0x90) { + //Extended char + this.backSpace(); + } + var char = getCharForByte(byte); + if (this.pos >= NR_COLS) { + logger.log("ERROR", "Cannot insert " + byte.toString(16) + " (" + char + ") at position " + this.pos + ". Skipping it!"); + return; + } + this.chars[this.pos].setChar(char, this.currPenState); + this.moveCursor(1); + }, + + clearFromPos: function clearFromPos(startPos) { + var i; + for (i = startPos; i < NR_COLS; i++) { + this.chars[i].reset(); + } + }, + + clear: function clear() { + this.clearFromPos(0); + this.pos = 0; + this.currPenState.reset(); + }, + + clearToEndOfRow: function clearToEndOfRow() { + this.clearFromPos(this.pos); + }, + + getTextString: function getTextString() { + var chars = []; + var empty = true; + for (var i = 0; i < NR_COLS; i++) { + var char = this.chars[i].uchar; + if (char !== " ") { + empty = false; + } + chars.push(char); + } + if (empty) { + return ""; + } else { + return chars.join(""); + } + }, + + setPenStyles: function setPenStyles(styles) { + this.currPenState.setStyles(styles); + var currChar = this.chars[this.pos]; + currChar.setPenState(this.currPenState); + } + }; + + /** + * Keep a CEA-608 screen of 32x15 styled characters + * @constructor + */ + var CaptionScreen = function CaptionScreen() { + + this.rows = []; + for (var i = 0; i < NR_ROWS; i++) { + this.rows.push(new Row()); // Note that we use zero-based numbering (0-14) + } + this.currRow = NR_ROWS - 1; + this.nrRollUpRows = null; + this.reset(); + }; + + CaptionScreen.prototype = { + + reset: function reset() { + for (var i = 0; i < NR_ROWS; i++) { + this.rows[i].clear(); + } + this.currRow = NR_ROWS - 1; + }, + + equals: function equals(other) { + var equal = true; + for (var i = 0; i < NR_ROWS; i++) { + if (!this.rows[i].equals(other.rows[i])) { + equal = false; + break; + } + } + return equal; + }, + + copy: function copy(other) { + for (var i = 0; i < NR_ROWS; i++) { + this.rows[i].copy(other.rows[i]); + } + }, + + isEmpty: function isEmpty() { + var empty = true; + for (var i = 0; i < NR_ROWS; i++) { + if (!this.rows[i].isEmpty()) { + empty = false; + break; + } + } + return empty; + }, + + backSpace: function backSpace() { + var row = this.rows[this.currRow]; + row.backSpace(); + }, + + clearToEndOfRow: function clearToEndOfRow() { + var row = this.rows[this.currRow]; + row.clearToEndOfRow(); + }, + + /** + * Insert a character (without styling) in the current row. + */ + insertChar: function insertChar(char) { + var row = this.rows[this.currRow]; + row.insertChar(char); + }, + + setPen: function setPen(styles) { + var row = this.rows[this.currRow]; + row.setPenStyles(styles); + }, + + moveCursor: function moveCursor(relPos) { + var row = this.rows[this.currRow]; + row.moveCursor(relPos); + }, + + setCursor: function setCursor(absPos) { + logger.log("INFO", "setCursor: " + absPos); + var row = this.rows[this.currRow]; + row.setCursor(absPos); + }, + + setPAC: function setPAC(pacData) { + logger.log("INFO", "pacData = " + JSON.stringify(pacData)); + var newRow = pacData.row - 1; + if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) { + newRow = this.nrRollUpRows - 1; + } + this.currRow = newRow; + var row = this.rows[this.currRow]; + if (pacData.indent !== null) { + var indent = pacData.indent; + var prevPos = Math.max(indent - 1, 0); + row.setCursor(pacData.indent); + pacData.color = row.chars[prevPos].penState.foreground; + } + var styles = { foreground: pacData.color, underline: pacData.underline, italics: pacData.italics, background: 'black', flash: false }; + this.setPen(styles); + }, + + /** + * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility). + */ + setBkgData: function setBkgData(bkgData) { + + logger.log("INFO", "bkgData = " + JSON.stringify(bkgData)); + this.backSpace(); + this.setPen(bkgData); + this.insertChar(0x20); //Space + }, + + setRollUpRows: function setRollUpRows(nrRows) { + this.nrRollUpRows = nrRows; + }, + + rollUp: function rollUp() { + if (this.nrRollUpRows === null) { + logger.log("DEBUG", "roll_up but nrRollUpRows not set yet"); + return; //Not properly setup + } + logger.log("TEXT", this.getDisplayText()); + var topRowIndex = this.currRow + 1 - this.nrRollUpRows; + var topRow = this.rows.splice(topRowIndex, 1)[0]; + topRow.clear(); + this.rows.splice(this.currRow, 0, topRow); + logger.log("INFO", "Rolling up"); + //logger.log("TEXT", this.get_display_text()) + }, + + /** + * Get all non-empty rows with as unicode text. + */ + getDisplayText: function getDisplayText(asOneRow) { + asOneRow = asOneRow || false; + var displayText = []; + var text = ""; + var rowNr = -1; + for (var i = 0; i < NR_ROWS; i++) { + var rowText = this.rows[i].getTextString(); + if (rowText) { + rowNr = i + 1; + if (asOneRow) { + displayText.push("Row " + rowNr + ': "' + rowText + '"'); + } else { + displayText.push(rowText.trim()); + } + } + } + if (displayText.length > 0) { + if (asOneRow) { + text = "[" + displayText.join(" | ") + "]"; + } else { + text = displayText.join("\n"); + } + } + return text; + }, + + getTextAndFormat: function getTextAndFormat() { + return this.rows; + } + }; + + /** + * Handle a CEA-608 channel and send decoded data to outputFilter + * @constructor + * @param {Number} channelNumber (1 or 2) + * @param {CueHandler} outputFilter Output from channel1 newCue(startTime, endTime, captionScreen) + */ + var Cea608Channel = function Cea608Channel(channelNumber, outputFilter) { + + this.chNr = channelNumber; + this.outputFilter = outputFilter; + this.mode = null; + this.verbose = 0; + this.displayedMemory = new CaptionScreen(); + this.nonDisplayedMemory = new CaptionScreen(); + this.lastOutputScreen = new CaptionScreen(); + this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1]; + this.writeScreen = this.displayedMemory; + this.mode = null; + this.cueStartTime = null; // Keeps track of where a cue started. + }; + + Cea608Channel.prototype = { + + modes: ["MODE_ROLL-UP", "MODE_POP-ON", "MODE_PAINT-ON", "MODE_TEXT"], + + reset: function reset() { + this.mode = null; + this.displayedMemory.reset(); + this.nonDisplayedMemory.reset(); + this.lastOutputScreen.reset(); + this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1]; + this.writeScreen = this.displayedMemory; + this.mode = null; + this.cueStartTime = null; + this.lastCueEndTime = null; + }, + + getHandler: function getHandler() { + return this.outputFilter; + }, + + setHandler: function setHandler(newHandler) { + this.outputFilter = newHandler; + }, + + setPAC: function setPAC(pacData) { + this.writeScreen.setPAC(pacData); + }, + + setBkgData: function setBkgData(bkgData) { + this.writeScreen.setBkgData(bkgData); + }, + + setMode: function setMode(newMode) { + if (newMode === this.mode) { + return; + } + this.mode = newMode; + logger.log("INFO", "MODE=" + newMode); + if (this.mode == "MODE_POP-ON") { + this.writeScreen = this.nonDisplayedMemory; + } else { + this.writeScreen = this.displayedMemory; + this.writeScreen.reset(); + } + if (this.mode !== "MODE_ROLL-UP") { + this.displayedMemory.nrRollUpRows = null; + this.nonDisplayedMemory.nrRollUpRows = null; + } + this.mode = newMode; + }, + + insertChars: function insertChars(chars) { + for (var i = 0; i < chars.length; i++) { + this.writeScreen.insertChar(chars[i]); + } + var screen = this.writeScreen === this.displayedMemory ? "DISP" : "NON_DISP"; + logger.log("INFO", screen + ": " + this.writeScreen.getDisplayText(true)); + if (this.mode === "MODE_PAINT-ON" || this.mode === "MODE_ROLL-UP") { + logger.log("TEXT", "DISPLAYED: " + this.displayedMemory.getDisplayText(true)); + this.outputDataUpdate(); + } + }, + + cc_RCL: function cc_RCL() { + // Resume Caption Loading (switch mode to Pop On) + logger.log("INFO", "RCL - Resume Caption Loading"); + this.setMode("MODE_POP-ON"); + }, + cc_BS: function cc_BS() { + // BackSpace + logger.log("INFO", "BS - BackSpace"); + if (this.mode === "MODE_TEXT") { + return; + } + this.writeScreen.backSpace(); + if (this.writeScreen === this.displayedMemory) { + this.outputDataUpdate(); + } + }, + cc_AOF: function cc_AOF() { + // Reserved (formerly Alarm Off) + return; + }, + cc_AON: function cc_AON() { + // Reserved (formerly Alarm On) + return; + }, + cc_DER: function cc_DER() { + // Delete to End of Row + logger.log("INFO", "DER- Delete to End of Row"); + this.writeScreen.clearToEndOfRow(); + this.outputDataUpdate(); + }, + cc_RU: function cc_RU(nrRows) { + //Roll-Up Captions-2,3,or 4 Rows + logger.log("INFO", "RU(" + nrRows + ") - Roll Up"); + this.writeScreen = this.displayedMemory; + this.setMode("MODE_ROLL-UP"); + this.writeScreen.setRollUpRows(nrRows); + }, + cc_FON: function cc_FON() { + //Flash On + logger.log("INFO", "FON - Flash On"); + this.writeScreen.setPen({ flash: true }); + }, + cc_RDC: function cc_RDC() { + // Resume Direct Captioning (switch mode to PaintOn) + logger.log("INFO", "RDC - Resume Direct Captioning"); + this.setMode("MODE_PAINT-ON"); + }, + cc_TR: function cc_TR() { + // Text Restart in text mode (not supported, however) + logger.log("INFO", "TR"); + this.setMode("MODE_TEXT"); + }, + cc_RTD: function cc_RTD() { + // Resume Text Display in Text mode (not supported, however) + logger.log("INFO", "RTD"); + this.setMode("MODE_TEXT"); + }, + cc_EDM: function cc_EDM() { + // Erase Displayed Memory + logger.log("INFO", "EDM - Erase Displayed Memory"); + this.displayedMemory.reset(); + this.outputDataUpdate(); + }, + cc_CR: function cc_CR() { + // Carriage Return + logger.log("CR - Carriage Return"); + this.writeScreen.rollUp(); + this.outputDataUpdate(); + }, + cc_ENM: function cc_ENM() { + //Erase Non-Displayed Memory + logger.log("INFO", "ENM - Erase Non-displayed Memory"); + this.nonDisplayedMemory.reset(); + }, + cc_EOC: function cc_EOC() { + //End of Caption (Flip Memories) + logger.log("INFO", "EOC - End Of Caption"); + if (this.mode === "MODE_POP-ON") { + var tmp = this.displayedMemory; + this.displayedMemory = this.nonDisplayedMemory; + this.nonDisplayedMemory = tmp; + this.writeScreen = this.nonDisplayedMemory; + logger.log("TEXT", "DISP: " + this.displayedMemory.getDisplayText()); + } + this.outputDataUpdate(); + }, + cc_TO: function cc_TO(nrCols) { + // Tab Offset 1,2, or 3 columns + logger.log("INFO", "TO(" + nrCols + ") - Tab Offset"); + this.writeScreen.moveCursor(nrCols); + }, + cc_MIDROW: function cc_MIDROW(secondByte) { + // Parse MIDROW command + var styles = { flash: false }; + styles.underline = secondByte % 2 === 1; + styles.italics = secondByte >= 0x2e; + if (!styles.italics) { + var colorIndex = Math.floor(secondByte / 2) - 0x10; + var colors = ["white", "green", "blue", "cyan", "red", "yellow", "magenta"]; + styles.foreground = colors[colorIndex]; + } else { + styles.foreground = "white"; + } + logger.log("INFO", "MIDROW: " + JSON.stringify(styles)); + this.writeScreen.setPen(styles); + }, + + outputDataUpdate: function outputDataUpdate() { + var t = logger.time; + if (t === null) { + return; + } + if (this.outputFilter) { + if (this.outputFilter.updateData) { + this.outputFilter.updateData(t, this.displayedMemory); + } + if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) { + // Start of a new cue + this.cueStartTime = t; + } else { + if (!this.displayedMemory.equals(this.lastOutputScreen)) { + if (this.outputFilter.newCue) { + this.outputFilter.newCue(this.cueStartTime, t, this.lastOutputScreen); + } + this.cueStartTime = this.displayedMemory.isEmpty() ? null : t; + } + } + this.lastOutputScreen.copy(this.displayedMemory); + } + }, + + cueSplitAtTime: function cueSplitAtTime(t) { + if (this.outputFilter) { + if (!this.displayedMemory.isEmpty()) { + if (this.outputFilter.newCue) { + this.outputFilter.newCue(this.cueStartTime, t, this.displayedMemory); + } + this.cueStartTime = t; + } + } + } + }; + + /** + * Parse CEA-608 data and send decoded data to out1 and out2. + * @constructor + * @param {Number} field CEA-608 field (1 or 2) + * @param {CueHandler} out1 Output from channel1 newCue(startTime, endTime, captionScreen) + * @param {CueHandler} out2 Output from channel2 newCue(startTime, endTime, captionScreen) + */ + var Cea608Parser = function Cea608Parser(field, out1, out2) { + this.field = field || 1; + this.outputs = [out1, out2]; + this.channels = [new Cea608Channel(1, out1), new Cea608Channel(2, out2)]; + this.currChNr = -1; // Will be 1 or 2 + this.lastCmdA = null; // First byte of last command + this.lastCmdB = null; // Second byte of last command + this.bufferedData = []; + this.startTime = null; + this.lastTime = null; + this.dataCounters = { 'padding': 0, 'char': 0, 'cmd': 0, 'other': 0 }; + }; + + Cea608Parser.prototype = { + + getHandler: function getHandler(index) { + return this.channels[index].getHandler(); + }, + + setHandler: function setHandler(index, newHandler) { + this.channels[index].setHandler(newHandler); + }, + + /** + * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs. + */ + addData: function addData(t, byteList) { + var cmdFound, + a, + b, + charsFound = false; + + this.lastTime = t; + logger.setTime(t); + + for (var i = 0; i < byteList.length; i += 2) { + a = byteList[i] & 0x7f; + b = byteList[i + 1] & 0x7f; + + if (a >= 0x10 && a <= 0x1f && a === this.lastCmdA && b === this.lastCmdB) { + this.lastCmdA = null; + this.lastCmdB = null; + logger.log("DEBUG", "Repeated command (" + numArrayToHexArray([a, b]) + ") is dropped"); + continue; // Repeated commands are dropped (once) + } + + if (a === 0 && b === 0) { + this.dataCounters.padding += 2; + continue; + } else { + logger.log("DATA", "[" + numArrayToHexArray([byteList[i], byteList[i + 1]]) + "] -> (" + numArrayToHexArray([a, b]) + ")"); + } + cmdFound = this.parseCmd(a, b); + if (!cmdFound) { + cmdFound = this.parseMidrow(a, b); + } + if (!cmdFound) { + cmdFound = this.parsePAC(a, b); + } + if (!cmdFound) { + cmdFound = this.parseBackgroundAttributes(a, b); + } + if (!cmdFound) { + charsFound = this.parseChars(a, b); + if (charsFound) { + if (this.currChNr && this.currChNr >= 0) { + var channel = this.channels[this.currChNr - 1]; + channel.insertChars(charsFound); + } else { + logger.log("WARNING", "No channel found yet. TEXT-MODE?"); + } + } + } + if (cmdFound) { + this.dataCounters.cmd += 2; + } else if (charsFound) { + this.dataCounters.char += 2; + } else { + this.dataCounters.other += 2; + logger.log("WARNING", "Couldn't parse cleaned data " + numArrayToHexArray([a, b]) + " orig: " + numArrayToHexArray([byteList[i], byteList[i + 1]])); + } + } + }, + + /** + * Parse Command. + * @returns {Boolean} Tells if a command was found + */ + parseCmd: function parseCmd(a, b) { + var chNr = null; + + var cond1 = (a === 0x14 || a === 0x15 || a === 0x1C || a === 0x1D) && 0x20 <= b && b <= 0x2F; + var cond2 = (a === 0x17 || a === 0x1F) && 0x21 <= b && b <= 0x23; + if (!(cond1 || cond2)) { + return false; + } + + if (a === 0x14 || a === 0x15 || a === 0x17) { + chNr = 1; + } else { + chNr = 2; // (a === 0x1C || a === 0x1D || a=== 0x1f) + } + + var channel = this.channels[chNr - 1]; + + if (a === 0x14 || a === 0x15 || a === 0x1C || a === 0x1D) { + if (b === 0x20) { + channel.cc_RCL(); + } else if (b === 0x21) { + channel.cc_BS(); + } else if (b === 0x22) { + channel.cc_AOF(); + } else if (b === 0x23) { + channel.cc_AON(); + } else if (b === 0x24) { + channel.cc_DER(); + } else if (b === 0x25) { + channel.cc_RU(2); + } else if (b === 0x26) { + channel.cc_RU(3); + } else if (b === 0x27) { + channel.cc_RU(4); + } else if (b === 0x28) { + channel.cc_FON(); + } else if (b === 0x29) { + channel.cc_RDC(); + } else if (b === 0x2A) { + channel.cc_TR(); + } else if (b === 0x2B) { + channel.cc_RTD(); + } else if (b === 0x2C) { + channel.cc_EDM(); + } else if (b === 0x2D) { + channel.cc_CR(); + } else if (b === 0x2E) { + channel.cc_ENM(); + } else if (b === 0x2F) { + channel.cc_EOC(); + } + } else { + //a == 0x17 || a == 0x1F + channel.cc_TO(b - 0x20); + } + this.lastCmdA = a; + this.lastCmdB = b; + this.currChNr = chNr; + return true; + }, + + /** + * Parse midrow styling command + * @returns {Boolean} + */ + parseMidrow: function parseMidrow(a, b) { + var chNr = null; + + if ((a === 0x11 || a === 0x19) && 0x20 <= b && b <= 0x2f) { + if (a === 0x11) { + chNr = 1; + } else { + chNr = 2; + } + if (chNr !== this.currChNr) { + logger.log("ERROR", "Mismatch channel in midrow parsing"); + return false; + } + var channel = this.channels[chNr - 1]; + // cea608 spec says midrow codes should inject a space + channel.insertChars([0x20]); + channel.cc_MIDROW(b); + logger.log("DEBUG", "MIDROW (" + numArrayToHexArray([a, b]) + ")"); + this.lastCmdA = a; + this.lastCmdB = b; + return true; + } + return false; + }, + /** + * Parse Preable Access Codes (Table 53). + * @returns {Boolean} Tells if PAC found + */ + parsePAC: function parsePAC(a, b) { + + var chNr = null; + var row = null; + + var case1 = (0x11 <= a && a <= 0x17 || 0x19 <= a && a <= 0x1F) && 0x40 <= b && b <= 0x7F; + var case2 = (a === 0x10 || a === 0x18) && 0x40 <= b && b <= 0x5F; + if (!(case1 || case2)) { + return false; + } + + chNr = a <= 0x17 ? 1 : 2; + + if (0x40 <= b && b <= 0x5F) { + row = chNr === 1 ? rowsLowCh1[a] : rowsLowCh2[a]; + } else { + // 0x60 <= b <= 0x7F + row = chNr === 1 ? rowsHighCh1[a] : rowsHighCh2[a]; + } + var pacData = this.interpretPAC(row, b); + var channel = this.channels[chNr - 1]; + channel.setPAC(pacData); + this.lastCmdA = a; + this.lastCmdB = b; + this.currChNr = chNr; + return true; + }, + + /** + * Interpret the second byte of the pac, and return the information. + * @returns {Object} pacData with style parameters. + */ + interpretPAC: function interpretPAC(row, byte) { + var pacIndex = byte; + var pacData = { color: null, italics: false, indent: null, underline: false, row: row }; + + if (byte > 0x5F) { + pacIndex = byte - 0x60; + } else { + pacIndex = byte - 0x40; + } + pacData.underline = (pacIndex & 1) === 1; + if (pacIndex <= 0xd) { + pacData.color = ['white', 'green', 'blue', 'cyan', 'red', 'yellow', 'magenta', 'white'][Math.floor(pacIndex / 2)]; + } else if (pacIndex <= 0xf) { + pacData.italics = true; + pacData.color = 'white'; + } else { + pacData.indent = Math.floor((pacIndex - 0x10) / 2) * 4; + } + return pacData; // Note that row has zero offset. The spec uses 1. + }, + + /** + * Parse characters. + * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise. + */ + parseChars: function parseChars(a, b) { + + var channelNr = null, + charCodes = null, + charCode1 = null, + charCode2 = null; + + if (a >= 0x19) { + channelNr = 2; + charCode1 = a - 8; + } else { + channelNr = 1; + charCode1 = a; + } + if (0x11 <= charCode1 && charCode1 <= 0x13) { + // Special character + var oneCode = b; + if (charCode1 === 0x11) { + oneCode = b + 0x50; + } else if (charCode1 === 0x12) { + oneCode = b + 0x70; + } else { + oneCode = b + 0x90; + } + logger.log("INFO", "Special char '" + getCharForByte(oneCode) + "' in channel " + channelNr); + charCodes = [oneCode]; + this.lastCmdA = a; + this.lastCmdB = b; + } else if (0x20 <= a && a <= 0x7f) { + charCodes = b === 0 ? [a] : [a, b]; + this.lastCmdA = null; + this.lastCmdB = null; + } + if (charCodes) { + var hexCodes = numArrayToHexArray(charCodes); + logger.log("DEBUG", "Char codes = " + hexCodes.join(",")); + } + return charCodes; + }, + + /** + * Parse extended background attributes as well as new foreground color black. + * @returns{Boolean} Tells if background attributes are found + */ + parseBackgroundAttributes: function parseBackgroundAttributes(a, b) { + var bkgData, index, chNr, channel; + + var case1 = (a === 0x10 || a === 0x18) && 0x20 <= b && b <= 0x2f; + var case2 = (a === 0x17 || a === 0x1f) && 0x2d <= b && b <= 0x2f; + if (!(case1 || case2)) { + return false; + } + bkgData = {}; + if (a === 0x10 || a === 0x18) { + index = Math.floor((b - 0x20) / 2); + bkgData.background = backgroundColors[index]; + if (b % 2 === 1) { + bkgData.background = bkgData.background + "_semi"; + } + } else if (b === 0x2d) { + bkgData.background = "transparent"; + } else { + bkgData.foreground = "black"; + if (b === 0x2f) { + bkgData.underline = true; + } + } + chNr = a < 0x18 ? 1 : 2; + channel = this.channels[chNr - 1]; + channel.setBkgData(bkgData); + this.lastCmdA = a; + this.lastCmdB = b; + return true; + }, + + /** + * Reset state of parser and its channels. + */ + reset: function reset() { + for (var i = 0; i < this.channels.length; i++) { + if (this.channels[i]) { + this.channels[i].reset(); + } + } + this.lastCmdA = null; + this.lastCmdB = null; + }, + + /** + * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty. + */ + cueSplitAtTime: function cueSplitAtTime(t) { + for (var i = 0; i < this.channels.length; i++) { + if (this.channels[i]) { + this.channels[i].cueSplitAtTime(t); + } + } + } + }; + + /** + * Find ranges corresponding to SEA CEA-608 NALUS in sizeprepended NALU array. + * @param {raw} dataView of binary data + * @param {startPos} start position in raw + * @param {size} total size of data in raw to consider + * @returns + */ + var findCea608Nalus = function findCea608Nalus(raw, startPos, size) { + var nalSize = 0, + cursor = startPos, + nalType = 0, + cea608NaluRanges = [], + + // Check SEI data according to ANSI-SCTE 128 + isCEA608SEI = function isCEA608SEI(payloadType, payloadSize, raw, pos) { + if (payloadType !== 4 || payloadSize < 8) { + return null; + } + var countryCode = raw.getUint8(pos); + var providerCode = raw.getUint16(pos + 1); + var userIdentifier = raw.getUint32(pos + 3); + var userDataTypeCode = raw.getUint8(pos + 7); + return countryCode == 0xB5 && providerCode == 0x31 && userIdentifier == 0x47413934 && userDataTypeCode == 0x3; + }; + while (cursor < startPos + size) { + nalSize = raw.getUint32(cursor); + nalType = raw.getUint8(cursor + 4) & 0x1F; + //console.log(time + " NAL " + nalType); + if (nalType === 6) { + // SEI NAL Unit. The NAL header is the first byte + //console.log("SEI NALU of size " + nalSize + " at time " + time); + var pos = cursor + 5; + var payloadType = -1; + while (pos < cursor + 4 + nalSize - 1) { + // The last byte should be rbsp_trailing_bits + payloadType = 0; + var b = 0xFF; + while (b === 0xFF) { + b = raw.getUint8(pos); + payloadType += b; + pos++; + } + var payloadSize = 0; + b = 0xFF; + while (b === 0xFF) { + b = raw.getUint8(pos); + payloadSize += b; + pos++; + } + if (isCEA608SEI(payloadType, payloadSize, raw, pos)) { + //console.log("CEA608 SEI " + time + " " + payloadSize); + cea608NaluRanges.push([pos, payloadSize]); + } + pos += payloadSize; + } + } + cursor += nalSize + 4; + } + return cea608NaluRanges; + }; + + var extractCea608DataFromRange = function extractCea608DataFromRange(raw, cea608Range) { + var pos = cea608Range[0]; + var fieldData = [[], []]; + + pos += 8; // Skip the identifier up to userDataTypeCode + var ccCount = raw.getUint8(pos) & 0x1f; + pos += 2; // Advance 1 and skip reserved byte + + for (var i = 0; i < ccCount; i++) { + var byte = raw.getUint8(pos); + var ccValid = byte & 0x4; + var ccType = byte & 0x3; + pos++; + var ccData1 = raw.getUint8(pos); // Keep parity bit + pos++; + var ccData2 = raw.getUint8(pos); // Keep parity bit + pos++; + if (ccValid && (ccData1 & 0x7f) + (ccData2 & 0x7f) !== 0) { + //Check validity and non-empty data + if (ccType === 0) { + fieldData[0].push(ccData1); + fieldData[0].push(ccData2); + } else if (ccType === 1) { + fieldData[1].push(ccData1); + fieldData[1].push(ccData2); + } + } + } + return fieldData; + }; + + exports.logger = logger; + exports.PenState = PenState; + exports.CaptionScreen = CaptionScreen; + exports.Cea608Parser = Cea608Parser; + exports.findCea608Nalus = findCea608Nalus; + exports.extractCea608DataFromRange = extractCea608DataFromRange; +})(typeof exports === 'undefined' ? undefined.cea608parser = {} : exports); + +},{}],3:[function(_dereq_,module,exports){ +/* + Copyright 2011-2013 Abdulla Abdurakhmanov + Original sources are available at https://code.google.com/p/x2js/ + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/* + Further modified for dashjs to: + - keep track of children nodes in order in attribute __children. + - add type conversion matchers + - re-add ignoreRoot + - allow zero-length attributePrefix + - don't add white-space text nodes + - remove explicit RequireJS support +*/ + +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +function X2JS(config) { + 'use strict'; + + var VERSION = "1.2.0"; + + config = config || {}; + initConfigDefaults(); + initRequiredPolyfills(); + + function initConfigDefaults() { + if (config.escapeMode === undefined) { + config.escapeMode = true; + } + + if (config.attributePrefix === undefined) { + config.attributePrefix = "_"; + } + + config.arrayAccessForm = config.arrayAccessForm || "none"; + config.emptyNodeForm = config.emptyNodeForm || "text"; + + if (config.enableToStringFunc === undefined) { + config.enableToStringFunc = true; + } + config.arrayAccessFormPaths = config.arrayAccessFormPaths || []; + if (config.skipEmptyTextNodesForObj === undefined) { + config.skipEmptyTextNodesForObj = true; + } + if (config.stripWhitespaces === undefined) { + config.stripWhitespaces = true; + } + config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || []; + + if (config.useDoubleQuotes === undefined) { + config.useDoubleQuotes = false; + } + + config.xmlElementsFilter = config.xmlElementsFilter || []; + config.jsonPropertiesFilter = config.jsonPropertiesFilter || []; + + if (config.keepCData === undefined) { + config.keepCData = false; + } + + if (config.ignoreRoot === undefined) { + config.ignoreRoot = false; + } + } + + var DOMNodeTypes = { + ELEMENT_NODE: 1, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9 + }; + + function initRequiredPolyfills() {} + + function getNodeLocalName(node) { + var nodeLocalName = node.localName; + if (nodeLocalName == null) // Yeah, this is IE!! + nodeLocalName = node.baseName; + if (nodeLocalName == null || nodeLocalName == "") // =="" is IE too + nodeLocalName = node.nodeName; + return nodeLocalName; + } + + function getNodePrefix(node) { + return node.prefix; + } + + function escapeXmlChars(str) { + if (typeof str == "string") return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');else return str; + } + + function unescapeXmlChars(str) { + return str.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&'); + } + + function checkInStdFiltersArrayForm(stdFiltersArrayForm, obj, name, path) { + var idx = 0; + for (; idx < stdFiltersArrayForm.length; idx++) { + var filterPath = stdFiltersArrayForm[idx]; + if (typeof filterPath === "string") { + if (filterPath == path) break; + } else if (filterPath instanceof RegExp) { + if (filterPath.test(path)) break; + } else if (typeof filterPath === "function") { + if (filterPath(obj, name, path)) break; + } + } + return idx != stdFiltersArrayForm.length; + } + + function toArrayAccessForm(obj, childName, path) { + switch (config.arrayAccessForm) { + case "property": + if (!(obj[childName] instanceof Array)) obj[childName + "_asArray"] = [obj[childName]];else obj[childName + "_asArray"] = obj[childName]; + break; + /*case "none": + break;*/ + } + + if (!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) { + if (checkInStdFiltersArrayForm(config.arrayAccessFormPaths, obj, childName, path)) { + obj[childName] = [obj[childName]]; + } + } + } + + function fromXmlDateTime(prop) { + // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object + // Improved to support full spec and optional parts + var bits = prop.split(/[-T:+Z]/g); + + var d = new Date(bits[0], bits[1] - 1, bits[2]); + var secondBits = bits[5].split("\."); + d.setHours(bits[3], bits[4], secondBits[0]); + if (secondBits.length > 1) d.setMilliseconds(secondBits[1]); + + // Get supplied time zone offset in minutes + if (bits[6] && bits[7]) { + var offsetMinutes = bits[6] * 60 + Number(bits[7]); + var sign = /\d\d-\d\d:\d\d$/.test(prop) ? '-' : '+'; + + // Apply the sign + offsetMinutes = 0 + (sign == '-' ? -1 * offsetMinutes : offsetMinutes); + + // Apply offset and local timezone + d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset()); + } else if (prop.indexOf("Z", prop.length - 1) !== -1) { + d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds())); + } + + // d is now a local time equivalent to the supplied time + return d; + } + + function checkFromXmlDateTimePaths(value, childName, fullPath) { + if (config.datetimeAccessFormPaths.length > 0) { + var path = fullPath.split("\.#")[0]; + if (checkInStdFiltersArrayForm(config.datetimeAccessFormPaths, value, childName, path)) { + return fromXmlDateTime(value); + } else return value; + } else return value; + } + + function checkXmlElementsFilter(obj, childType, childName, childPath) { + if (childType == DOMNodeTypes.ELEMENT_NODE && config.xmlElementsFilter.length > 0) { + return checkInStdFiltersArrayForm(config.xmlElementsFilter, obj, childName, childPath); + } else return true; + } + + function parseDOMChildren(node, path) { + if (node.nodeType == DOMNodeTypes.DOCUMENT_NODE) { + var result = new Object(); + var nodeChildren = node.childNodes; + // Alternative for firstElementChild which is not supported in some environments + for (var cidx = 0; cidx < nodeChildren.length; cidx++) { + var child = nodeChildren[cidx]; + if (child.nodeType == DOMNodeTypes.ELEMENT_NODE) { + if (config.ignoreRoot) { + result = parseDOMChildren(child); + } else { + result = {}; + var childName = getNodeLocalName(child); + result[childName] = parseDOMChildren(child); + } + } + } + return result; + } else if (node.nodeType == DOMNodeTypes.ELEMENT_NODE) { + var result = new Object(); + result.__cnt = 0; + + var children = []; + var nodeChildren = node.childNodes; + + // Children nodes + for (var cidx = 0; cidx < nodeChildren.length; cidx++) { + var child = nodeChildren[cidx]; + var childName = getNodeLocalName(child); + + if (child.nodeType != DOMNodeTypes.COMMENT_NODE) { + var childPath = path + "." + childName; + if (checkXmlElementsFilter(result, child.nodeType, childName, childPath)) { + result.__cnt++; + if (result[childName] == null) { + var c = parseDOMChildren(child, childPath); + if (childName != "#text" || /[^\s]/.test(c)) { + var o = {}; + o[childName] = c; + children.push(o); + } + result[childName] = c; + toArrayAccessForm(result, childName, childPath); + } else { + if (result[childName] != null) { + if (!(result[childName] instanceof Array)) { + result[childName] = [result[childName]]; + toArrayAccessForm(result, childName, childPath); + } + } + + var c = parseDOMChildren(child, childPath); + if (childName != "#text" || /[^\s]/.test(c)) { + // Don't add white-space text nodes + var o = {}; + o[childName] = c; + children.push(o); + } + result[childName][result[childName].length] = c; + } + } + } + } + + result.__children = children; + + // Attributes + var nodeLocalName = getNodeLocalName(node); + for (var aidx = 0; aidx < node.attributes.length; aidx++) { + var attr = node.attributes[aidx]; + result.__cnt++; + + var value2 = attr.value; + for (var m = 0, ml = config.matchers.length; m < ml; m++) { + var matchobj = config.matchers[m]; + if (matchobj.test(attr, nodeLocalName)) value2 = matchobj.converter(attr.value); + } + + result[config.attributePrefix + attr.name] = value2; + } + + // Node namespace prefix + var nodePrefix = getNodePrefix(node); + if (nodePrefix != null && nodePrefix != "") { + result.__cnt++; + result.__prefix = nodePrefix; + } + + if (result["#text"] != null) { + result.__text = result["#text"]; + if (result.__text instanceof Array) { + result.__text = result.__text.join("\n"); + } + //if(config.escapeMode) + // result.__text = unescapeXmlChars(result.__text); + if (config.stripWhitespaces) result.__text = result.__text.trim(); + delete result["#text"]; + if (config.arrayAccessForm == "property") delete result["#text_asArray"]; + result.__text = checkFromXmlDateTimePaths(result.__text, childName, path + "." + childName); + } + if (result["#cdata-section"] != null) { + result.__cdata = result["#cdata-section"]; + delete result["#cdata-section"]; + if (config.arrayAccessForm == "property") delete result["#cdata-section_asArray"]; + } + + if (result.__cnt == 0 && config.emptyNodeForm == "text") { + result = ''; + } else if (result.__cnt == 1 && result.__text != null) { + result = result.__text; + } else if (result.__cnt == 1 && result.__cdata != null && !config.keepCData) { + result = result.__cdata; + } else if (result.__cnt > 1 && result.__text != null && config.skipEmptyTextNodesForObj) { + if (config.stripWhitespaces && result.__text == "" || result.__text.trim() == "") { + delete result.__text; + } + } + delete result.__cnt; + + if (config.enableToStringFunc && (result.__text != null || result.__cdata != null)) { + result.toString = function () { + return (this.__text != null ? this.__text : '') + (this.__cdata != null ? this.__cdata : ''); + }; + } + + return result; + } else if (node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) { + return node.nodeValue; + } + } + + function startTag(jsonObj, element, attrList, closed) { + var resultStr = "<" + (jsonObj != null && jsonObj.__prefix != null ? jsonObj.__prefix + ":" : "") + element; + if (attrList != null) { + for (var aidx = 0; aidx < attrList.length; aidx++) { + var attrName = attrList[aidx]; + var attrVal = jsonObj[attrName]; + if (config.escapeMode) attrVal = escapeXmlChars(attrVal); + resultStr += " " + attrName.substr(config.attributePrefix.length) + "="; + if (config.useDoubleQuotes) resultStr += '"' + attrVal + '"';else resultStr += "'" + attrVal + "'"; + } + } + if (!closed) resultStr += ">";else resultStr += "/>"; + return resultStr; + } + + function endTag(jsonObj, elementName) { + return ""; + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + function jsonXmlSpecialElem(jsonObj, jsonObjField) { + if (config.arrayAccessForm == "property" && endsWith(jsonObjField.toString(), "_asArray") || jsonObjField.toString().indexOf(config.attributePrefix) == 0 || jsonObjField.toString().indexOf("__") == 0 || jsonObj[jsonObjField] instanceof Function) return true;else return false; + } + + function jsonXmlElemCount(jsonObj) { + var elementsCnt = 0; + if (jsonObj instanceof Object) { + for (var it in jsonObj) { + if (jsonXmlSpecialElem(jsonObj, it)) continue; + elementsCnt++; + } + } + return elementsCnt; + } + + function checkJsonObjPropertiesFilter(jsonObj, propertyName, jsonObjPath) { + return config.jsonPropertiesFilter.length == 0 || jsonObjPath == "" || checkInStdFiltersArrayForm(config.jsonPropertiesFilter, jsonObj, propertyName, jsonObjPath); + } + + function parseJSONAttributes(jsonObj) { + var attrList = []; + if (jsonObj instanceof Object) { + for (var ait in jsonObj) { + if (ait.toString().indexOf("__") == -1 && ait.toString().indexOf(config.attributePrefix) == 0) { + attrList.push(ait); + } + } + } + return attrList; + } + + function parseJSONTextAttrs(jsonTxtObj) { + var result = ""; + + if (jsonTxtObj.__cdata != null) { + result += ""; + } + + if (jsonTxtObj.__text != null) { + if (config.escapeMode) result += escapeXmlChars(jsonTxtObj.__text);else result += jsonTxtObj.__text; + } + return result; + } + + function parseJSONTextObject(jsonTxtObj) { + var result = ""; + + if (jsonTxtObj instanceof Object) { + result += parseJSONTextAttrs(jsonTxtObj); + } else if (jsonTxtObj != null) { + if (config.escapeMode) result += escapeXmlChars(jsonTxtObj);else result += jsonTxtObj; + } + + return result; + } + + function getJsonPropertyPath(jsonObjPath, jsonPropName) { + if (jsonObjPath === "") { + return jsonPropName; + } else return jsonObjPath + "." + jsonPropName; + } + + function parseJSONArray(jsonArrRoot, jsonArrObj, attrList, jsonObjPath) { + var result = ""; + if (jsonArrRoot.length == 0) { + result += startTag(jsonArrRoot, jsonArrObj, attrList, true); + } else { + for (var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) { + result += startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false); + result += parseJSONObject(jsonArrRoot[arIdx], getJsonPropertyPath(jsonObjPath, jsonArrObj)); + result += endTag(jsonArrRoot[arIdx], jsonArrObj); + } + } + return result; + } + + function parseJSONObject(jsonObj, jsonObjPath) { + var result = ""; + + var elementsCnt = jsonXmlElemCount(jsonObj); + + if (elementsCnt > 0) { + for (var it in jsonObj) { + + if (jsonXmlSpecialElem(jsonObj, it) || jsonObjPath != "" && !checkJsonObjPropertiesFilter(jsonObj, it, getJsonPropertyPath(jsonObjPath, it))) continue; + + var subObj = jsonObj[it]; + + var attrList = parseJSONAttributes(subObj); + + if (subObj == null || subObj == undefined) { + result += startTag(subObj, it, attrList, true); + } else if (subObj instanceof Object) { + + if (subObj instanceof Array) { + result += parseJSONArray(subObj, it, attrList, jsonObjPath); + } else if (subObj instanceof Date) { + result += startTag(subObj, it, attrList, false); + result += subObj.toISOString(); + result += endTag(subObj, it); + } else { + var subObjElementsCnt = jsonXmlElemCount(subObj); + if (subObjElementsCnt > 0 || subObj.__text != null || subObj.__cdata != null) { + result += startTag(subObj, it, attrList, false); + result += parseJSONObject(subObj, getJsonPropertyPath(jsonObjPath, it)); + result += endTag(subObj, it); + } else { + result += startTag(subObj, it, attrList, true); + } + } + } else { + result += startTag(subObj, it, attrList, false); + result += parseJSONTextObject(subObj); + result += endTag(subObj, it); + } + } + } + result += parseJSONTextObject(jsonObj); + + return result; + } + + this.parseXmlString = function (xmlDocStr) { + var isIEParser = window.ActiveXObject || "ActiveXObject" in window; + if (xmlDocStr === undefined) { + return null; + } + var xmlDoc; + if (window.DOMParser) { + var parser = new window.DOMParser(); + var parsererrorNS = null; + try { + xmlDoc = parser.parseFromString(xmlDocStr, "text/xml"); + if (xmlDoc.getElementsByTagNameNS("*", "parsererror").length > 0) { + xmlDoc = null; + } + } catch (err) { + xmlDoc = null; + } + } else { + // IE :( + if (xmlDocStr.indexOf("") + 2); + } + xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(xmlDocStr); + } + return xmlDoc; + }; + + this.asArray = function (prop) { + if (prop === undefined || prop == null) return [];else if (prop instanceof Array) return prop;else return [prop]; + }; + + this.toXmlDateTime = function (dt) { + if (dt instanceof Date) return dt.toISOString();else if (typeof dt === 'number') return new Date(dt).toISOString();else return null; + }; + + this.asDateTime = function (prop) { + if (typeof prop == "string") { + return fromXmlDateTime(prop); + } else return prop; + }; + + this.xml2json = function (xmlDoc) { + return parseDOMChildren(xmlDoc); + }; + + this.xml_str2json = function (xmlDocStr) { + var xmlDoc = this.parseXmlString(xmlDocStr); + if (xmlDoc != null) return this.xml2json(xmlDoc);else return null; + }; + + this.json2xml_str = function (jsonObj) { + return parseJSONObject(jsonObj, ""); + }; + + this.json2xml = function (jsonObj) { + var xmlDocStr = this.json2xml_str(jsonObj); + return this.parseXmlString(xmlDocStr); + }; + + this.getVersion = function () { + return VERSION; + }; +} + +exports["default"] = X2JS; +module.exports = exports["default"]; + +},{}],4:[function(_dereq_,module,exports){ +(function (global){ +/** + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and contributor + * rights, including patent rights, and no such rights are granted under this license. + * + * Copyright (c) 2013, Dash Industry Forum. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * Neither the name of Dash Industry Forum nor the names of its + * contributors may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _srcStreamingMediaPlayer = _dereq_(91); + +var _srcStreamingMediaPlayer2 = _interopRequireDefault(_srcStreamingMediaPlayer); + +var _srcCoreFactoryMaker = _dereq_(47); + +var _srcCoreFactoryMaker2 = _interopRequireDefault(_srcCoreFactoryMaker); + +var _srcCoreDebug = _dereq_(45); + +var _srcCoreDebug2 = _interopRequireDefault(_srcCoreDebug); + +var _srcCoreVersion = _dereq_(48); + +// Shove both of these into the global scope +var context = typeof window !== 'undefined' && window || global; + +var dashjs = context.dashjs; +if (!dashjs) { + dashjs = context.dashjs = {}; +} + +dashjs.MediaPlayer = _srcStreamingMediaPlayer2['default']; +dashjs.FactoryMaker = _srcCoreFactoryMaker2['default']; +dashjs.Debug = _srcCoreDebug2['default']; +dashjs.Version = (0, _srcCoreVersion.getVersionString)(); + +exports['default'] = dashjs; +exports.MediaPlayer = _srcStreamingMediaPlayer2['default']; +exports.FactoryMaker = _srcCoreFactoryMaker2['default']; +exports.Debug = _srcCoreDebug2['default']; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"45":45,"47":47,"48":48,"91":91}],5:[function(_dereq_,module,exports){ +/*! codem-isoboxer v0.3.5 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */ +var ISOBoxer = {}; + +ISOBoxer.parseBuffer = function(arrayBuffer) { + return new ISOFile(arrayBuffer).parse(); +}; + +ISOBoxer.addBoxProcessor = function(type, parser) { + if (typeof type !== 'string' || typeof parser !== 'function') { + return; + } + ISOBox.prototype._boxProcessors[type] = parser; +}; + +ISOBoxer.createFile = function() { + return new ISOFile(); +}; + +// See ISOBoxer.append() for 'pos' parameter syntax +ISOBoxer.createBox = function(type, parent, pos) { + var newBox = ISOBox.create(type); + if (parent) { + parent.append(newBox, pos); + } + return newBox; +}; + +// See ISOBoxer.append() for 'pos' parameter syntax +ISOBoxer.createFullBox = function(type, parent, pos) { + var newBox = ISOBoxer.createBox(type, parent, pos); + newBox.version = 0; + newBox.flags = 0; + return newBox; +}; + +ISOBoxer.Utils = {}; +ISOBoxer.Utils.dataViewToString = function(dataView, encoding) { + var impliedEncoding = encoding || 'utf-8'; + if (typeof TextDecoder !== 'undefined') { + return new TextDecoder(impliedEncoding).decode(dataView); + } + var a = []; + var i = 0; + + if (impliedEncoding === 'utf-8') { + /* The following algorithm is essentially a rewrite of the UTF8.decode at + http://bannister.us/weblog/2007/simple-base64-encodedecode-javascript/ + */ + + while (i < dataView.byteLength) { + var c = dataView.getUint8(i++); + if (c < 0x80) { + // 1-byte character (7 bits) + } else if (c < 0xe0) { + // 2-byte character (11 bits) + c = (c & 0x1f) << 6; + c |= (dataView.getUint8(i++) & 0x3f); + } else if (c < 0xf0) { + // 3-byte character (16 bits) + c = (c & 0xf) << 12; + c |= (dataView.getUint8(i++) & 0x3f) << 6; + c |= (dataView.getUint8(i++) & 0x3f); + } else { + // 4-byte character (21 bits) + c = (c & 0x7) << 18; + c |= (dataView.getUint8(i++) & 0x3f) << 12; + c |= (dataView.getUint8(i++) & 0x3f) << 6; + c |= (dataView.getUint8(i++) & 0x3f); + } + a.push(String.fromCharCode(c)); + } + } else { // Just map byte-by-byte (probably wrong) + while (i < dataView.byteLength) { + a.push(String.fromCharCode(dataView.getUint8(i++))); + } + } + return a.join(''); +}; + +ISOBoxer.Utils.utf8ToByteArray = function(string) { + // Only UTF-8 encoding is supported by TextEncoder + var u, i; + if (typeof TextEncoder !== 'undefined') { + u = new TextEncoder().encode(string); + } else { + u = []; + for (i = 0; i < string.length; ++i) { + var c = string.charCodeAt(i); + if (c < 0x80) { + u.push(c); + } else if (c < 0x800) { + u.push(0xC0 | (c >> 6)); + u.push(0x80 | (63 & c)); + } else if (c < 0x10000) { + u.push(0xE0 | (c >> 12)); + u.push(0x80 | (63 & (c >> 6))); + u.push(0x80 | (63 & c)); + } else { + u.push(0xF0 | (c >> 18)); + u.push(0x80 | (63 & (c >> 12))); + u.push(0x80 | (63 & (c >> 6))); + u.push(0x80 | (63 & c)); + } + } + } + return u; +}; + +// Method to append a box in the list of child boxes +// The 'pos' parameter can be either: +// - (number) a position index at which to insert the new box +// - (string) the type of the box after which to insert the new box +// - (object) the box after which to insert the new box +ISOBoxer.Utils.appendBox = function(parent, box, pos) { + box._offset = parent._cursor.offset; + box._root = (parent._root ? parent._root : parent); + box._raw = parent._raw; + box._parent = parent; + + if (pos === -1) { + // The new box is a sub-box of the parent but not added in boxes array, + // for example when the new box is set as an entry (see dref and stsd for example) + return; + } + + if (pos === undefined || pos === null) { + parent.boxes.push(box); + return; + } + + var index = -1, + type; + + if (typeof pos === "number") { + index = pos; + } else { + if (typeof pos === "string") { + type = pos; + } else if (typeof pos === "object" && pos.type) { + type = pos.type; + } else { + parent.boxes.push(box); + return; + } + + for (var i = 0; i < parent.boxes.length; i++) { + if (type === parent.boxes[i].type) { + index = i + 1; + break; + } + } + } + parent.boxes.splice(index, 0, box); +}; + +if (typeof exports !== 'undefined') { + exports.parseBuffer = ISOBoxer.parseBuffer; + exports.addBoxProcessor = ISOBoxer.addBoxProcessor; + exports.createFile = ISOBoxer.createFile; + exports.createBox = ISOBoxer.createBox; + exports.createFullBox = ISOBoxer.createFullBox; + exports.Utils = ISOBoxer.Utils; +} + +ISOBoxer.Cursor = function(initialOffset) { + this.offset = (typeof initialOffset == 'undefined' ? 0 : initialOffset); +}; + +var ISOFile = function(arrayBuffer) { + this._cursor = new ISOBoxer.Cursor(); + this.boxes = []; + if (arrayBuffer) { + this._raw = new DataView(arrayBuffer); + } +}; + +ISOFile.prototype.fetch = function(type) { + var result = this.fetchAll(type, true); + return (result.length ? result[0] : null); +}; + +ISOFile.prototype.fetchAll = function(type, returnEarly) { + var result = []; + ISOFile._sweep.call(this, type, result, returnEarly); + return result; +}; + +ISOFile.prototype.parse = function() { + this._cursor.offset = 0; + this.boxes = []; + while (this._cursor.offset < this._raw.byteLength) { + var box = ISOBox.parse(this); + + // Box could not be parsed + if (typeof box.type === 'undefined') break; + + this.boxes.push(box); + } + return this; +}; + +ISOFile._sweep = function(type, result, returnEarly) { + if (this.type && this.type == type) result.push(this); + for (var box in this.boxes) { + if (result.length && returnEarly) return; + ISOFile._sweep.call(this.boxes[box], type, result, returnEarly); + } +}; + +ISOFile.prototype.write = function() { + + var length = 0, + i; + + for (i = 0; i < this.boxes.length; i++) { + length += this.boxes[i].getLength(false); + } + + var bytes = new Uint8Array(length); + this._rawo = new DataView(bytes.buffer); + this.bytes = bytes; + this._cursor.offset = 0; + + for (i = 0; i < this.boxes.length; i++) { + this.boxes[i].write(); + } + + return bytes.buffer; +}; + +ISOFile.prototype.append = function(box, pos) { + ISOBoxer.Utils.appendBox(this, box, pos); +}; +var ISOBox = function() { + this._cursor = new ISOBoxer.Cursor(); +}; + +ISOBox.parse = function(parent) { + var newBox = new ISOBox(); + newBox._offset = parent._cursor.offset; + newBox._root = (parent._root ? parent._root : parent); + newBox._raw = parent._raw; + newBox._parent = parent; + newBox._parseBox(); + parent._cursor.offset = newBox._raw.byteOffset + newBox._raw.byteLength; + return newBox; +}; + +ISOBox.create = function(type) { + var newBox = new ISOBox(); + newBox.type = type; + newBox.boxes = []; + return newBox; +}; + +ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc', 'sinf', 'schi', 'encv', 'enca']; + +ISOBox.prototype._boxProcessors = {}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Generic read/write functions + +ISOBox.prototype._procField = function (name, type, size) { + if (this._parsing) { + this[name] = this._readField(type, size); + } + else { + this._writeField(type, size, this[name]); + } +}; + +ISOBox.prototype._procFieldArray = function (name, length, type, size) { + var i; + if (this._parsing) { + this[name] = []; + for (i = 0; i < length; i++) { + this[name][i] = this._readField(type, size); + } + } + else { + for (i = 0; i < this[name].length; i++) { + this._writeField(type, size, this[name][i]); + } + } +}; + +ISOBox.prototype._procFullBox = function() { + this._procField('version', 'uint', 8); + this._procField('flags', 'uint', 24); +}; + +ISOBox.prototype._procEntries = function(name, length, fn) { + var i; + if (this._parsing) { + this[name] = []; + for (i = 0; i < length; i++) { + this[name].push({}); + fn.call(this, this[name][i]); + } + } + else { + for (i = 0; i < length; i++) { + fn.call(this, this[name][i]); + } + } +}; + +ISOBox.prototype._procSubEntries = function(entry, name, length, fn) { + var i; + if (this._parsing) { + entry[name] = []; + for (i = 0; i < length; i++) { + entry[name].push({}); + fn.call(this, entry[name][i]); + } + } + else { + for (i = 0; i < length; i++) { + fn.call(this, entry[name][i]); + } + } +}; + +ISOBox.prototype._procEntryField = function (entry, name, type, size) { + if (this._parsing) { + entry[name] = this._readField(type, size); + } + else { + this._writeField(type, size, entry[name]); + } +}; + +ISOBox.prototype._procSubBoxes = function(name, length) { + var i; + if (this._parsing) { + this[name] = []; + for (i = 0; i < length; i++) { + this[name].push(ISOBox.parse(this)); + } + } + else { + for (i = 0; i < length; i++) { + if (this._rawo) { + this[name][i].write(); + } else { + this.size += this[name][i].getLength(); + } + } + } +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Read/parse functions + +ISOBox.prototype._readField = function(type, size) { + switch (type) { + case 'uint': + return this._readUint(size); + case 'int': + return this._readInt(size); + case 'template': + return this._readTemplate(size); + case 'string': + return (size === -1) ? this._readTerminatedString() : this._readString(size); + case 'data': + return this._readData(size); + case 'utf8': + return this._readUTF8String(); + default: + return -1; + } +}; + +ISOBox.prototype._readInt = function(size) { + var result = null, + offset = this._cursor.offset - this._raw.byteOffset; + switch(size) { + case 8: + result = this._raw.getInt8(offset); + break; + case 16: + result = this._raw.getInt16(offset); + break; + case 32: + result = this._raw.getInt32(offset); + break; + case 64: + // Warning: JavaScript cannot handle 64-bit integers natively. + // This will give unexpected results for integers >= 2^53 + var s1 = this._raw.getInt32(offset); + var s2 = this._raw.getInt32(offset + 4); + result = (s1 * Math.pow(2,32)) + s2; + break; + } + this._cursor.offset += (size >> 3); + return result; +}; + +ISOBox.prototype._readUint = function(size) { + var result = null, + offset = this._cursor.offset - this._raw.byteOffset, + s1, s2; + switch(size) { + case 8: + result = this._raw.getUint8(offset); + break; + case 16: + result = this._raw.getUint16(offset); + break; + case 24: + s1 = this._raw.getUint16(offset); + s2 = this._raw.getUint8(offset + 2); + result = (s1 << 8) + s2; + break; + case 32: + result = this._raw.getUint32(offset); + break; + case 64: + // Warning: JavaScript cannot handle 64-bit integers natively. + // This will give unexpected results for integers >= 2^53 + s1 = this._raw.getUint32(offset); + s2 = this._raw.getUint32(offset + 4); + result = (s1 * Math.pow(2,32)) + s2; + break; + } + this._cursor.offset += (size >> 3); + return result; +}; + +ISOBox.prototype._readString = function(length) { + var str = ''; + for (var c = 0; c < length; c++) { + var char = this._readUint(8); + str += String.fromCharCode(char); + } + return str; +}; + +ISOBox.prototype._readTemplate = function(size) { + var pre = this._readUint(size / 2); + var post = this._readUint(size / 2); + return pre + (post / Math.pow(2, size / 2)); +}; + +ISOBox.prototype._readTerminatedString = function() { + var str = ''; + while (this._cursor.offset - this._offset < this._raw.byteLength) { + var char = this._readUint(8); + if (char === 0) break; + str += String.fromCharCode(char); + } + return str; +}; + +ISOBox.prototype._readData = function(size) { + var length = (size > 0) ? size : (this._raw.byteLength - (this._cursor.offset - this._offset)); + if (length > 0) { + var data = new Uint8Array(this._raw.buffer, this._cursor.offset, length); + + this._cursor.offset += length; + return data; + } + else { + return null; + } +}; + +ISOBox.prototype._readUTF8String = function() { + var length = this._raw.byteLength - (this._cursor.offset - this._offset); + var data = null; + if (length > 0) { + data = new DataView(this._raw.buffer, this._cursor.offset, length); + this._cursor.offset += length; + } + + return data ? ISOBoxer.Utils.dataViewToString(data) : data; +}; + +ISOBox.prototype._parseBox = function() { + this._parsing = true; + this._cursor.offset = this._offset; + + // return immediately if there are not enough bytes to read the header + if (this._offset + 8 > this._raw.buffer.byteLength) { + this._root._incomplete = true; + return; + } + + this._procField('size', 'uint', 32); + this._procField('type', 'string', 4); + + if (this.size === 1) { this._procField('largesize', 'uint', 64); } + if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } + + switch(this.size) { + case 0: + this._raw = new DataView(this._raw.buffer, this._offset, (this._raw.byteLength - this._cursor.offset + 8)); + break; + case 1: + if (this._offset + this.size > this._raw.buffer.byteLength) { + this._incomplete = true; + this._root._incomplete = true; + } else { + this._raw = new DataView(this._raw.buffer, this._offset, this.largesize); + } + break; + default: + if (this._offset + this.size > this._raw.buffer.byteLength) { + this._incomplete = true; + this._root._incomplete = true; + } else { + this._raw = new DataView(this._raw.buffer, this._offset, this.size); + } + } + + // additional parsing + if (!this._incomplete) { + if (this._boxProcessors[this.type]) { + this._boxProcessors[this.type].call(this); + } + if (this._boxContainers.indexOf(this.type) !== -1) { + this._parseContainerBox(); + } else{ + // Unknown box => read and store box content + this._data = this._readData(); + } + } +}; + +ISOBox.prototype._parseFullBox = function() { + this.version = this._readUint(8); + this.flags = this._readUint(24); +}; + +ISOBox.prototype._parseContainerBox = function() { + this.boxes = []; + while (this._cursor.offset - this._raw.byteOffset < this._raw.byteLength) { + this.boxes.push(ISOBox.parse(this)); + } +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Write functions + +ISOBox.prototype.append = function(box, pos) { + ISOBoxer.Utils.appendBox(this, box, pos); +}; + +ISOBox.prototype.getLength = function() { + this._parsing = false; + this._rawo = null; + + this.size = 0; + this._procField('size', 'uint', 32); + this._procField('type', 'string', 4); + + if (this.size === 1) { this._procField('largesize', 'uint', 64); } + if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } + + if (this._boxProcessors[this.type]) { + this._boxProcessors[this.type].call(this); + } + + if (this._boxContainers.indexOf(this.type) !== -1) { + for (var i = 0; i < this.boxes.length; i++) { + this.size += this.boxes[i].getLength(); + } + } + + if (this._data) { + this._writeData(this._data); + } + + return this.size; +}; + +ISOBox.prototype.write = function() { + this._parsing = false; + this._cursor.offset = this._parent._cursor.offset; + + switch(this.size) { + case 0: + this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, (this.parent._rawo.byteLength - this._cursor.offset)); + break; + case 1: + this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.largesize); + break; + default: + this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.size); + } + + this._procField('size', 'uint', 32); + this._procField('type', 'string', 4); + + if (this.size === 1) { this._procField('largesize', 'uint', 64); } + if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } + + if (this._boxProcessors[this.type]) { + this._boxProcessors[this.type].call(this); + } + + if (this._boxContainers.indexOf(this.type) !== -1) { + for (var i = 0; i < this.boxes.length; i++) { + this.boxes[i].write(); + } + } + + if (this._data) { + this._writeData(this._data); + } + + this._parent._cursor.offset += this.size; + + return this.size; +}; + +ISOBox.prototype._writeInt = function(size, value) { + if (this._rawo) { + var offset = this._cursor.offset - this._rawo.byteOffset; + switch(size) { + case 8: + this._rawo.setInt8(offset, value); + break; + case 16: + this._rawo.setInt16(offset, value); + break; + case 32: + this._rawo.setInt32(offset, value); + break; + case 64: + // Warning: JavaScript cannot handle 64-bit integers natively. + // This will give unexpected results for integers >= 2^53 + var s1 = Math.floor(value / Math.pow(2,32)); + var s2 = value - (s1 * Math.pow(2,32)); + this._rawo.setUint32(offset, s1); + this._rawo.setUint32(offset + 4, s2); + break; + } + this._cursor.offset += (size >> 3); + } else { + this.size += (size >> 3); + } +}; + +ISOBox.prototype._writeUint = function(size, value) { + + if (this._rawo) { + var offset = this._cursor.offset - this._rawo.byteOffset, + s1, s2; + switch(size) { + case 8: + this._rawo.setUint8(offset, value); + break; + case 16: + this._rawo.setUint16(offset, value); + break; + case 24: + s1 = (value & 0xFFFF00) >> 8; + s2 = (value & 0x0000FF); + this._rawo.setUint16(offset, s1); + this._rawo.setUint8(offset + 2, s2); + break; + case 32: + this._rawo.setUint32(offset, value); + break; + case 64: + // Warning: JavaScript cannot handle 64-bit integers natively. + // This will give unexpected results for integers >= 2^53 + s1 = Math.floor(value / Math.pow(2,32)); + s2 = value - (s1 * Math.pow(2,32)); + this._rawo.setUint32(offset, s1); + this._rawo.setUint32(offset + 4, s2); + break; + } + this._cursor.offset += (size >> 3); + } else { + this.size += (size >> 3); + } +}; + +ISOBox.prototype._writeString = function(size, str) { + for (var c = 0; c < size; c++) { + this._writeUint(8, str.charCodeAt(c)); + } +}; + +ISOBox.prototype._writeTerminatedString = function(str) { + if (str.length === 0) { + return; + } + for (var c = 0; c < str.length; c++) { + this._writeUint(8, str.charCodeAt(c)); + } + this._writeUint(8, 0); +}; + +ISOBox.prototype._writeTemplate = function(size, value) { + var pre = Math.floor(value); + var post = (value - pre) * Math.pow(2, size / 2); + this._writeUint(size / 2, pre); + this._writeUint(size / 2, post); +}; + +ISOBox.prototype._writeData = function(data) { + var i; + //data to copy + if (data) { + if (this._rawo) { + //Array and Uint8Array has also to be managed + if (data instanceof Array) { + var offset = this._cursor.offset - this._rawo.byteOffset; + for (var i = 0; i < data.length; i++) { + this._rawo.setInt8(offset + i, data[i]); + } + this._cursor.offset += data.length; + } + + if (data instanceof Uint8Array) { + this._root.bytes.set(data, this._cursor.offset); + this._cursor.offset += data.length; + } + + } else { + //nothing to copy only size to compute + this.size += data.length; + } + } +}; + +ISOBox.prototype._writeUTF8String = function(string) { + var u = ISOBoxer.Utils.utf8ToByteArray(string); + if (this._rawo) { + var dataView = new DataView(this._rawo.buffer, this._cursor.offset, u.length); + for (var i = 0; i < u.length; i++) { + dataView.setUint8(i, u[i]); + } + } else { + this.size += u.length; + } +}; + +ISOBox.prototype._writeField = function(type, size, value) { + switch (type) { + case 'uint': + this._writeUint(size, value); + break; + case 'int': + this._writeInt(size, value); + break; + case 'template': + this._writeTemplate(size, value); + break; + case 'string': + if (size == -1) { + this._writeTerminatedString(value); + } else { + this._writeString(size, value); + } + break; + case 'data': + this._writeData(value); + break; + case 'utf8': + this._writeUTF8String(value); + break; + default: + break; + } +}; + +// ISO/IEC 14496-15:2014 - avc1 box +ISOBox.prototype._boxProcessors['avc1'] = ISOBox.prototype._boxProcessors['encv'] = function() { + // SampleEntry fields + this._procFieldArray('reserved1', 6, 'uint', 8); + this._procField('data_reference_index', 'uint', 16); + // VisualSampleEntry fields + this._procField('pre_defined1', 'uint', 16); + this._procField('reserved2', 'uint', 16); + this._procFieldArray('pre_defined2', 3, 'uint', 32); + this._procField('width', 'uint', 16); + this._procField('height', 'uint', 16); + this._procField('horizresolution', 'template', 32); + this._procField('vertresolution', 'template', 32); + this._procField('reserved3', 'uint', 32); + this._procField('frame_count', 'uint', 16); + this._procFieldArray('compressorname', 32,'uint', 8); + this._procField('depth', 'uint', 16); + this._procField('pre_defined3', 'int', 16); + // AVCSampleEntry fields + this._procField('config', 'data', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box +ISOBox.prototype._boxProcessors['dref'] = function() { + this._procFullBox(); + this._procField('entry_count', 'uint', 32); + this._procSubBoxes('entries', this.entry_count); +}; + +// ISO/IEC 14496-12:2012 - 8.6.6 Edit List Box +ISOBox.prototype._boxProcessors['elst'] = function() { + this._procFullBox(); + this._procField('entry_count', 'uint', 32); + this._procEntries('entries', this.entry_count, function(entry) { + this._procEntryField(entry, 'segment_duration', 'uint', (this.version === 1) ? 64 : 32); + this._procEntryField(entry, 'media_time', 'int', (this.version === 1) ? 64 : 32); + this._procEntryField(entry, 'media_rate_integer', 'int', 16); + this._procEntryField(entry, 'media_rate_fraction', 'int', 16); + }); +}; + +// ISO/IEC 23009-1:2014 - 5.10.3.3 Event Message Box +ISOBox.prototype._boxProcessors['emsg'] = function() { + this._procFullBox(); + this._procField('scheme_id_uri', 'string', -1); + this._procField('value', 'string', -1); + this._procField('timescale', 'uint', 32); + this._procField('presentation_time_delta', 'uint', 32); + this._procField('event_duration', 'uint', 32); + this._procField('id', 'uint', 32); + this._procField('message_data', 'data', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.1.2 Free Space Box +ISOBox.prototype._boxProcessors['free'] = ISOBox.prototype._boxProcessors['skip'] = function() { + this._procField('data', 'data', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.12.2 Original Format Box +ISOBox.prototype._boxProcessors['frma'] = function() { + this._procField('data_format', 'uint', 32); +}; +// ISO/IEC 14496-12:2012 - 4.3 File Type Box / 8.16.2 Segment Type Box +ISOBox.prototype._boxProcessors['ftyp'] = +ISOBox.prototype._boxProcessors['styp'] = function() { + this._procField('major_brand', 'string', 4); + this._procField('minor_version', 'uint', 32); + var nbCompatibleBrands = -1; + if (this._parsing) { + nbCompatibleBrands = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset)) / 4; + } + this._procFieldArray('compatible_brands', nbCompatibleBrands, 'string', 4); +}; + +// ISO/IEC 14496-12:2012 - 8.4.3 Handler Reference Box +ISOBox.prototype._boxProcessors['hdlr'] = function() { + this._procFullBox(); + this._procField('pre_defined', 'uint', 32); + this._procField('handler_type', 'string', 4); + this._procFieldArray('reserved', 3, 'uint', 32); + this._procField('name', 'string', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.1.1 Media Data Box +ISOBox.prototype._boxProcessors['mdat'] = function() { + this._procField('data', 'data', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.4.2 Media Header Box +ISOBox.prototype._boxProcessors['mdhd'] = function() { + this._procFullBox(); + this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('timescale', 'uint', 32); + this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); + if (!this._parsing && typeof this.language === 'string') { + // In case of writing and language has been set as a string, then convert it into char codes array + this.language = ((this.language.charCodeAt(0) - 0x60) << 10) | + ((this.language.charCodeAt(1) - 0x60) << 5) | + ((this.language.charCodeAt(2) - 0x60)); + } + this._procField('language', 'uint', 16); + if (this._parsing) { + this.language = String.fromCharCode(((this.language >> 10) & 0x1F) + 0x60, + ((this.language >> 5) & 0x1F) + 0x60, + (this.language & 0x1F) + 0x60); + } + this._procField('pre_defined', 'uint', 16); +}; + +// ISO/IEC 14496-12:2012 - 8.8.2 Movie Extends Header Box +ISOBox.prototype._boxProcessors['mehd'] = function() { + this._procFullBox(); + this._procField('fragment_duration', 'uint', (this.version == 1) ? 64 : 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.5 Movie Fragment Header Box +ISOBox.prototype._boxProcessors['mfhd'] = function() { + this._procFullBox(); + this._procField('sequence_number', 'uint', 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.11 Movie Fragment Random Access Box +ISOBox.prototype._boxProcessors['mfro'] = function() { + this._procFullBox(); + this._procField('mfra_size', 'uint', 32); // Called mfra_size to distinguish from the normal "size" attribute of a box +}; + + +// ISO/IEC 14496-12:2012 - 8.5.2.2 mp4a box (use AudioSampleEntry definition and naming) +ISOBox.prototype._boxProcessors['mp4a'] = ISOBox.prototype._boxProcessors['enca'] = function() { + // SampleEntry fields + this._procFieldArray('reserved1', 6, 'uint', 8); + this._procField('data_reference_index', 'uint', 16); + // AudioSampleEntry fields + this._procFieldArray('reserved2', 2, 'uint', 32); + this._procField('channelcount', 'uint', 16); + this._procField('samplesize', 'uint', 16); + this._procField('pre_defined', 'uint', 16); + this._procField('reserved3', 'uint', 16); + this._procField('samplerate', 'template', 32); + // ESDescriptor fields + this._procField('esds', 'data', -1); +}; + +// ISO/IEC 14496-12:2012 - 8.2.2 Movie Header Box +ISOBox.prototype._boxProcessors['mvhd'] = function() { + this._procFullBox(); + this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('timescale', 'uint', 32); + this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); + this._procField('rate', 'template', 32); + this._procField('volume', 'template', 16); + this._procField('reserved1', 'uint', 16); + this._procFieldArray('reserved2', 2, 'uint', 32); + this._procFieldArray('matrix', 9, 'template', 32); + this._procFieldArray('pre_defined', 6,'uint', 32); + this._procField('next_track_ID', 'uint', 32); +}; + +// ISO/IEC 14496-30:2014 - WebVTT Cue Payload Box. +ISOBox.prototype._boxProcessors['payl'] = function() { + this._procField('cue_text', 'utf8'); +}; + +//ISO/IEC 23001-7:2011 - 8.1 Protection System Specific Header Box +ISOBox.prototype._boxProcessors['pssh'] = function() { + this._procFullBox(); + + this._procFieldArray('SystemID', 16, 'uint', 8); + this._procField('DataSize', 'uint', 32); + this._procFieldArray('Data', this.DataSize, 'uint', 8); +}; +// ISO/IEC 14496-12:2012 - 8.12.5 Scheme Type Box +ISOBox.prototype._boxProcessors['schm'] = function() { + this._procFullBox(); + + this._procField('scheme_type', 'uint', 32); + this._procField('scheme_version', 'uint', 32); + + if (this.flags & 0x000001) { + this._procField('scheme_uri', 'string', -1); + } +}; +// ISO/IEC 14496-12:2012 - 8.6.4.1 sdtp box +ISOBox.prototype._boxProcessors['sdtp'] = function() { + this._procFullBox(); + + var sample_count = -1; + if (this._parsing) { + sample_count = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset)); + } + + this._procFieldArray('sample_dependency_table', sample_count, 'uint', 8); +}; + +// ISO/IEC 14496-12:2012 - 8.16.3 Segment Index Box +ISOBox.prototype._boxProcessors['sidx'] = function() { + this._procFullBox(); + this._procField('reference_ID', 'uint', 32); + this._procField('timescale', 'uint', 32); + this._procField('earliest_presentation_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('first_offset', 'uint', (this.version == 1) ? 64 : 32); + this._procField('reserved', 'uint', 16); + this._procField('reference_count', 'uint', 16); + this._procEntries('references', this.reference_count, function(entry) { + if (!this._parsing) { + entry.reference = (entry.reference_type & 0x00000001) << 31; + entry.reference |= (entry.referenced_size & 0x7FFFFFFF); + entry.sap = (entry.starts_with_SAP & 0x00000001) << 31; + entry.sap |= (entry.SAP_type & 0x00000003) << 28; + entry.sap |= (entry.SAP_delta_time & 0x0FFFFFFF); + } + this._procEntryField(entry, 'reference', 'uint', 32); + this._procEntryField(entry, 'subsegment_duration', 'uint', 32); + this._procEntryField(entry, 'sap', 'uint', 32); + if (this._parsing) { + entry.reference_type = (entry.reference >> 31) & 0x00000001; + entry.referenced_size = entry.reference & 0x7FFFFFFF; + entry.starts_with_SAP = (entry.sap >> 31) & 0x00000001; + entry.SAP_type = (entry.sap >> 28) & 0x00000007; + entry.SAP_delta_time = (entry.sap & 0x0FFFFFFF); + } + }); +}; + +// ISO/IEC 14496-12:2012 - 8.4.5.3 Sound Media Header Box +ISOBox.prototype._boxProcessors['smhd'] = function() { + this._procFullBox(); + this._procField('balance', 'uint', 16); + this._procField('reserved', 'uint', 16); +}; + +// ISO/IEC 14496-12:2012 - 8.16.4 Subsegment Index Box +ISOBox.prototype._boxProcessors['ssix'] = function() { + this._procFullBox(); + this._procField('subsegment_count', 'uint', 32); + this._procEntries('subsegments', this.subsegment_count, function(subsegment) { + this._procEntryField(subsegment, 'ranges_count', 'uint', 32); + this._procSubEntries(subsegment, 'ranges', subsegment.ranges_count, function(range) { + this._procEntryField(range, 'level', 'uint', 8); + this._procEntryField(range, 'range_size', 'uint', 24); + }); + }); +}; + +// ISO/IEC 14496-12:2012 - 8.5.2 Sample Description Box +ISOBox.prototype._boxProcessors['stsd'] = function() { + this._procFullBox(); + this._procField('entry_count', 'uint', 32); + this._procSubBoxes('entries', this.entry_count); +}; + +// ISO/IEC 14496-12:2015 - 8.7.7 Sub-Sample Information Box +ISOBox.prototype._boxProcessors['subs'] = function () { + this._procFullBox(); + this._procField('entry_count', 'uint', 32); + this._procEntries('entries', this.entry_count, function(entry) { + this._procEntryField(entry, 'sample_delta', 'uint', 32); + this._procEntryField(entry, 'subsample_count', 'uint', 16); + this._procSubEntries(entry, 'subsamples', entry.subsample_count, function(subsample) { + this._procEntryField(subsample, 'subsample_size', 'uint', (this.version === 1) ? 32 : 16); + this._procEntryField(subsample, 'subsample_priority', 'uint', 8); + this._procEntryField(subsample, 'discardable', 'uint', 8); + this._procEntryField(subsample, 'codec_specific_parameters', 'uint', 32); + }); + }); +}; + +//ISO/IEC 23001-7:2011 - 8.2 Track Encryption Box +ISOBox.prototype._boxProcessors['tenc'] = function() { + this._procFullBox(); + + this._procField('default_IsEncrypted', 'uint', 24); + this._procField('default_IV_size', 'uint', 8); + this._procFieldArray('default_KID', 16, 'uint', 8); + }; + +// ISO/IEC 14496-12:2012 - 8.8.12 Track Fragmnent Decode Time +ISOBox.prototype._boxProcessors['tfdt'] = function() { + this._procFullBox(); + this._procField('baseMediaDecodeTime', 'uint', (this.version == 1) ? 64 : 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.7 Track Fragment Header Box +ISOBox.prototype._boxProcessors['tfhd'] = function() { + this._procFullBox(); + this._procField('track_ID', 'uint', 32); + if (this.flags & 0x01) this._procField('base_data_offset', 'uint', 64); + if (this.flags & 0x02) this._procField('sample_description_offset', 'uint', 32); + if (this.flags & 0x08) this._procField('default_sample_duration', 'uint', 32); + if (this.flags & 0x10) this._procField('default_sample_size', 'uint', 32); + if (this.flags & 0x20) this._procField('default_sample_flags', 'uint', 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.10 Track Fragment Random Access Box +ISOBox.prototype._boxProcessors['tfra'] = function() { + this._procFullBox(); + this._procField('track_ID', 'uint', 32); + if (!this._parsing) { + this.reserved = 0; + this.reserved |= (this.length_size_of_traf_num & 0x00000030) << 4; + this.reserved |= (this.length_size_of_trun_num & 0x0000000C) << 2; + this.reserved |= (this.length_size_of_sample_num & 0x00000003); + } + this._procField('reserved', 'uint', 32); + if (this._parsing) { + this.length_size_of_traf_num = (this.reserved & 0x00000030) >> 4; + this.length_size_of_trun_num = (this.reserved & 0x0000000C) >> 2; + this.length_size_of_sample_num = (this.reserved & 0x00000003); + } + this._procField('number_of_entry', 'uint', 32); + this._procEntries('entries', this.number_of_entry, function(entry) { + this._procEntryField(entry, 'time', 'uint', (this.version === 1) ? 64 : 32); + this._procEntryField(entry, 'moof_offset', 'uint', (this.version === 1) ? 64 : 32); + this._procEntryField(entry, 'traf_number', 'uint', (this.length_size_of_traf_num + 1) * 8); + this._procEntryField(entry, 'trun_number', 'uint', (this.length_size_of_trun_num + 1) * 8); + this._procEntryField(entry, 'sample_number', 'uint', (this.length_size_of_sample_num + 1) * 8); + }); +}; + +// ISO/IEC 14496-12:2012 - 8.3.2 Track Header Box +ISOBox.prototype._boxProcessors['tkhd'] = function() { + this._procFullBox(); + this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); + this._procField('track_ID', 'uint', 32); + this._procField('reserved1', 'uint', 32); + this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); + this._procFieldArray('reserved2', 2, 'uint', 32); + this._procField('layer', 'uint', 16); + this._procField('alternate_group', 'uint', 16); + this._procField('volume', 'template', 16); + this._procField('reserved3', 'uint', 16); + this._procFieldArray('matrix', 9, 'template', 32); + this._procField('width', 'template', 32); + this._procField('height', 'template', 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.3 Track Extends Box +ISOBox.prototype._boxProcessors['trex'] = function() { + this._procFullBox(); + this._procField('track_ID', 'uint', 32); + this._procField('default_sample_description_index', 'uint', 32); + this._procField('default_sample_duration', 'uint', 32); + this._procField('default_sample_size', 'uint', 32); + this._procField('default_sample_flags', 'uint', 32); +}; + +// ISO/IEC 14496-12:2012 - 8.8.8 Track Run Box +// Note: the 'trun' box has a direct relation to the 'tfhd' box for defaults. +// These defaults are not set explicitly here, but are left to resolve for the user. +ISOBox.prototype._boxProcessors['trun'] = function() { + this._procFullBox(); + this._procField('sample_count', 'uint', 32); + if (this.flags & 0x1) this._procField('data_offset', 'int', 32); + if (this.flags & 0x4) this._procField('first_sample_flags', 'uint', 32); + this._procEntries('samples', this.sample_count, function(sample) { + if (this.flags & 0x100) this._procEntryField(sample, 'sample_duration', 'uint', 32); + if (this.flags & 0x200) this._procEntryField(sample, 'sample_size', 'uint', 32); + if (this.flags & 0x400) this._procEntryField(sample, 'sample_flags', 'uint', 32); + if (this.flags & 0x800) this._procEntryField(sample, 'sample_composition_time_offset', (this.version === 1) ? 'int' : 'uint', 32); + }); +}; + +// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box +ISOBox.prototype._boxProcessors['url '] = ISOBox.prototype._boxProcessors['urn '] = function() { + this._procFullBox(); + if (this.type === 'urn ') { + this._procField('name', 'string', -1); + } + this._procField('location', 'string', -1); +}; + +// ISO/IEC 14496-30:2014 - WebVTT Source Label Box +ISOBox.prototype._boxProcessors['vlab'] = function() { + this._procField('source_label', 'utf8'); +}; + +// ISO/IEC 14496-12:2012 - 8.4.5.2 Video Media Header Box +ISOBox.prototype._boxProcessors['vmhd'] = function() { + this._procFullBox(); + this._procField('graphicsmode', 'uint', 16); + this._procFieldArray('opcolor', 3, 'uint', 16); +}; + +// ISO/IEC 14496-30:2014 - WebVTT Configuration Box +ISOBox.prototype._boxProcessors['vttC'] = function() { + this._procField('config', 'utf8'); +}; + +// ISO/IEC 14496-30:2014 - WebVTT Empty Sample Box +ISOBox.prototype._boxProcessors['vtte'] = function() { + // Nothing should happen here. +}; + +},{}],6:[function(_dereq_,module,exports){ +'use strict'; + +var isArray = Array.isArray; +var keyList = Object.keys; +var hasProp = Object.prototype.hasOwnProperty; + +module.exports = function equal(a, b) { + if (a === b) return true; + + var arrA = isArray(a) + , arrB = isArray(b) + , i + , length + , key; + + if (arrA && arrB) { + length = a.length; + if (length != b.length) return false; + for (i = 0; i < length; i++) + if (!equal(a[i], b[i])) return false; + return true; + } + + if (arrA != arrB) return false; + + var dateA = a instanceof Date + , dateB = b instanceof Date; + if (dateA != dateB) return false; + if (dateA && dateB) return a.getTime() == b.getTime(); + + var regexpA = a instanceof RegExp + , regexpB = b instanceof RegExp; + if (regexpA != regexpB) return false; + if (regexpA && regexpB) return a.toString() == b.toString(); + + if (a instanceof Object && b instanceof Object) { + var keys = keyList(a); + length = keys.length; + + if (length !== keyList(b).length) + return false; + + for (i = 0; i < length; i++) + if (!hasProp.call(b, keys[i])) return false; + + for (i = 0; i < length; i++) { + key = keys[i]; + if (!equal(a[key], b[key])) return false; + } + + return true; + } + + return false; +}; + +},{}],7:[function(_dereq_,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS || + code === PLUS_URL_SAFE) + return 62 // '+' + if (code === SLASH || + code === SLASH_URL_SAFE) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 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 + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],8:[function(_dereq_,module,exports){ + +},{}],9:[function(_dereq_,module,exports){ +(function (global){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = _dereq_(7) +var ieee754 = _dereq_(13) +var isArray = _dereq_(10) + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var rootParent = {} + +/** + * 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. + * + * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property + * on objects. + * + * - 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() + +function typedArraySupport () { + function Bar () {} + try { + var arr = new Uint8Array(1) + arr.foo = function () { return 42 } + arr.constructor = Bar + return arr.foo() === 42 && // typed array instances can be augmented + arr.constructor === Bar && // constructor can be set + 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 +} + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (arg) { + if (!(this instanceof Buffer)) { + // Avoid going through an ArgumentsAdaptorTrampoline in the common case. + if (arguments.length > 1) return new Buffer(arg, arguments[1]) + return new Buffer(arg) + } + + if (!Buffer.TYPED_ARRAY_SUPPORT) { + this.length = 0 + this.parent = undefined + } + + // Common case. + if (typeof arg === 'number') { + return fromNumber(this, arg) + } + + // Slightly less common case. + if (typeof arg === 'string') { + return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') + } + + // Unusual. + return fromObject(this, arg) +} + +function fromNumber (that, length) { + that = allocate(that, length < 0 ? 0 : checked(length) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < length; i++) { + that[i] = 0 + } + } + return that +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' + + // Assumption: byteLength() return value is always < kMaxLength. + var length = byteLength(string, encoding) | 0 + that = allocate(that, length) + + that.write(string, encoding) + return that +} + +function fromObject (that, object) { + if (Buffer.isBuffer(object)) return fromBuffer(that, object) + + if (isArray(object)) return fromArray(that, object) + + if (object == null) { + throw new TypeError('must start with number, buffer, array or string') + } + + if (typeof ArrayBuffer !== 'undefined') { + if (object.buffer instanceof ArrayBuffer) { + return fromTypedArray(that, object) + } + if (object instanceof ArrayBuffer) { + return fromArrayBuffer(that, object) + } + } + + if (object.length) return fromArrayLike(that, object) + + return fromJsonObject(that, object) +} + +function fromBuffer (that, buffer) { + var length = checked(buffer.length) | 0 + that = allocate(that, length) + buffer.copy(that, 0, 0, length) + return that +} + +function fromArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Duplicate of fromArray() to keep fromArray() monomorphic. +function fromTypedArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + // Truncating the elements is probably not what people expect from typed + // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior + // of the old Buffer constructor. + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + array.byteLength + that = Buffer._augment(new Uint8Array(array)) + } else { + // Fallback: Return an object instance of the Buffer class + that = fromTypedArray(that, new Uint8Array(array)) + } + return that +} + +function fromArrayLike (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. +// Returns a zero-length buffer for inputs that don't conform to the spec. +function fromJsonObject (that, object) { + var array + var length = 0 + + if (object.type === 'Buffer' && isArray(object.data)) { + array = object.data + length = checked(array.length) | 0 + } + that = allocate(that, length) + + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array +} else { + // pre-set for values that may exist in the future + Buffer.prototype.length = undefined + Buffer.prototype.parent = undefined +} + +function allocate (that, length) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = Buffer._augment(new Uint8Array(length)) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that.length = length + that._isBuffer = true + } + + var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 + if (fromPool) that.parent = rootParent + + return that +} + +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 (subject, encoding) { + if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) + + var buf = new Buffer(subject, encoding) + delete buf.parent + return buf +} + +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 + + var i = 0 + var len = Math.min(x, y) + while (i < len) { + if (a[i] !== b[i]) break + + ++i + } + + if (i !== len) { + x = a[i] + y = b[i] + } + + 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 'binary': + case 'base64': + case 'raw': + 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 new Buffer(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; i++) { + length += list[i].length + } + } + + var buf = new Buffer(length) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +function byteLength (string, encoding) { + 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 'binary': + // Deprecated + case 'raw': + case 'raws': + return len + case 'utf8': + case 'utf-8': + 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 + + start = start | 0 + end = end === undefined || end === Infinity ? this.length : end | 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + 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 'binary': + return binarySlice(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 + } + } +} + +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.prototype.compare = function compare (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return 0 + return Buffer.compare(this, b) +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset) { + if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff + else if (byteOffset < -0x80000000) byteOffset = -0x80000000 + byteOffset >>= 0 + + if (this.length === 0) return -1 + if (byteOffset >= this.length) return -1 + + // Negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) + + if (typeof val === 'string') { + if (val.length === 0) return -1 // special case: looking for empty string always fails + return String.prototype.indexOf.call(this, val, byteOffset) + } + if (Buffer.isBuffer(val)) { + return arrayIndexOf(this, val, byteOffset) + } + if (typeof val === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { + return Uint8Array.prototype.indexOf.call(this, val, byteOffset) + } + return arrayIndexOf(this, [ val ], byteOffset) + } + + function arrayIndexOf (arr, val, byteOffset) { + var foundIndex = -1 + for (var i = 0; byteOffset + i < arr.length; i++) { + if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex + } else { + foundIndex = -1 + } + } + return -1 + } + + throw new TypeError('val must be string, number or Buffer') +} + +// `get` is deprecated +Buffer.prototype.get = function get (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` is deprecated +Buffer.prototype.set = function set (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +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 Error('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)) throw new Error('Invalid hex string') + 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 binaryWrite (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 { + var swap = encoding + encoding = offset + offset = length | 0 + length = swap + } + + 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 'binary': + return binaryWrite(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 binarySlice (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 = Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + } + + if (newBuf.length) newBuf.parent = this.parent || this + + 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 must be a Buffer instance') + if (value > max || value < min) throw new RangeError('value 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) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 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) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 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 = value < 0 ? 1 : 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + 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 = value < 0 ? 1 : 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + 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 (value > max || value < min) throw new RangeError('value is out of bounds') + 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 { + target._set(this.subarray(start, start + len), targetStart) + } + + return len +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function fill (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new RangeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') + if (end < 0 || end > this.length) throw new RangeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function toArrayBuffer () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function _augment (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array set method before overwriting + arr._set = arr.set + + // deprecated + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.indexOf = BP.indexOf + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUIntLE = BP.readUIntLE + arr.readUIntBE = BP.readUIntBE + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readIntLE = BP.readIntLE + arr.readIntBE = BP.readIntBE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUIntLE = BP.writeUIntLE + arr.writeUIntBE = BP.writeUIntBE + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeIntLE = BP.writeIntLE + arr.writeIntBE = BP.writeIntBE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +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 +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"10":10,"13":13,"7":7}],10:[function(_dereq_,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],11:[function(_dereq_,module,exports){ +(function (Buffer){ +// 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. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":_dereq_(15)}) + +},{"15":15}],12:[function(_dereq_,module,exports){ +// 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 EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],13:[function(_dereq_,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 +} + +},{}],14:[function(_dereq_,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],15:[function(_dereq_,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],16:[function(_dereq_,module,exports){ +(function (process){ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this,_dereq_(17)) + +},{"17":17}],17:[function(_dereq_,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],18:[function(_dereq_,module,exports){ +module.exports = _dereq_(19); + +},{"19":19}],19:[function(_dereq_,module,exports){ +// 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. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = _dereq_(16); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = _dereq_(11); +util.inherits = _dereq_(14); +/**/ + +var Readable = _dereq_(21); +var Writable = _dereq_(23); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"11":11,"14":14,"16":16,"21":21,"23":23}],20:[function(_dereq_,module,exports){ +// 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. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = _dereq_(22); + +/**/ +var util = _dereq_(11); +util.inherits = _dereq_(14); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"11":11,"14":14,"22":22}],21:[function(_dereq_,module,exports){ +(function (process,global){ +// 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. + +'use strict'; + +/**/ + +var pna = _dereq_(16); +/**/ + +module.exports = Readable; + +/**/ +var isArray = _dereq_(27); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = _dereq_(12).EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = _dereq_(26); +/**/ + +/**/ + +var Buffer = _dereq_(33).Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = _dereq_(11); +util.inherits = _dereq_(14); +/**/ + +/**/ +var debugUtil = _dereq_(8); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = _dereq_(24); +var destroyImpl = _dereq_(25); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || _dereq_(19); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = _dereq_(28).StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || _dereq_(19); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = _dereq_(28).StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,_dereq_(17),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"11":11,"12":12,"14":14,"16":16,"17":17,"19":19,"24":24,"25":25,"26":26,"27":27,"28":28,"33":33,"8":8}],22:[function(_dereq_,module,exports){ +// 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. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = _dereq_(19); + +/**/ +var util = _dereq_(11); +util.inherits = _dereq_(14); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"11":11,"14":14,"19":19}],23:[function(_dereq_,module,exports){ +(function (process,global){ +// 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. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = _dereq_(16); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = _dereq_(11); +util.inherits = _dereq_(14); +/**/ + +/**/ +var internalUtil = { + deprecate: _dereq_(36) +}; +/**/ + +/**/ +var Stream = _dereq_(26); +/**/ + +/**/ + +var Buffer = _dereq_(33).Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = _dereq_(25); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || _dereq_(19); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || _dereq_(19); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,_dereq_(17),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"11":11,"14":14,"16":16,"17":17,"19":19,"25":25,"26":26,"33":33,"36":36}],24:[function(_dereq_,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = _dereq_(33).Buffer; +var util = _dereq_(8); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"33":33,"8":8}],25:[function(_dereq_,module,exports){ +'use strict'; + +/**/ + +var pna = _dereq_(16); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"16":16}],26:[function(_dereq_,module,exports){ +module.exports = _dereq_(12).EventEmitter; + +},{"12":12}],27:[function(_dereq_,module,exports){ +arguments[4][10][0].apply(exports,arguments) +},{"10":10}],28:[function(_dereq_,module,exports){ +// 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. + +'use strict'; + +/**/ + +var Buffer = _dereq_(33).Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"33":33}],29:[function(_dereq_,module,exports){ +module.exports = _dereq_(30).PassThrough + +},{"30":30}],30:[function(_dereq_,module,exports){ +exports = module.exports = _dereq_(21); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = _dereq_(23); +exports.Duplex = _dereq_(19); +exports.Transform = _dereq_(22); +exports.PassThrough = _dereq_(20); + +},{"19":19,"20":20,"21":21,"22":22,"23":23}],31:[function(_dereq_,module,exports){ +module.exports = _dereq_(30).Transform + +},{"30":30}],32:[function(_dereq_,module,exports){ +module.exports = _dereq_(23); + +},{"23":23}],33:[function(_dereq_,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = _dereq_(9) +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"9":9}],34:[function(_dereq_,module,exports){ +// 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. + +module.exports = Stream; + +var EE = _dereq_(12).EventEmitter; +var inherits = _dereq_(14); + +inherits(Stream, EE); +Stream.Readable = _dereq_(30); +Stream.Writable = _dereq_(32); +Stream.Duplex = _dereq_(18); +Stream.Transform = _dereq_(31); +Stream.PassThrough = _dereq_(29); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"12":12,"14":14,"18":18,"29":29,"30":30,"31":31,"32":32}],35:[function(_dereq_,module,exports){ +// 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. + +var Buffer = _dereq_(9).Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"9":9}],36:[function(_dereq_,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],37:[function(_dereq_,module,exports){ +/* + * Copyright (c) 2016, Pierre-Anthony Lemieux + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @module imscDoc + */ + +; +(function (imscDoc, sax, imscNames, imscStyles, imscUtils) { + + + /** + * Allows a client to provide callbacks to handle children of the element + * @typedef {Object} MetadataHandler + * @property {?OpenTagCallBack} onOpenTag + * @property {?CloseTagCallBack} onCloseTag + * @property {?TextCallBack} onText + */ + + /** + * Called when the opening tag of an element node is encountered. + * @callback OpenTagCallBack + * @param {string} ns Namespace URI of the element + * @param {string} name Local name of the element + * @param {Object[]} attributes List of attributes, each consisting of a + * `uri`, `name` and `value` + */ + + /** + * Called when the closing tag of an element node is encountered. + * @callback CloseTagCallBack + */ + + /** + * Called when a text node is encountered. + * @callback TextCallBack + * @param {string} contents Contents of the text node + */ + + /** + * Parses an IMSC1 document into an opaque in-memory representation that exposes + * a single method
getMediaTimeEvents()
that returns a list of time + * offsets (in seconds) of the ISD, i.e. the points in time where the visual + * representation of the document change. `metadataHandler` allows the caller to + * be called back when nodes are present in elements. + * + * @param {string} xmlstring XML document + * @param {?module:imscUtils.ErrorHandler} errorHandler Error callback + * @param {?MetadataHandler} metadataHandler Callback for elements + * @returns {Object} Opaque in-memory representation of an IMSC1 document + */ + + imscDoc.fromXML = function (xmlstring, errorHandler, metadataHandler) { + var p = sax.parser(true, {xmlns: true}); + var estack = []; + var xmllangstack = []; + var xmlspacestack = []; + var metadata_depth = 0; + var doc = null; + + p.onclosetag = function (node) { + + if (estack[0] instanceof Styling) { + + /* flatten chained referential styling */ + + for (var sid in estack[0].styles) { + + mergeChainedStyles(estack[0], estack[0].styles[sid], errorHandler); + + } + + } else if (estack[0] instanceof P || estack[0] instanceof Span) { + + /* merge anonymous spans */ + + if (estack[0].contents.length > 1) { + + var cs = [estack[0].contents[0]]; + + var c; + + for (c = 1; c < estack[0].contents.length; c++) { + + if (estack[0].contents[c] instanceof AnonymousSpan && + cs[cs.length - 1] instanceof AnonymousSpan) { + + cs[cs.length - 1].text += estack[0].contents[c].text; + + } else { + + cs.push(estack[0].contents[c]); + + } + + } + + estack[0].contents = cs; + + } + + // remove redundant nested anonymous spans (9.3.3(1)(c)) + + if (estack[0] instanceof Span && + estack[0].contents.length === 1 && + estack[0].contents[0] instanceof AnonymousSpan && + estack[0].text === null) { + + estack[0].text = estack[0].contents[0].text; + delete estack[0].contents; + + } + + } else if (estack[0] instanceof ForeignElement) { + + if (estack[0].node.uri === imscNames.ns_tt && + estack[0].node.local === 'metadata') { + + /* leave the metadata element */ + + metadata_depth--; + + } else if (metadata_depth > 0 && + metadataHandler && + 'onCloseTag' in metadataHandler) { + + /* end of child of metadata element */ + + metadataHandler.onCloseTag(); + + } + + } + + // TODO: delete stylerefs? + + // maintain the xml:space stack + + xmlspacestack.shift(); + + // maintain the xml:lang stack + + xmllangstack.shift(); + + // prepare for the next element + + estack.shift(); + }; + + p.ontext = function (str) { + + if (estack[0] === undefined) { + + /* ignoring text outside of elements */ + + } else if (estack[0] instanceof Span || estack[0] instanceof P) { + + /* create an anonymous span */ + + var s = new AnonymousSpan(); + + s.initFromText(doc, estack[0], str, xmlspacestack[0], errorHandler); + + estack[0].contents.push(s); + + } else if (estack[0] instanceof ForeignElement && + metadata_depth > 0 && + metadataHandler && + 'onText' in metadataHandler) { + + /* text node within a child of metadata element */ + + metadataHandler.onText(str); + + } + + }; + + + p.onopentag = function (node) { + + // maintain the xml:space stack + + var xmlspace = node.attributes["xml:space"]; + + if (xmlspace) { + + xmlspacestack.unshift(xmlspace.value); + + } else { + + if (xmlspacestack.length === 0) { + + xmlspacestack.unshift("default"); + + } else { + + xmlspacestack.unshift(xmlspacestack[0]); + + } + + } + + /* maintain the xml:lang stack */ + + + var xmllang = node.attributes["xml:lang"]; + + if (xmllang) { + + xmllangstack.unshift(xmllang.value); + + } else { + + if (xmllangstack.length === 0) { + + xmllangstack.unshift(""); + + } else { + + xmllangstack.unshift(xmllangstack[0]); + + } + + } + + + /* process the element */ + + if (node.uri === imscNames.ns_tt) { + + if (node.local === 'tt') { + + if (doc !== null) { + + reportFatal("Two elements at (" + this.line + "," + this.column + ")"); + + } + + doc = new TT(); + + doc.initFromNode(node, errorHandler); + + estack.unshift(doc); + + } else if (node.local === 'head') { + + if (!(estack[0] instanceof TT)) { + reportFatal("Parent of element is not at (" + this.line + "," + this.column + ")"); + } + + if (doc.head !== null) { + reportFatal("Second element at (" + this.line + "," + this.column + ")"); + } + + doc.head = new Head(); + + estack.unshift(doc.head); + + } else if (node.local === 'styling') { + + if (!(estack[0] instanceof Head)) { + reportFatal("Parent of element is not at (" + this.line + "," + this.column + ")"); + } + + if (doc.head.styling !== null) { + reportFatal("Second element at (" + this.line + "," + this.column + ")"); + } + + doc.head.styling = new Styling(); + + estack.unshift(doc.head.styling); + + } else if (node.local === 'style') { + + var s; + + if (estack[0] instanceof Styling) { + + s = new Style(); + + s.initFromNode(node, errorHandler); + + /* ignore