25 lines
320 KiB
JavaScript
25 lines
320 KiB
JavaScript
"use strict";
|
|
/*
|
|
* ATTENTION: An "eval-source-map" devtool has been used.
|
|
* This devtool is neither made for production nor for readable output files.
|
|
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
|
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
* or disable the default devtool with "devtool: false".
|
|
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
*/
|
|
exports.id = "vendor-chunks/jsox@1.2.121";
|
|
exports.ids = ["vendor-chunks/jsox@1.2.121"];
|
|
exports.modules = {
|
|
|
|
/***/ "(rsc)/./node_modules/.pnpm/jsox@1.2.121/node_modules/jsox/lib/jsox.mjs":
|
|
/*!************************************************************************!*\
|
|
!*** ./node_modules/.pnpm/jsox@1.2.121/node_modules/jsox/lib/jsox.mjs ***!
|
|
\************************************************************************/
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ JSOX: () => (/* binding */ JSOX)\n/* harmony export */ });\n//\"use strict\";\n// jsox.js\n// JSOX JavaScript Object eXchange. Inherits human features of comments\n// and extended formatting from JSON6; adds macros, big number and date\n// support. See README.md for details.\n//\n// This file is based off of https://github.com/JSON6/ ./lib/json6.js\n// which is based off of https://github.com/d3x0r/sack ./src/netlib/html5.websocket/json6_parser.c\n//\n\n//const util = require('util'); // debug inspect.\n//import util from 'util'; \n\nconst _JSON=JSON; // in case someone does something like JSON=JSOX; we still need a primitive _JSON for internal stringification\nif( \"undefined\" === typeof exports )\n\tvar exports = {};\nconst JSOX = exports || {};\nexports.JSOX = JSOX;\n\nJSOX.version = \"1.2.121\";\n\n//function privateizeEverything() {\n//const _DEBUG_LL = false;\n//const _DEBUG_PARSING = false;\n//const _DEBUG_STRINGIFY = false;\n//const _DEBUG_PARSING_STACK = false;\n//const _DEBUG_PARSING_NUMBERS = false;\n//const _DEBUG_PARSING_DETAILS = false;\n//const _DEBUG_PARSING_CONTEXT = false;\n//const _DEBUG_REFERENCES = false; // this tracks folling context stack when the components have not been completed.\n//const _DEBUG_WHITESPACE = false; \nconst hasBigInt = (typeof BigInt === \"function\");\nconst testNonIdentifierCharacters = false; // maybe an option to enable; references otherwise unused table.\nconst VALUE_UNDEFINED = -1\nconst VALUE_UNSET = 0\nconst VALUE_NULL = 1\nconst VALUE_TRUE = 2\nconst VALUE_FALSE = 3\nconst VALUE_STRING = 4\nconst VALUE_NUMBER = 5\nconst VALUE_OBJECT = 6\nconst VALUE_NEG_NAN = 7\nconst VALUE_NAN = 8\nconst VALUE_NEG_INFINITY = 9\nconst VALUE_INFINITY = 10\n//const VALUE_DATE = 11 // unused yet; this is actuall a subType of VALUE_NUMBER\nconst VALUE_EMPTY = 12 // [,] makes an array with 'empty item'\nconst VALUE_ARRAY = 13 //\n// internally arrayType = -1 is a normal array\n// arrayType = -2 is a reference array, which, which closed is resolved to\n// the specified object.\n// arrayType = -3 is a normal array, that has already had this element pushed.\nconst knownArrayTypeNames = [\"ab\",\"u8\",\"cu8\",\"s8\",\"u16\",\"s16\",\"u32\",\"s32\",\"u64\",\"s64\",\"f32\",\"f64\"];\nlet arrayToJSOX = null;\nlet mapToJSOX = null;\nconst knownArrayTypes = [ArrayBuffer\n ,Uint8Array,Uint8ClampedArray,Int8Array\n ,Uint16Array,Int16Array\n ,Uint32Array,Int32Array\n ,null,null//,Uint64Array,Int64Array\n ,Float32Array,Float64Array];\n// somehow max isn't used... it would be the NEXT available VALUE_XXX value...\n//const VALUE_ARRAY_MAX = VALUE_ARRAY + knownArrayTypes.length + 1; // 1 type is not typed; just an array.\n\nconst WORD_POS_RESET = 0;\nconst WORD_POS_TRUE_1 = 1;\nconst WORD_POS_TRUE_2 = 2;\nconst WORD_POS_TRUE_3 = 3;\nconst WORD_POS_FALSE_1 = 5;\nconst WORD_POS_FALSE_2 = 6;\nconst WORD_POS_FALSE_3 = 7;\nconst WORD_POS_FALSE_4 = 8;\nconst WORD_POS_NULL_1 = 9;\nconst WORD_POS_NULL_2 = 10;\nconst WORD_POS_NULL_3 = 11;\nconst WORD_POS_UNDEFINED_1 = 12;\nconst WORD_POS_UNDEFINED_2 = 13;\nconst WORD_POS_UNDEFINED_3 = 14;\nconst WORD_POS_UNDEFINED_4 = 15;\nconst WORD_POS_UNDEFINED_5 = 16;\nconst WORD_POS_UNDEFINED_6 = 17;\nconst WORD_POS_UNDEFINED_7 = 18;\nconst WORD_POS_UNDEFINED_8 = 19;\nconst WORD_POS_NAN_1 = 20;\nconst WORD_POS_NAN_2 = 21;\nconst WORD_POS_INFINITY_1 = 22;\nconst WORD_POS_INFINITY_2 = 23;\nconst WORD_POS_INFINITY_3 = 24;\nconst WORD_POS_INFINITY_4 = 25;\nconst WORD_POS_INFINITY_5 = 26;\nconst WORD_POS_INFINITY_6 = 27;\nconst WORD_POS_INFINITY_7 = 28;\n\nconst WORD_POS_FIELD = 29;\nconst WORD_POS_AFTER_FIELD = 30;\nconst WORD_POS_END = 31;\nconst WORD_POS_AFTER_FIELD_VALUE = 32;\n//const WORD_POS_BINARY = 32;\n\nconst CONTEXT_UNKNOWN = 0\nconst CONTEXT_IN_ARRAY = 1\nconst CONTEXT_OBJECT_FIELD = 2\nconst CONTEXT_OBJECT_FIELD_VALUE = 3\nconst CONTEXT_CLASS_FIELD = 4\nconst CONTEXT_CLASS_VALUE = 5\nconst CONTEXT_CLASS_FIELD_VALUE = 6\nconst keywords = {\t[\"true\"]:true,[\"false\"]:false,[\"null\"]:null,[\"NaN\"]:NaN,[\"Infinity\"]:Infinity,[\"undefined\"]:undefined }\n\n/*\nExtend Date type with a nanosecond field.\n*/\nclass DateNS extends Date {\n\tconstructor(a,b ) {\n\t\tsuper(a);\n\t\tthis.ns = b||0;\n\t}\t\n}\n\nJSOX.DateNS = DateNS;\n\nconst contexts = [];\nfunction getContext() {\n\tlet ctx = contexts.pop();\n\tif( !ctx )\n\t\tctx = { context : CONTEXT_UNKNOWN\n\t\t , current_proto : null\n\t\t , current_class : null\n\t\t , current_class_field : 0\n\t\t , arrayType : -1\n\t\t , valueType : VALUE_UNSET\n\t\t , elements : null\n\t\t };\n\treturn ctx;\n}\nfunction dropContext(ctx) { \n\tcontexts.push( ctx ) \n}\n\nJSOX.updateContext = function() {\n //if( toProtoTypes.get( Map.prototype ) ) return;\n //console.log( \"Do init protoypes for new context objects...\" );\n //initPrototypes();\n}\n\nconst buffers = [];\nfunction getBuffer() { let buf = buffers.pop(); if( !buf ) buf = { buf:null, n:0 }; else buf.n = 0; return buf; }\nfunction dropBuffer(buf) { buffers.push( buf ); }\n\n/**\n * @param {string} string \n * @returns {string}\n */\nJSOX.escape = function(string) {\n\tlet n;\n\tlet output = '';\n\tif( !string ) return string;\n\tfor( n = 0; n < string.length; n++ ) {\n\t\tif( ( string[n] == '\"' ) || ( string[n] == '\\\\' ) || ( string[n] == '`' )|| ( string[n] == '\\'' )) {\n\t\t\toutput += '\\\\';\n\t\t}\n\t\toutput += string[n];\n\t}\n\treturn output;\n}\n\n\nlet toProtoTypes = new WeakMap();\nlet toObjectTypes = new Map();\nlet fromProtoTypes = new Map();\nlet commonClasses = [];\n\nJSOX.reset = resetJSOX;\n\nfunction resetJSOX() {\n\ttoProtoTypes = new WeakMap();\n\ttoObjectTypes = new Map();\n\tfromProtoTypes = new Map();\n\tcommonClasses = [];\t\n}\n\n/**\n * @param {(value:any)} [cb]\n * @param {(this: unknown, key: string, value: unknown) => any} [reviver] \n * @returns {none}\n*/\nJSOX.begin = function( cb, reviver ) {\n\n\tconst val = { name : null,\t // name of this value (if it's contained in an object)\n\t\t\tvalue_type: VALUE_UNSET, // value from above indiciating the type of this value\n\t\t\tstring : '', // the string value of this value (strings and number types only)\n\t\t\tcontains : null,\n\t\t\tclassName : null,\n\t\t};\n\t\n\tconst pos = { line:1, col:1 };\n\tlet\tn = 0;\n\tlet str;\n\tlet\tlocalFromProtoTypes = new Map();\n\tlet\tword = WORD_POS_RESET,\n\t\tstatus = true,\n\t\tredefineClass = false,\n\t\tnegative = false,\n\t\tresult = null,\n\t\trootObject = null,\n\t\telements = undefined,\n\t\tcontext_stack = {\n\t\t\tfirst : null,\n\t\t\tlast : null,\n\t\t\tsaved : null,\n\t\t\tpush(node) {\n\t\t\t\t//_DEBUG_PARSING_CONTEXT && console.log( \"pushing context:\", node );\n\t\t\t\tlet recover = this.saved;\n\t\t\t\tif( recover ) { this.saved = recover.next; \n\t\t\t\t\trecover.node = node; \n\t\t\t\t\trecover.next = null; \n\t\t\t\t\trecover.prior = this.last; }\n\t\t\t\telse { recover = { node : node, next : null, prior : this.last }; }\n\t\t\t\tif( !this.last ) this.first = recover;\n\t\t\t\telse this.last.next = recover;\n\t\t\t\tthis.last = recover;\n\t\t\t\tthis.length++;\n\t\t\t},\n\t\t\tpop() {\n\t\t\t\tlet result = this.last;\n\t\t\t\t// through normal usage this line can never be used.\n\t\t\t\t//if( !result ) return null;\n\t\t\t\tif( !(this.last = result.prior ) ) this.first = null;\n\t\t\t\tresult.next = this.saved;\n\t\t\t\tif( this.last ) this.last.next = null;\n\t\t\t\tif( !result.next ) result.first = null;\n\t\t\t\tthis.saved = result;\n\t\t\t\tthis.length--;\n\t\t\t\t//_DEBUG_PARSING_CONTEXT && console.log( \"popping context:\", result.node );\n\t\t\t\treturn result.node;\n\t\t\t},\n\t\t\tlength : 0,\n\t\t\t/*dump() { // //_DEBUG_CONTEXT_STACK\n\t\t\t\tconsole.log( \"STACK LENGTH:\", this.length );\n\t\t\t\tlet cur= this.first;\n\t\t\t\tlet level = 0;\n\t\t\t\twhile( cur ) {\n\t\t\t\t\tconsole.log( \"Context:\", level, cur.node );\n\t\t\t\t\tlevel++;\n\t\t\t\t\tcur = cur.next;\n\t\t\t\t}\n\t\t\t}*/\n\t\t},\n\t\tclasses = [], // class templates that have been defined.\n\t\tprotoTypes = {},\n\t\tcurrent_proto = null, // the current class being defined or being referenced.\n\t\tcurrent_class = null, // the current class being defined or being referenced.\n\t\tcurrent_class_field = 0,\n\t\tarrayType = -1, // the current class being defined or being referenced.\n\t\tparse_context = CONTEXT_UNKNOWN,\n\t\tcomment = 0,\n\t\tfromHex = false,\n\t\tdecimal = false,\n\t\texponent = false,\n\t\texponent_sign = false,\n\t\texponent_digit = false,\n\t\tinQueue = {\n\t\t\tfirst : null,\n\t\t\tlast : null,\n\t\t\tsaved : null,\n\t\t\tpush(node) {\n\t\t\t\tlet recover = this.saved;\n\t\t\t\tif( recover ) { this.saved = recover.next; recover.node = node; recover.next = null; recover.prior = this.last; }\n\t\t\t\telse { recover = { node : node, next : null, prior : this.last }; }\n\t\t\t\tif( !this.last ) this.first = recover;\n\t\t\t\telse this.last.next = recover;\n\t\t\t\tthis.last = recover;\n\t\t\t},\n\t\t\tshift() {\n\t\t\t\tlet result = this.first;\n\t\t\t\tif( !result ) return null;\n\t\t\t\tif( !(this.first = result.next ) ) this.last = null;\n\t\t\t\tresult.next = this.saved; this.saved = result;\n\t\t\t\treturn result.node;\n\t\t\t},\n\t\t\tunshift(node) {\n\t\t\t\tlet recover = this.saved;\n\t\t\t\t// this is always true in this usage.\n\t\t\t\t//if( recover ) { \n\t\t\t\t\tthis.saved = recover.next; recover.node = node; recover.next = this.first; recover.prior = null; \n\t\t\t\t//}\n\t\t\t\t//else { recover = { node : node, next : this.first, prior : null }; }\n\t\t\t\tif( !this.first ) this.last = recover;\n\t\t\t\tthis.first = recover;\n\t\t\t}\n\t\t},\n\t\tgatheringStringFirstChar = null,\n\t\tgatheringString = false,\n\t\tgatheringNumber = false,\n\t\tstringEscape = false,\n\t\tcr_escaped = false,\n\t\tunicodeWide = false,\n\t\tstringUnicode = false,\n\t\tstringHex = false,\n\t\thex_char = 0,\n\t\thex_char_len = 0,\n\t\tcompleted = false,\n\t\tdate_format = false,\n\t\tisBigInt = false\n\t\t;\n\n\tfunction throwEndError( leader ) {\n\t\tthrow new Error( `${leader} at ${n} [${pos.line}:${pos.col}]`);\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Define a class that can be used to deserialize objects of this type.\n\t\t * @param {string} prototypeName \n\t\t * @param {type} o \n\t\t * @param {(any)=>any} f \n\t\t */\n\t\tfromJSOX( prototypeName, o, f ) {\n\t\t\tif( localFromProtoTypes.get(prototypeName) ) throw new Error( \"Existing fromJSOX has been registered for prototype\" );\n\t\t\tfunction privateProto() { }\n\t\t\tif( !o ) o = privateProto;\n\t\t\tif( o && !(\"constructor\" in o )){\n\t\t\t\tthrow new Error( \"Please pass a prototype like thing...\");\n\t\t\t}\n\t\t\tlocalFromProtoTypes.set( prototypeName, { protoCon:o.prototype.constructor, cb:f } );\n\t\t},\n\t\tregisterFromJSOX( prototypeName, o/*, f*/ ) {\n\t\t\tthrow new Error( \"registerFromJSOX is deprecated, please update to use fromJSOX instead:\" + prototypeName + o.toString() );\n\t\t},\n\t\tfinalError() {\n\t\t\tif( comment !== 0 ) { // most of the time everything's good.\n\t\t\t\tif( comment === 1 ) throwEndError( \"Comment began at end of document\" );\n\t\t\t\tif( comment === 2 ) /*console.log( \"Warning: '//' comment without end of line ended document\" )*/;\n\t\t\t\tif( comment === 3 ) throwEndError( \"Open comment '/*' is missing close at end of document\" );\n\t\t\t\tif( comment === 4 ) throwEndError( \"Incomplete '/* *' close at end of document\" );\n\t\t\t}\n\t\t\tif( gatheringString ) throwEndError( \"Incomplete string\" );\n\t\t},\n\t\tvalue() {\n\t\t\tthis.finalError();\n\t\t\tlet r = result;\n\t\t\tresult = undefined;\n\t\t\treturn r;\n\t\t},\n\t\t/**\n\t\t * Reset the parser to a blank state.\n\t\t */\n\t\treset() {\n\t\t\tword = WORD_POS_RESET;\n\t\t\tstatus = true;\n\t\t\tif( inQueue.last ) inQueue.last.next = inQueue.save;\n\t\t\tinQueue.save = inQueue.first;\n\t\t\tinQueue.first = inQueue.last = null;\n\t\t\tif( context_stack.last ) context_stack.last.next = context_stack.save;\n\t\t\tcontext_stack.length = 0;\n\t\t\tcontext_stack.save = inQueue.first;\n\t\t\tcontext_stack.first = context_stack.last = null;//= [];\n\t\t\telements = undefined;\n\t\t\tparse_context = CONTEXT_UNKNOWN;\n\t\t\tclasses = [];\n\t\t\tprotoTypes = {};\n\t\t\tcurrent_proto = null;\n\t\t\tcurrent_class = null;\n\t\t\tcurrent_class_field = 0;\n\t\t\tval.value_type = VALUE_UNSET;\n\t\t\tval.name = null;\n\t\t\tval.string = '';\n\t\t\tval.className = null;\n\t\t\tpos.line = 1;\n\t\t\tpos.col = 1;\n\t\t\tnegative = false;\n\t\t\tcomment = 0;\n\t\t\tcompleted = false;\n\t\t\tgatheringString = false;\n\t\t\tstringEscape = false; // string stringEscape intro\n\t\t\tcr_escaped = false; // carraige return escaped\n\t\t\tdate_format = false;\n\t\t\t//stringUnicode = false; // reading \\u\n\t\t\t//unicodeWide = false; // reading \\u{} in string\n\t\t\t//stringHex = false; // reading \\x in string\n\t\t},\n\t\tusePrototype(className,protoType ) { protoTypes[className] = protoType; },\n\t\t/**\n\t\t * Add input to the parser to get parsed.\n\t\t * @param {string} msg \n\t\t */\n\t\twrite(msg) {\n\t\t\tlet retcode;\n\t\t\tif (typeof msg !== \"string\" && typeof msg !== \"undefined\") msg = String(msg);\n\t\t\tif( !status ) throw new Error( \"Parser is still in an error state, please reset before resuming\" );\n\t\t\tfor( retcode = this._write(msg,false); retcode > 0; retcode = this._write() ) {\n\t\t\t\tif( typeof reviver === 'function' ) (function walk(holder, key) {\n\t\t\t\t\tlet k, v, value = holder[key];\n\t\t\t\t\tif (value && typeof value === 'object') {\n\t\t\t\t\t\tfor (k in value) {\n\t\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\t\tv = walk(value, k);\n\t\t\t\t\t\t\t\tif (v !== undefined) {\n\t\t\t\t\t\t\t\t\tvalue[k] = v;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdelete value[k];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn reviver.call(holder, key, value);\n\t\t\t\t}({'': result}, ''));\n\t\t\t\tresult = cb( result );\n\n\t\t\t\tif( retcode < 2 )\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Parse a string and return the result.\n\t\t * @param {string} msg\n\t\t * @param {(key:string,value:any)=>any} [reviver]\n\t\t * @returns {any}\n\t\t */\n\t\tparse(msg,reviver) {\n\t\t\tif (typeof msg !== \"string\") msg = String(msg);\n\t\t\tthis.reset();\n\t\t\tconst writeResult = this._write( msg, true );\n\t\t\tif( writeResult > 0 ) {\n\t\t\t\tif( writeResult > 1 ){\n\t\t\t\t\t// probably a carriage return.\n\t\t\t\t\t//console.log( \"Extra data at end of message\");\n\t\t\t\t}\n\t\t\t\tlet result = this.value();\n\t\t\t\tif( ( \"undefined\" === typeof result ) && writeResult > 1 ){\n\t\t\t\t\tthrow new Error( \"Pending value could not complete\");\n\t\t\t\t}\n\t \n\t\t\t\tresult = typeof reviver === 'function' ? (function walk(holder, key) {\n\t\t\t\t\tlet k, v, value = holder[key];\n\t\t\t\t\tif (value && typeof value === 'object') {\n\t\t\t\t\t\tfor (k in value) {\n\t\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\t\tv = walk(value, k);\n\t\t\t\t\t\t\t\tif (v !== undefined) {\n\t\t\t\t\t\t\t\t\tvalue[k] = v;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdelete value[k];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn reviver.call(holder, key, value);\n\t\t\t\t}({'': result}, '')) : result;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tthis.finalError();\n\t\t\treturn undefined;\n\n\t\t\t\n\t\t\treturn this.write(msg );\n\t\t},\n\t\t_write(msg,complete_at_end) {\n\t\t\tlet cInt;\n\t\t\tlet input;\n\t\t\tlet buf;\n\t\t\tlet retval = 0;\n\t\t\tfunction throwError( leader, c ) {\n\t\t\t\tthrow new Error( `${leader} '${String.fromCodePoint( c )}' unexpected at ${n} (near '${buf.substr(n>4?(n-4):0,n>4?3:(n-1))}[${String.fromCodePoint( c )}]${buf.substr(n, 10)}') [${pos.line}:${pos.col}]`);\n\t\t\t}\n\n\t\t\tfunction RESET_VAL() {\n\t\t\t\tval.value_type = VALUE_UNSET;\n\t\t\t\tval.string = '';\n\t\t\t\tval.contains = null;\n\t\t\t\t//val.className = null;\n\t\t\t}\n\n\t\t\tfunction convertValue() {\n\t\t\t\tlet fp = null;\n\t\t\t\t//_DEBUG_PARSING && console.log( \"CONVERT VAL:\", val );\n\t\t\t\tswitch( val.value_type ){\n\t\t\t\tcase VALUE_NUMBER:\n\t\t\t\t\t//1502678337047\n\t\t\t\t\tif( ( ( val.string.length > 13 ) || ( val.string.length == 13 && val[0]>'2' ) )\n\t\t\t\t\t && !date_format && !exponent_digit && !exponent_sign && !decimal ) {\n\t\t\t\t\t\tisBigInt = true;\n\t\t\t\t\t}\n\t\t\t\t\tif( isBigInt ) { if( hasBigInt ) return BigInt(val.string); else throw new Error( \"no builtin BigInt()\", 0 ) }\n\t\t\t\t\tif( date_format ) { \n\t\t\t\t\t\tconst r = val.string.match(/\\.(\\d\\d\\d\\d*)/ );\n\t\t\t\t\t\tconst frac = ( r )?( r )[1]:null;\n\t\t\t\t\t\tif( !frac || (frac.length < 4) ) {\n\t\t\t\t\t\t\tconst r = new Date( val.string ); \n\t\t\t\t\t\t\tif(isNaN(r.getTime())) throwError( \"Bad Date format\", cInt ); return r; \n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlet ns = frac.substr( 3 );\n\t\t\t\t\t\t\twhile( ns.length < 6 ) ns = ns+'0';\n\t\t\t\t\t\t\tconst r = new DateNS( val.string, Number(ns ) ); \n\t\t\t\t\t\t\tif(isNaN(r.getTime())) throwError( \"Bad DateNS format\" + r+r.getTime(), cInt ); return r; \n\t\t\t\t\t\t}\n\t\t\t\t\t\t//const r = new Date( val.string ); if(isNaN(r.getTime())) throwError( \"Bad number format\", cInt ); return r; \n\t\t\t\t\t}\n\t\t\t\t\treturn (negative?-1:1) * Number( val.string );\n\t\t\t\tcase VALUE_STRING:\n\t\t\t\t\tif( val.className ) {\n\t\t\t\t\t\tfp = localFromProtoTypes.get( val.className );\n\t\t\t\t\t\tif( !fp )\n\t\t\t\t\t\t\tfp = fromProtoTypes.get( val.className );\n\t\t\t\t\t\tif( fp && fp.cb ) {\n\t\t\t\t\t\t\tval.className = null;\n\t\t\t\t\t\t\treturn fp.cb.call( val.string );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// '[object Object]' throws this error.\n\t\t\t\t\t\t\tthrow new Error( \"Double string error, no constructor for: new \" + val.className + \"(\"+val.string+\")\" )\n\t\t\t\t\t\t}\t\n\t\t\t\t\t}\n\t\t\t\t\treturn val.string;\n\t\t\t\tcase VALUE_TRUE:\n\t\t\t\t\treturn true;\n\t\t\t\tcase VALUE_FALSE:\n\t\t\t\t\treturn false;\n\t\t\t\tcase VALUE_NEG_NAN:\n\t\t\t\t\treturn -NaN;\n\t\t\t\tcase VALUE_NAN:\n\t\t\t\t\treturn NaN;\n\t\t\t\tcase VALUE_NEG_INFINITY:\n\t\t\t\t\treturn -Infinity;\n\t\t\t\tcase VALUE_INFINITY:\n\t\t\t\t\treturn Infinity;\n\t\t\t\tcase VALUE_NULL:\n\t\t\t\t\treturn null;\n\t\t\t\tcase VALUE_UNDEFINED:\n\t\t\t\t\treturn undefined;\n\t\t\t\tcase VALUE_EMPTY:\n\t\t\t\t\treturn undefined;\n\t\t\t\tcase VALUE_OBJECT:\n\t\t\t\t\tif( val.className ) { \n\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"class reviver\" );\n\t\t\t\t\t\tfp = localFromProtoTypes.get( val.className );\n\t\t\t\t\t\tif( !fp )\n\t\t\t\t\t\t\tfp = fromProtoTypes.get( val.className );\n\t\t\t\t\t\tval.className = null;\n\t\t\t\t\t\tif( fp && fp.cb ) return val.contains = fp.cb.call( val.contains ); \n\t\t\t\t\t}\n\t\t\t\t\treturn val.contains;\n\t\t\t\tcase VALUE_ARRAY:\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"Array conversion:\", arrayType, val.contains );\n\t\t\t\t\tif( arrayType >= 0 ) {\n\t\t\t\t\t\tlet ab;\n\t\t\t\t\t\tif( val.contains.length )\n\t\t\t\t\t\t\tab = DecodeBase64( val.contains[0] )\n\t\t\t\t\t\telse ab = DecodeBase64( val.string );\n\t\t\t\t\t\tif( arrayType === 0 ) {\n\t\t\t\t\t\t\tarrayType = -1;\n\t\t\t\t\t\t\treturn ab;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst newab = new knownArrayTypes[arrayType]( ab );\n\t\t\t\t\t\t\tarrayType = -1;\n\t\t\t\t\t\t\treturn newab;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if( arrayType === -2 ) {\n\t\t\t\t\t\tlet obj = rootObject;\n\t\t\t\t\t\t//let ctx = context_stack.first;\n\t\t\t\t\t\tlet lvl;\n\t\t\t\t\t\t//console.log( \"Resolving Reference...\", context_stack.length );\n\t\t\t\t\t\t//console.log( \"--elements and array\", elements );\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst pathlen = val.contains.length;\n\t\t\t\t\t\tfor( lvl = 0; lvl < pathlen; lvl++ ) {\n\t\t\t\t\t\t\tconst idx = val.contains[lvl];\n\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Looking up idx:\", idx, \"of\", val.contains, \"in\", obj );\n\t\t\t\t\t\t\tlet nextObj = obj[idx];\n\n\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Resolve path:\", lvl, idx,\"in\", obj, context_stack.length, val.contains.toString() );\n\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"NEXT OBJECT:\", nextObj );\n\t\t\t\t\t\t\tif( !nextObj ) {\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlet ctx = context_stack.first;\n\t\t\t\t\t\t\t\t\tlet p = 0;\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING_CONTEXT && context_stack.dump();\n\t\t\t\t\t\t\t\t\twhile( ctx && p < pathlen && p < context_stack.length ) {\n\t\t\t\t\t\t\t\t\t\tconst thisKey = val.contains[p];\n\t\t\t\t\t\t\t\t\t\tif( !ctx.next || thisKey !== ctx.next.node.name ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak; // can't follow context stack any further.... \n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Checking context:\", obj, \"p=\",p, \"key=\",thisKey, \"ctx(and .next)=\",util.inspect(ctx));\n\t\t\t\t\t\t\t\t\t\t//console.dir(ctx, { depth: null })\n\t\t\t\t\t\t\t\t\t\tif( ctx.next ) {\n\t\t\t\t\t\t\t\t\t\t\tif( \"number\" === typeof thisKey ) {\n\t\t\t\t\t\t\t\t\t\t\t\tconst actualObject = ctx.next.node.elements;\n\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Number in index... tracing stack...\", obj, actualObject, ctx && ctx.next && ctx.next.next && ctx.next.next.node );\n\n\t\t\t\t\t\t\t\t\t\t\t\tif( actualObject && thisKey >= actualObject.length ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"AT \", p, actualObject.length, val.contains.length );\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( p === (context_stack.length-1) ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconsole.log( \"This is actually at the current object so use that\", p, val.contains, elements );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = elements;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tp++;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx = ctx.next;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"is next... \", thisKey, actualObject.length )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif( ctx.next.next && thisKey === actualObject.length ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"is next... \")\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = ctx.next.next.node.elements;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx = ctx.next;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tp++;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tobj = nextObj;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"FAILING HERE\", ctx.next, ctx.next.next, elements, obj );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Nothing after, so this is just THIS?\" );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = elements;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tp++; // make sure to exit.\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//obj = next\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"field AT index\", p,\"of\", val.contains.length );\n\t\t\t\t\t\t\t\t\t\t\t\tif( thisKey !== ctx.next.node.name ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Expect:\", thisKey, ctx.next.node.name, ctx.next.node.elements );\n\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = ( ctx.next.node.elements[thisKey] );\n\t\t\t\t\t\t\t\t\t\t\t\t\t//throw new Error( \"Unexpected path-context relationship\" );\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tlvl = p;\n\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Updating next object(NEW) to\", ctx.next.node, elements, thisKey)\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( ctx.next.next )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = ctx.next.next.node.elements;\n\t\t\t\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Nothing after, so this is just THIS?\" );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnextObj = elements;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"using named element from\", ctx.next.node.elements, \"=\", nextObj )\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t//if( //_DEBUG_REFERENCES ) {\n\t\t\t\t\t\t\t\t\t\t\t//\tconst a = ctx.next.node.elements;\n\t\t\t\t\t\t\t\t\t\t\t//\tconsole.log( \"Stack Dump:\"\n\t\t\t\t\t\t\t\t\t\t\t//\t\t, a?a.length:a\n\t\t\t\t\t\t\t\t\t\t\t//\t\t, ctx.next.node.name\n\t\t\t\t\t\t\t\t\t\t\t//\t\t, thisKey\n\t\t\t\t\t\t\t\t\t\t\t//\t\t);\n\t\t\t\t\t\t\t\t\t\t\t//}\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tnextObj = nextObj[thisKey];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Doing next context??\", p, context_stack.length, val.contains.length );\n\t\t\t\t\t\t\t\t\t\tctx = ctx.next;\n\t\t\t\t\t\t\t\t\t\tp++;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"Done with context stack...level\", lvl, \"p\", p );\n\t\t\t\t\t\t\t\t\tif( p < pathlen )\n\t\t\t\t\t\t\t\t\t\tlvl = p-1;\n\t\t\t\t\t\t\t\t\telse lvl = p;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t//_DEBUG_REFERENCES && console.log( \"End of processing level:\", lvl );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( (\"object\" === typeof nextObj ) && !nextObj ) {\n\t\t\t\t\t\t\t\tthrow new Error( \"Path did not resolve properly:\" + val.contains + \" at \" + idx + '(' + lvl + ')' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tobj = nextObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"Resulting resolved object:\", obj );\n\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"SETTING MODE TO -3 (resolved -2)\" );\n\t\t\t\t\t\tarrayType = -3;\n\t\t\t\t\t\treturn obj;\n\t\t\t\t\t}\n\t\t\t\t\tif( val.className ) { \n\t\t\t\t\t\tfp = localFromProtoTypes.get( val.className );\n\t\t\t\t\t\tif( !fp )\n\t\t\t\t\t\t\tfp = fromProtoTypes.get( val.className );\n\t\t\t\t\t\tval.className = null; \n\t\t\t\t\t\tif( fp && fp.cb ) return fp.cb.call( val.contains ); \n\t\t\t\t\t}\n\t\t\t\t\treturn val.contains;\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.log( \"Unhandled value conversion.\", val );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction arrayPush() {\n\t\t\t\t//_DEBUG_PARSING && console.log( \"PUSH TO ARRAY:\", val );\n\t\t\t\tif( arrayType == -3 ) {\n\t\t\t\t\t//_DEBUG_PARSING && console.log(\" Array type -3?\", val.value_type, elements );\n\t\t\t\t\tif( val.value_type === VALUE_OBJECT ) {\n\t\t\t\t\t\telements.push( val.contains );\n\t\t\t\t\t}\n\t\t\t\t\tarrayType = -1; // next one should be allowed?\n\t\t\t\t\treturn;\n\t\t\t\t} //else\n\t\t\t\t//\tconsole.log( \"Finally a push that's not already pushed!\", );\n\t\t\t\tswitch( val.value_type ){\n\t\t\t\tcase VALUE_EMPTY:\n\t\t\t\t\telements.push( undefined );\n\t\t\t\t\tdelete elements[elements.length-1];\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\telements.push( convertValue() );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tRESET_VAL();\n\t\t\t}\n\n\t\t\tfunction objectPush() {\n\t\t\t\tif( arrayType === -3 && val.value_type === VALUE_ARRAY ) {\n\t\t\t\t\t//console.log( \"Array has already been set in object.\" );\n\t\t\t\t\t//elements[val.name] = val.contains;\n\t\t\t\t\tRESET_VAL();\n\t\t\t\t\tarrayType = -1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif( val.value_type === VALUE_EMPTY ) return;\n\t\t\t\tif( !val.name && current_class ) {\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"A Stepping current class field:\", current_class_field, val.name );\n\t\t\t\t\tval.name = current_class.fields[current_class_field++];\n\t\t\t\t}\n\t\t\t\tlet value = convertValue();\n\n\t\t\t\tif( current_proto && current_proto.protoDef && current_proto.protoDef.cb ) {\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"SOMETHING SHOULD AHVE BEEN REPLACED HERE??\", current_proto );\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"(need to do fromprototoypes here) object:\", val, value );\n\t\t\t\t\tvalue = current_proto.protoDef.cb.call( elements, val.name, value );\n\t\t\t\t\tif( value ) elements[val.name] = value;\n\t\t\t\t\t//elements = new current_proto.protoCon( elements );\n\t\t\t\t}else {\n\t\t\t\t //_DEBUG_PARSING_DETAILS && console.log( \"Default no special class reviver\", val.name, value );\n\t\t\t\t\telements[val.name] = value;\n\t\t\t\t}\n\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"Updated value:\", current_class_field, val.name, elements[val.name] );\n\t\t\t\n\t\t\t\t//_DEBUG_PARSING && console.log( \"+++ Added object field:\", val.name, elements, elements[val.name], rootObject );\n\t\t\t\tRESET_VAL();\n\t\t\t}\n\n\t\t\tfunction recoverIdent(cInt) {\n\t\t\t\t//_DEBUG_PARSING&&console.log( \"Recover Ident char:\", cInt, val, String.fromCodePoint(cInt), \"word:\", word );\n\t\t\t\tif( word !== WORD_POS_RESET ) {\n\t\t\t\t\tif( negative ) { \n\t\t\t\t\t\t//val.string += \"-\"; negative = false; \n\t\t\t\t\t\tthrowError( \"Negative outside of quotes, being converted to a string (would lose count of leading '-' characters)\", cInt );\n\t\t\t\t\t}\n\t\t\t\t\tswitch( word ) {\n\t\t\t\t\tcase WORD_POS_END:\n\t\t\t\t\t\tswitch( val.value_type ) {\n\t\t\t\t\t\tcase VALUE_TRUE: val.string += \"true\"; break\n\t\t\t\t\t\tcase VALUE_FALSE: val.string += \"false\"; break\n\t\t\t\t\t\tcase VALUE_NULL: val.string += \"null\"; break\n\t\t\t\t\t\tcase VALUE_INFINITY: val.string += \"Infinity\"; break\n\t\t\t\t\t\tcase VALUE_NEG_INFINITY: val.string += \"-Infinity\"; throwError( \"Negative outside of quotes, being converted to a string\", cInt ); break\n\t\t\t\t\t\tcase VALUE_NAN: val.string += \"NaN\"; break\n\t\t\t\t\t\tcase VALUE_NEG_NAN: val.string += \"-NaN\"; throwError( \"Negative outside of quotes, being converted to a string\", cInt ); break\n\t\t\t\t\t\tcase VALUE_UNDEFINED: val.string += \"undefined\"; break\n\t\t\t\t\t\tcase VALUE_STRING: break;\n\t\t\t\t\t\tcase VALUE_UNSET: break;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.log( \"Value of type \" + val.value_type + \" is not restored...\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WORD_POS_TRUE_1 : val.string += \"t\"; break;\n\t\t\t\t\tcase WORD_POS_TRUE_2 : val.string += \"tr\"; break;\n\t\t\t\t\tcase WORD_POS_TRUE_3 : val.string += \"tru\"; break;\n\t\t\t\t\tcase WORD_POS_FALSE_1 : val.string += \"f\"; break;\n\t\t\t\t\tcase WORD_POS_FALSE_2 : val.string += \"fa\"; break;\n\t\t\t\t\tcase WORD_POS_FALSE_3 : val.string += \"fal\"; break;\n\t\t\t\t\tcase WORD_POS_FALSE_4 : val.string += \"fals\"; break;\n\t\t\t\t\tcase WORD_POS_NULL_1 : val.string += \"n\"; break;\n\t\t\t\t\tcase WORD_POS_NULL_2 : val.string += \"nu\"; break;\n\t\t\t\t\tcase WORD_POS_NULL_3 : val.string += \"nul\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_1 : val.string += \"u\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_2 : val.string += \"un\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_3 : val.string += \"und\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_4 : val.string += \"unde\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_5 : val.string += \"undef\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_6 : val.string += \"undefi\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_7 : val.string += \"undefin\"; break;\n\t\t\t\t\tcase WORD_POS_UNDEFINED_8 : val.string += \"undefine\"; break;\n\t\t\t\t\tcase WORD_POS_NAN_1 : val.string += \"N\"; break;\n\t\t\t\t\tcase WORD_POS_NAN_2 : val.string += \"Na\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_1 : val.string += \"I\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_2 : val.string += \"In\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_3 : val.string += \"Inf\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_4 : val.string += \"Infi\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_5 : val.string += \"Infin\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_6 : val.string += \"Infini\"; break;\n\t\t\t\t\tcase WORD_POS_INFINITY_7 : val.string += \"Infinit\"; break;\n\t\t\t\t\tcase WORD_POS_RESET : break;\n\t\t\t\t\tcase WORD_POS_FIELD : break;\n\t\t\t\t\tcase WORD_POS_AFTER_FIELD:\n\t\t\t\t\t //throwError( \"String-keyword recovery fail (after whitespace)\", cInt);\n\t\t\t\t\t break;\n\t\t\t\t\tcase WORD_POS_AFTER_FIELD_VALUE:\n\t\t\t\t\t throwError( \"String-keyword recovery fail (after whitespace)\", cInt );\n\t\t\t\t\t break;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t//console.log( \"Word context: \" + word + \" unhandled\" );\n\t\t\t\t\t}\n\t\t\t\t\tval.value_type = VALUE_STRING;\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tif( word < WORD_POS_FIELD)\n\t\t\t\t\t word = WORD_POS_END;\n\t\t\t\t} else {\n\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t//if( val.value_type === VALUE_UNSET && val.string.length )\n\t\t\t\t\t\tval.value_type = VALUE_STRING\n\t\t\t\t}\n\t\t\t\tif( cInt == 123/*'{'*/ )\n\t\t\t\t\topenObject();\n\t\t\t\telse if( cInt == 91/*'['*/ )\n\t\t\t\t\topenArray();\n\t\t\t\telse if( cInt == 44/*','*/ ) {\n\t\t\t\t\t// comma separates the string, it gets consumed.\n\t\t\t\t} else {\n\t\t\t\t\t// ignore white space.\n\t\t\t\t\tif( cInt == 32/*' '*/ || cInt == 13 || cInt == 10 || cInt == 9 || cInt == 0xFEFF || cInt == 0x2028 || cInt == 0x2029 ) {\n\t\t\t\t\t\t//_DEBUG_WHITESPACE && console.log( \"IGNORE WHITESPACE\" );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( cInt == 44/*','*/ || cInt == 125/*'}'*/ || cInt == 93/*']'*/ || cInt == 58/*':'*/ )\n\t\t\t\t\t\tthrowError( \"Invalid character near identifier\", cInt );\n\t\t\t\t\telse //if( typeof cInt === \"number\")\n\t\t\t\t\t\tval.string += str;\n\t\t\t\t}\n\t\t\t\t//console.log( \"VAL STRING IS:\", val.string, str );\n\t\t\t}\n\n\t\t\t// gather a string from an input stream; start_c is the opening quote to find a related close quote.\n\t\t\tfunction gatherString( start_c ) {\n\t\t\t\tlet retval = 0;\n\t\t\t\twhile( retval == 0 && ( n < buf.length ) ) {\n\t\t\t\t\tstr = buf.charAt(n);\n\t\t\t\t\tlet cInt = buf.codePointAt(n++);\n\t\t\t\t\tif( cInt >= 0x10000 ) { str += buf.charAt(n); n++; }\n\t\t\t\t\t//console.log( \"gathering....\", stringEscape, str, cInt, unicodeWide, stringHex, stringUnicode, hex_char_len );\n\t\t\t\t\tpos.col++;\n\t\t\t\t\tif( cInt == start_c ) { //( cInt == 34/*'\"'*/ ) || ( cInt == 39/*'\\''*/ ) || ( cInt == 96/*'`'*/ ) )\n\t\t\t\t\t\tif( stringEscape ) { \n\t\t\t\t\t\t\tif( stringHex )\n\t\t\t\t\t\t\t\tthrowError( \"Incomplete hexidecimal sequence\", cInt );\n\t\t\t\t\t\t\telse if( stringUnicode )\n\t\t\t\t\t\t\t\tthrowError( \"Incomplete long unicode sequence\", cInt );\n\t\t\t\t\t\t\telse if( unicodeWide )\n\t\t\t\t\t\t\t\tthrowError( \"Incomplete unicode sequence\", cInt );\n\t\t\t\t\t\t\tif( cr_escaped ) {\n\t\t\t\t\t\t\t\tcr_escaped = false;\n\t\t\t\t\t\t\t\tretval = 1; // complete string, escaped \\r\n\t\t\t\t\t\t\t} else val.string += str;\n\t\t\t\t\t\t\tstringEscape = false; }\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t// quote matches, and is not processing an escape sequence.\n\t\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telse if( stringEscape ) {\n\t\t\t\t\t\tif( unicodeWide ) {\n\t\t\t\t\t\t\tif( cInt == 125/*'}'*/ ) {\n\t\t\t\t\t\t\t\tval.string += String.fromCodePoint( hex_char );\n\t\t\t\t\t\t\t\tunicodeWide = false;\n\t\t\t\t\t\t\t\tstringUnicode = false;\n\t\t\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\thex_char *= 16;\n\t\t\t\t\t\t\tif( cInt >= 48/*'0'*/ && cInt <= 57/*'9'*/ ) hex_char += cInt - 0x30;\n\t\t\t\t\t\t\telse if( cInt >= 65/*'A'*/ && cInt <= 70/*'F'*/ ) hex_char += ( cInt - 65 ) + 10;\n\t\t\t\t\t\t\telse if( cInt >= 97/*'a'*/ && cInt <= 102/*'f'*/ ) hex_char += ( cInt - 97 ) + 10;\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tthrowError( \"(escaped character, parsing hex of \\\\u)\", cInt );\n\t\t\t\t\t\t\t\tretval = -1;\n\t\t\t\t\t\t\t\tunicodeWide = false;\n\t\t\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( stringHex || stringUnicode ) {\n\t\t\t\t\t\t\tif( hex_char_len === 0 && cInt === 123/*'{'*/ ) {\n\t\t\t\t\t\t\t\tunicodeWide = true;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( hex_char_len < 2 || ( stringUnicode && hex_char_len < 4 ) ) {\n\t\t\t\t\t\t\t\thex_char *= 16;\n\t\t\t\t\t\t\t\tif( cInt >= 48/*'0'*/ && cInt <= 57/*'9'*/ ) hex_char += cInt - 0x30;\n\t\t\t\t\t\t\t\telse if( cInt >= 65/*'A'*/ && cInt <= 70/*'F'*/ ) hex_char += ( cInt - 65 ) + 10;\n\t\t\t\t\t\t\t\telse if( cInt >= 97/*'a'*/ && cInt <= 102/*'f'*/ ) hex_char += ( cInt - 97 ) + 10;\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tthrowError( stringUnicode?\"(escaped character, parsing hex of \\\\u)\":\"(escaped character, parsing hex of \\\\x)\", cInt );\n\t\t\t\t\t\t\t\t\tretval = -1;\n\t\t\t\t\t\t\t\t\tstringHex = false;\n\t\t\t\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\thex_char_len++;\n\t\t\t\t\t\t\t\tif( stringUnicode ) {\n\t\t\t\t\t\t\t\t\tif( hex_char_len == 4 ) {\n\t\t\t\t\t\t\t\t\t\tval.string += String.fromCodePoint( hex_char );\n\t\t\t\t\t\t\t\t\t\tstringUnicode = false;\n\t\t\t\t\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( hex_char_len == 2 ) {\n\t\t\t\t\t\t\t\t\tval.string += String.fromCodePoint( hex_char );\n\t\t\t\t\t\t\t\t\tstringHex = false;\n\t\t\t\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tswitch( cInt ) {\n\t\t\t\t\t\tcase 13/*'\\r'*/:\n\t\t\t\t\t\t\tcr_escaped = true;\n\t\t\t\t\t\t\tpos.col = 1;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tcase 0x2028: // LS (Line separator)\n\t\t\t\t\t\tcase 0x2029: // PS (paragraph separate)\n\t\t\t\t\t\t\tpos.col = 1;\n\t\t\t\t\t\t\t// falls through\n\t\t\t\t\t\tcase 10/*'\\n'*/:\n\t\t\t\t\t\t\tif( !cr_escaped ) { // \\\\ \\n\n\t\t\t\t\t\t\t\tpos.col = 1;\n\t\t\t\t\t\t\t} else { // \\\\ \\r \\n\n\t\t\t\t\t\t\t\tcr_escaped = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpos.line++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 116/*'t'*/:\n\t\t\t\t\t\t\tval.string += '\\t';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 98/*'b'*/:\n\t\t\t\t\t\t\tval.string += '\\b';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 110/*'n'*/:\n\t\t\t\t\t\t\tval.string += '\\n';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 114/*'r'*/:\n\t\t\t\t\t\t\tval.string += '\\r';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 102/*'f'*/:\n\t\t\t\t\t\t\tval.string += '\\f';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 118/*'v'*/:\n\t\t\t\t\t\t\tval.string += '\\v';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 48/*'0'*/: \n\t\t\t\t\t\t\tval.string += '\\0';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 120/*'x'*/:\n\t\t\t\t\t\t\tstringHex = true;\n\t\t\t\t\t\t\thex_char_len = 0;\n\t\t\t\t\t\t\thex_char = 0;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tcase 117/*'u'*/:\n\t\t\t\t\t\t\tstringUnicode = true;\n\t\t\t\t\t\t\thex_char_len = 0;\n\t\t\t\t\t\t\thex_char = 0;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t//case 47/*'/'*/:\n\t\t\t\t\t\t//case 92/*'\\\\'*/:\n\t\t\t\t\t\t//case 34/*'\"'*/:\n\t\t\t\t\t\t//case 39/*\"'\"*/:\n\t\t\t\t\t\t//case 96/*'`'*/:\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//console.log( \"other...\" );\n\t\t\t\t\t\tstringEscape = false;\n\t\t\t\t\t}\n\t\t\t\t\telse if( cInt === 92/*'\\\\'*/ ) {\n\t\t\t\t\t\tif( stringEscape ) {\n\t\t\t\t\t\t\tval.string += '\\\\';\n\t\t\t\t\t\t\tstringEscape = false\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tstringEscape = true;\n\t\t\t\t\t\t\thex_char = 0;\n\t\t\t\t\t\t\thex_char_len = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse { /* any other character */\n\t\t\t\t\t\tif( cr_escaped ) {\n\t\t\t\t\t\t\t// \\\\ \\r <any char>\n\t\t\t\t\t\t\tcr_escaped = false;\n\t\t\t\t\t\t\tpos.line++;\n\t\t\t\t\t\t\tpos.col = 2; // this character is pos 1; and increment to be after it.\n\t\t\t\t\t\t}\n\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn retval;\n\t\t\t}\n\n\t\t\t// gather a number from the input stream.\n\t\t\tfunction collectNumber() {\n\t\t\t\tlet _n;\n\t\t\t\twhile( (_n = n) < buf.length ) {\n\t\t\t\t\tstr = buf.charAt(_n);\n\t\t\t\t\tlet cInt = buf.codePointAt(n++);\n\t\t\t\t\tif( cInt >= 256 ) { \n\t\t\t\t\t\t\tpos.col -= n - _n;\n\t\t\t\t\t\t\tn = _n; // put character back in queue to process.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//_DEBUG_PARSING_NUMBERS && console.log( \"in getting number:\", n, cInt, String.fromCodePoint(cInt) );\n\t\t\t\t\t\tif( cInt == 95 /*_*/ )\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tpos.col++;\n\t\t\t\t\t\t// leading zeros should be forbidden.\n\t\t\t\t\t\tif( cInt >= 48/*'0'*/ && cInt <= 57/*'9'*/ ) {\n\t\t\t\t\t\t\tif( exponent ) {\n\t\t\t\t\t\t\t\texponent_digit = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t} else if( cInt == 45/*'-'*/ || cInt == 43/*'+'*/ ) {\n\t\t\t\t\t\t\tif( val.string.length == 0 || ( exponent && !exponent_sign && !exponent_digit ) ) {\n\t\t\t\t\t\t\t\tif( cInt == 45/*'-'*/ && !exponent ) negative = !negative;\n\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\texponent_sign = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif( negative ) { val.string = '-' + val.string; negative = false; }\n\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\tdate_format = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( cInt == 78/*'N'*/ ) {\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) {\n\t\t\t\t\t\t\t\tgatheringNumber = false;\n\t\t\t\t\t\t\t\tword = WORD_POS_NAN_1;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if( cInt == 73/*'I'*/ ) {\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) {\n\t\t\t\t\t\t\t\tgatheringNumber = false;\n\t\t\t\t\t\t\t\tword = WORD_POS_INFINITY_1;\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if( cInt == 58/*':'*/ && date_format ) {\n\t\t\t\t\t\t\tif( negative ) { val.string = '-' + val.string; negative = false; }\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\tdate_format = true;\n\t\t\t\t\t\t} else if( cInt == 84/*'T'*/ && date_format ) {\n\t\t\t\t\t\t\tif( negative ) { val.string = '-' + val.string; negative = false; }\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\tdate_format = true;\n\t\t\t\t\t\t} else if( cInt == 90/*'Z'*/ && date_format ) {\n\t\t\t\t\t\t\tif( negative ) { val.string = '-' + val.string; negative = false; }\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\tdate_format = true;\n\t\t\t\t\t\t} else if( cInt == 46/*'.'*/ ) {\n\t\t\t\t\t\t\tif( !decimal && !fromHex && !exponent ) {\n\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\tdecimal = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( cInt == 110/*'n'*/ ) {\n\t\t\t\t\t\t\tisBigInt = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if( fromHex && ( ( ( cInt >= 95/*'a'*/ ) && ( cInt <= 102/*'f'*/ ) ) ||\n\t\t\t\t\t\t ( ( cInt >= 65/*'A'*/ ) && ( cInt <= 70/*'F'*/ ) ) ) ) {\n\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t} else if( cInt == 120/*'x'*/ || cInt == 98/*'b'*/ || cInt == 111/*'o'*/\n\t\t\t\t\t\t\t\t|| cInt == 88/*'X'*/ || cInt == 66/*'B'*/ || cInt == 79/*'O'*/ ) {\n\t\t\t\t\t\t\t// hex conversion.\n\t\t\t\t\t\t\tif( !fromHex && val.string == '0' ) {\n\t\t\t\t\t\t\t\tfromHex = true;\n\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( ( cInt == 101/*'e'*/ ) || ( cInt == 69/*'E'*/ ) ) {\n\t\t\t\t\t\t\tif( !exponent ) {\n\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\texponent = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif( cInt == 32/*' '*/ || cInt == 13 || cInt == 10 || cInt == 9 || cInt == 47/*'/'*/ || cInt == 35/*'#'*/\n\t\t\t\t\t\t\t || cInt == 44/*','*/ || cInt == 125/*'}'*/ || cInt == 93/*']'*/\n\t\t\t\t\t\t\t || cInt == 123/*'{'*/ || cInt == 91/*'['*/ || cInt == 34/*'\"'*/ || cInt == 39/*'''*/ || cInt == 96/*'`'*/\n\t\t\t\t\t\t\t || cInt == 58/*':'*/ ) {\n\t\t\t\t\t\t\t\tpos.col -= n - _n;\n\t\t\t\t\t\t\t\tn = _n; // put character back in queue to process.\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( complete_at_end ) {\n\t\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\t\tthrowError( \"fault while parsing number;\", cInt );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif( (!complete_at_end) && n == buf.length ) {\n\t\t\t\t\tgatheringNumber = true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tgatheringNumber = false;\n\t\t\t\t\tval.value_type = VALUE_NUMBER;\n\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// begin parsing an object type\n\t\t\tfunction openObject() {\n\t\t\t\tlet nextMode = CONTEXT_OBJECT_FIELD;\n\t\t\t\tlet cls = null;\n\t\t\t\tlet tmpobj = {};\n\t\t\t\t//_DEBUG_PARSING && console.log( \"opening object:\", val.string, val.value_type, word, parse_context );\n\t\t\t\tif( word > WORD_POS_RESET && word < WORD_POS_FIELD )\n\t\t\t\t\trecoverIdent( 123 /* '{' */ );\n\t\t\t\tlet protoDef;\n\t\t\t\tprotoDef = getProto(); // lookup classname using val.string and get protodef(if any)\n\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\tif( word == WORD_POS_FIELD /*|| word == WORD_POS_AFTER_FIELD*/ \n\t\t\t\t\t || word == WORD_POS_END\n\t\t\t\t\t && ( protoDef || val.string.length ) ) {\n\t\t\t\t\t\t\tif( protoDef && protoDef.protoDef && protoDef.protoDef.protoCon ) {\n\t\t\t\t\t\t\t\ttmpobj = new protoDef.protoDef.protoCon();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tif( !protoDef || !protoDef.protoDef && val.string ) // class creation is redundant...\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcls = classes.find( cls=>cls.name===val.string );\n\t\t\t\t\t\t\t//console.log( \"Probably creating the Macro-Tag here?\", cls )\n\t\t\t\t\t\t\tif( !cls ) {\n\t\t\t\t\t\t\t\t/* eslint-disable no-inner-declarations */\n\t\t\t\t\t\t\t\tfunction privateProto() {} \n\t\t\t\t\t\t\t\t// this just uses the tmpobj {} container to store the values collected for this class...\n\t\t\t\t\t\t\t\t// this does not generate the instance of the class.\n\t\t\t\t\t\t\t\t// if this tag type is also a prototype, use that prototype, else create a unique proto\n\t\t\t\t\t\t\t\t// for this tagged class type.\n\t\t\t\t\t\t\t\tclasses.push( cls = { name : val.string\n\t\t\t\t\t\t\t\t, protoCon: (protoDef && protoDef.protoDef && protoDef.protoDef.protoCon) || privateProto.constructor\n\t\t\t\t\t\t\t\t , fields : [] } );\n\t\t\t\t\t\t\t\t nextMode = CONTEXT_CLASS_FIELD;\n\t\t\t\t\t\t\t} else if( redefineClass ) {\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"redefine class...\" );\n\t\t\t\t\t\t\t\t// redefine this class\n\t\t\t\t\t\t\t\tcls.fields.length = 0;\n\t\t\t\t\t\t\t\tnextMode = CONTEXT_CLASS_FIELD;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"found existing class, using it....\");\n\t\t\t\t\t\t\t\ttmpobj = new cls.protoCon();\n\t\t\t\t\t\t\t\t//tmpobj = Object.assign( tmpobj, cls.protoObject );\n\t\t\t\t\t\t\t\t//Object.setPrototypeOf( tmpobj, Object.getPrototypeOf( cls.protoObject ) );\n\t\t\t\t\t\t\t\tnextMode = CONTEXT_CLASS_VALUE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tredefineClass = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcurrent_class = cls\n\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tword = WORD_POS_FIELD;\n\t\t\t\t\t}\n\t\t\t\t} else if( word == WORD_POS_FIELD /*|| word == WORD_POS_AFTER_FIELD*/ \n\t\t\t\t\t\t|| parse_context === CONTEXT_IN_ARRAY \n\t\t\t\t\t\t|| parse_context === CONTEXT_OBJECT_FIELD_VALUE \n\t\t\t\t\t\t|| parse_context == CONTEXT_CLASS_VALUE ) {\n\t\t\t\t\tif( word != WORD_POS_RESET || val.value_type == VALUE_STRING ) {\n\t\t\t\t\t\tif( protoDef && protoDef.protoDef ) {\n\t\t\t\t\t\t\t// need to collect the object,\n\t\t\t\t\t\t\ttmpobj = new protoDef.protoDef.protoCon();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// look for a class type (shorthand) to recover.\n\t\t\t\t\t\t\tcls = classes.find( cls=>cls.name === val.string );\n\t\t\t\t\t\t\tif( !cls )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t/* eslint-disable no-inner-declarations */\n\t\t\t\t\t\t\t function privateProto(){}\n\t\t\t\t\t\t\t\t//sconsole.log( \"privateProto has no proto?\", privateProto.prototype.constructor.name );\n\t\t\t\t\t\t\t\tlocalFromProtoTypes.set( val.string,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ protoCon:privateProto.prototype.constructor\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, cb: null }\n\t\t\t\t\t\t\t\t\t\t\t\t\t );\n\t\t\t\t\t\t\t\ttmpobj = new privateProto();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tnextMode = CONTEXT_CLASS_VALUE;\n\t\t\t\t\t\t\t\ttmpobj = {};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//nextMode = CONTEXT_CLASS_VALUE;\n\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t}\n\t\t\t\t} else if( ( parse_context == CONTEXT_OBJECT_FIELD && word == WORD_POS_RESET ) ) {\n\t\t\t\t\tthrowError( \"fault while parsing; getting field name unexpected \", cInt );\n\t\t\t\t\tstatus = false;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// common code to push into next context\n\t\t\t\tlet old_context = getContext();\n\t\t\t\t//_DEBUG_PARSING && console.log( \"Begin a new object; previously pushed into elements; but wait until trailing comma or close previously \", val.value_type, val.className );\n\n\t\t\t\tval.value_type = VALUE_OBJECT;\n\t\t\t\tif( parse_context === CONTEXT_UNKNOWN ){\n\t\t\t\t\telements = tmpobj;\n\t\t\t\t} else if( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\tif( arrayType == -1 ) {\n\t\t\t\t\t\t// this is pushed later... \n\t\t\t\t\t\t//console.log( \"PUSHING OPEN OBJECT INTO EXISTING ARRAY - THIS SHOULD BE RE-SET?\", JSOX.stringify(context_stack.first.node) );\n\t\t\t\t\t\t//elements.push( tmpobj );\n\t\t\t\t\t}\n\t\t\t\t\tval.name = elements.length;\n\t\t\t\t\t//else if( //_DEBUG_PARSING && arrayType !== -3 )\n\t\t\t\t\t//\tconsole.log( \"This is an invalid parsing state, typed array with sub-object elements\" );\n\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD_VALUE || parse_context == CONTEXT_CLASS_VALUE ) {\n\t\t\t\t\tif( !val.name && current_class ){\n\t\t\t\t\t\tval.name = current_class.fields[current_class_field++];\n\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"B Stepping current class field:\", val, current_class_field, val.name );\n\t\t\t\t\t}\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"Setting element:\", val.name, tmpobj );\n\t\t\t\t\telements[val.name] = tmpobj;\n\t\t\t\t}\n\n\t\t\t\told_context.context = parse_context;\n\t\t\t\told_context.elements = elements;\n\t\t\t\t//old_context.element_array = element_array;\n\t\t\t\told_context.name = val.name;\n\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"pushing val.name:\", val.name, arrayType );\n\t\t\t\told_context.current_proto = current_proto;\n\t\t\t\told_context.current_class = current_class;\n\t\t\t\told_context.current_class_field = current_class_field;\n\t\t\t\told_context.valueType = val.value_type;\n\t\t\t\told_context.arrayType = arrayType; // pop that we don't want to have this value re-pushed.\n\t\t\t\told_context.className = val.className;\n\t\t\t\t//arrayType = -3; // this doesn't matter, it's an object state, and a new array will reset to -1\n\t\t\t\tval.className = null;\n\t\t\t\tval.name = null;\n\t\t\t\tcurrent_proto = protoDef;\n\t\t\t\tcurrent_class = cls;\n\t\t\t\t//console.log( \"Setting current class:\", current_class.name );\n\t\t\t\tcurrent_class_field = 0;\n\t\t\t\telements = tmpobj;\n\t\t\t\tif( !rootObject ) rootObject = elements;\n\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"push context (open object): \", context_stack.length, \" new mode:\", nextMode );\n\t\t\t\tcontext_stack.push( old_context );\n\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"RESET OBJECT FIELD\", old_context, context_stack );\n\t\t\t\tRESET_VAL();\n\t\t\t\tparse_context = nextMode;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tfunction openArray() {\n\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"openArray()...\" );\n\t\t\t\tif( word > WORD_POS_RESET && word < WORD_POS_FIELD )\n\t\t\t\t\trecoverIdent( 91 );\n\n\t\t\t\tif( word == WORD_POS_END && val.string.length ) {\n\t\t\t\t\t//_DEBUG_PARSING && console.log( \"recover arrayType:\", arrayType, val.string );\n\t\t\t\t\tlet typeIndex = knownArrayTypeNames.findIndex( type=>(type === val.string) );\n\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\tif( typeIndex >= 0 ) {\n\t\t\t\t\t\tarrayType = typeIndex;\n\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\tval.string = null;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif( val.string === \"ref\" ) {\n\t\t\t\t\t\t\tval.className = null;\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"This will be a reference recovery for key:\", val );\n\t\t\t\t\t\t\tarrayType = -2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif( localFromProtoTypes.get( val.string ) ) {\n\t\t\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\telse if( fromProtoTypes.get( val.string ) ) {\n\t\t\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t\tthrowError( `Unknown type '${val.string}' specified for array`, cInt );\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \" !!!!!A Set Classname:\", val.className );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD || word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD ) {\n\t\t\t\t\tthrowError( \"Fault while parsing; while getting field name unexpected\", cInt );\n\t\t\t\t\tstatus = false;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tlet old_context = getContext();\n\t\t\t\t\t//_DEBUG_PARSING && console.log( \"Begin a new array; previously pushed into elements; but wait until trailing comma or close previously \", val.value_type );\n\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"Opening array:\", val, parse_context );\n\t\t\t\t\tval.value_type = VALUE_ARRAY;\n\t\t\t\t\tlet tmparr = [];\n\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN )\n\t\t\t\t\t\telements = tmparr;\n\t\t\t\t\telse if( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\t\tif( arrayType == -1 ){\n\t\t\t\t\t\t\t//console.log( \"Pushing new opening array into existing array already RE-SET\" );\n\t\t\t\t\t\t\telements.push( tmparr );\n\t\t\t\t\t\t} //else if( //_DEBUG_PARSING && arrayType !== -3 )\n\t\t\t\t\t\tval.name = elements.length;\n\t\t\t\t\t\t//\tconsole.log( \"This is an invalid parsing state, typed array with sub-array elements\" );\n\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD_VALUE ) {\n\t\t\t\t\t\tif( !val.name ) {\n\t\t\t\t\t\t\tconsole.log( \"This says it's resolved.......\" );\n\t\t\t\t\t\t\tarrayType = -3;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( current_proto && current_proto.protoDef ) {\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"SOMETHING SHOULD HAVE BEEN REPLACED HERE??\", current_proto );\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"(need to do fromprototoypes here) object:\", val, value );\n\t\t\t\t\t\t\tif( current_proto.protoDef.cb ){\n\t\t\t\t\t\t\t\tconst newarr = current_proto.protoDef.cb.call( elements, val.name, tmparr );\n\t\t\t\t\t\t\t\tif( newarr !== undefined ) tmparr = elements[val.name] = newarr;\n\t\t\t\t\t\t\t\t//else console.log( \"Warning: Received undefined for an array; keeping original array, not setting field\" );\n\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\telements[val.name] = tmparr;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\telements[val.name] = tmparr;\n\t\t\t\t\t}\n\t\t\t\t\told_context.context = parse_context;\n\t\t\t\t\told_context.elements = elements;\n\t\t\t\t\t//old_context.element_array = element_array;\n\t\t\t\t\told_context.name = val.name;\n\t\t\t\t\told_context.current_proto = current_proto;\n\t\t\t\t\told_context.current_class = current_class;\n\t\t\t\t\told_context.current_class_field = current_class_field;\n\t\t\t\t\t// already pushed?\n\t\t\t\t\told_context.valueType = val.value_type;\n\t\t\t\t\told_context.arrayType = (arrayType==-1)?-3:arrayType; // pop that we don't want to have this value re-pushed.\n\t\t\t\t\told_context.className = val.className;\n\t\t\t\t\tarrayType = -1;\n\t\t\t\t\tval.className = null;\n\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \" !!!!!B Clear Classname:\", old_context, val.className, old_context.className, old_context.name );\n\t\t\t\t\tval.name = null;\n\t\t\t\t\tcurrent_proto = null;\n\t\t\t\t\tcurrent_class = null;\n\t\t\t\t\tcurrent_class_field = 0;\n\t\t\t\t\t//element_array = tmparr;\n\t\t\t\t\telements = tmparr;\n\t\t\t\t\tif( !rootObject ) rootObject = tmparr;\n\t\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"push context (open array): \", context_stack.length );\n\t\t\t\t\tcontext_stack.push( old_context );\n\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"RESET ARRAY FIELD\", old_context, context_stack );\n\n\t\t\t\t\tRESET_VAL();\n\t\t\t\t\tparse_context = CONTEXT_IN_ARRAY;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tfunction getProto() {\n\t\t\t\tconst result = {protoDef:null,cls:null};\n\t\t\t\tif( ( result.protoDef = localFromProtoTypes.get( val.string ) ) ) {\n\t\t\t\t\tif( !val.className ){\n\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\tval.string = null;\n\t\t\t\t\t}\n\t\t\t\t\t// need to collect the object, \n\t\t\t\t}\n\t\t\t\telse if( ( result.protoDef = fromProtoTypes.get( val.string ) ) ) {\n\t\t\t\t\tif( !val.className ){\n\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\tval.string = null;\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\tif( val.string )\n\t\t\t\t{\n\t\t\t\t\tresult.cls = classes.find( cls=>cls.name === val.string );\n\t\t\t\t\tif( !result.protoDef && !result.cls ) {\n\t\t\t\t\t // this will creaet a class def with a new proto to cover when we don't KNOW.\n\t\t\t\t\t //throwError( \"Referenced class \" + val.string + \" has not been defined\", cInt );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn (result.protoDef||result.cls)?result:null;\n\t\t\t}\n\n\t\t\tif( !status )\n\t\t\t\treturn -1;\n\n\t\t\tif( msg && msg.length ) {\n\t\t\t\tinput = getBuffer();\n\t\t\t\tinput.buf = msg;\n\t\t\t\tinQueue.push( input );\n\t\t\t} else {\n\t\t\t\tif( gatheringNumber ) {\n\t\t\t\t\t//console.log( \"Force completed.\")\n\t\t\t\t\tgatheringNumber = false;\n\t\t\t\t\tval.value_type = VALUE_NUMBER;\n\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t}\n\t\t\t\t\tretval = 1; // if returning buffers, then obviously there's more in this one.\n\t\t\t\t}\n\t\t\t\tif( parse_context !== CONTEXT_UNKNOWN )\n\t\t\t\t\tthrowError( \"Unclosed object at end of stream.\", cInt );\n\t\t\t}\n\n\t\t\twhile( status && ( input = inQueue.shift() ) ) {\n\t\t\t\tn = input.n;\n\t\t\t\tbuf = input.buf;\n\t\t\t\tif( gatheringString ) {\n\t\t\t\t\tlet string_status = gatherString( gatheringStringFirstChar );\n\t\t\t\t\tif( string_status < 0 )\n\t\t\t\t\t\tstatus = false;\n\t\t\t\t\telse if( string_status > 0 ) {\n\t\t\t\t\t\tgatheringString = false;\n\t\t\t\t\t\tif( status ) val.value_type = VALUE_STRING;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif( gatheringNumber ) {\n\t\t\t\t\tcollectNumber();\n\t\t\t\t}\n\n\t\t\t\twhile( !completed && status && ( n < buf.length ) ) {\n\t\t\t\t\tstr = buf.charAt(n);\n\t\t\t\t\tcInt = buf.codePointAt(n++);\n\t\t\t\t\tif( cInt >= 0x10000 ) { str += buf.charAt(n); n++; }\n\t\t\t\t\t//_DEBUG_PARSING && console.log( \"parsing at \", cInt, str );\n\t\t\t\t\t//_DEBUG_LL && console.log( \"processing: \", cInt, n, str, pos, comment, parse_context, word );\n\t\t\t\t\tpos.col++;\n\t\t\t\t\tif( comment ) {\n\t\t\t\t\t\tif( comment == 1 ) {\n\t\t\t\t\t\t\tif( cInt == 42/*'*'*/ ) comment = 3;\n\t\t\t\t\t\t\telse if( cInt != 47/*'/'*/ ) return throwError( \"fault while parsing;\", cInt );\n\t\t\t\t\t\t\telse comment = 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( comment == 2 ) {\n\t\t\t\t\t\t\tif( cInt == 10/*'\\n'*/ || cInt == 13/*'\\r'*/ ) comment = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( comment == 3 ) {\n\t\t\t\t\t\t\tif( cInt == 42/*'*'*/ ) comment = 4;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tif( cInt == 47/*'/'*/ ) comment = 0;\n\t\t\t\t\t\t\telse comment = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tswitch( cInt ) {\n\t\t\t\t\tcase 35/*'#'*/:\n\t\t\t\t\t\tcomment = 2; // pretend this is the second slash.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 47/*'/'*/:\n\t\t\t\t\t\tcomment = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 123/*'{'*/:\n\t\t\t\t\t\topenObject();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 91/*'['*/:\n\t\t\t\t\t\topenArray();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 58/*':'*/:\n\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"colon received...\")\n\t\t\t\t\t\tif( parse_context == CONTEXT_CLASS_VALUE ) {\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\tval.name = val.string;\n\t\t\t\t\t\t\tval.string = '';\n\t\t\t\t\t\t\tval.value_type = VALUE_UNSET;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD\n\t\t\t\t\t\t\t|| parse_context == CONTEXT_CLASS_FIELD ) {\n\t\t\t\t\t\t\tif( parse_context == CONTEXT_CLASS_FIELD ) {\n\t\t\t\t\t\t\t\tif( !Object.keys( elements).length ) {\n\t\t\t\t\t\t\t\t\t console.log( \"This is a full object, not a class def...\", val.className );\n\t\t\t\t\t\t\t\tconst privateProto = ()=>{} \n\t\t\t\t\t\t\t\tlocalFromProtoTypes.set( context_stack.last.node.current_class.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ protoCon:privateProto.prototype.constructor\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t, cb: null }\n\t\t\t\t\t\t\t\t\t\t\t\t\t );\n\t\t\t\t\t\t\t\telements = new privateProto();\n\t\t\t\t\t\t\t\tparse_context = CONTEXT_OBJECT_FIELD_VALUE\n\t\t\t\t\t\t\t\tval.name = val.string;\n\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\tval.string = ''\n\t\t\t\t\t\t\t\tval.value_type = VALUE_UNSET;\n\t\t\t\t\t\t\t\tconsole.log( \"don't do default;s do a revive...\" );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif( word != WORD_POS_RESET\n\t\t\t\t\t\t\t\t && word != WORD_POS_END\n\t\t\t\t\t\t\t\t && word != WORD_POS_FIELD\n\t\t\t\t\t\t\t\t && word != WORD_POS_AFTER_FIELD ) {\n\t\t\t\t\t\t\t\t\trecoverIdent( 32 );\n\t\t\t\t\t\t\t\t\t// allow starting a new word\n\t\t\t\t\t\t\t\t\t//status = false;\n\t\t\t\t\t\t\t\t\t//throwError( `fault while parsing; unquoted keyword used as object field name (state:${word})`, cInt );\n\t\t\t\t\t\t\t\t\t//break;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\tval.name = val.string;\n\t\t\t\t\t\t\t\tval.string = '';\n\t\t\t\t\t\t\t\tparse_context = (parse_context===CONTEXT_OBJECT_FIELD)?CONTEXT_OBJECT_FIELD_VALUE:CONTEXT_CLASS_FIELD_VALUE;\n\t\t\t\t\t\t\t\tval.value_type = VALUE_UNSET;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( parse_context == CONTEXT_UNKNOWN ){\n\t\t\t\t\t\t\tconsole.log( \"Override colon found, allow class redefinition\", parse_context );\n\t\t\t\t\t\t\tredefineClass = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif( parse_context == CONTEXT_IN_ARRAY )\n\t\t\t\t\t\t\t\tthrowError( \"(in array, got colon out of string):parsing fault;\", cInt );\n\t\t\t\t\t\t\telse if( parse_context == CONTEXT_OBJECT_FIELD_VALUE ){\n\t\t\t\t\t\t\t\tthrowError( \"String unexpected\", cInt );\n\t\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t\tthrowError( \"(outside any object, got colon out of string):parsing fault;\", cInt );\n\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 125/*'}'*/:\n\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"close bracket context:\", word, parse_context, val.value_type, val.string );\n\t\t\t\t\t\tif( word == WORD_POS_END ) {\n\t\t\t\t\t\t\t// allow starting a new word\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// coming back after pushing an array or sub-object will reset the contxt to FIELD, so an end with a field should still push value.\n\t\t\t\t\t\tif( parse_context == CONTEXT_CLASS_FIELD ) {\n\t\t\t\t\t\t\tif( current_class ) {\n\t\t\t\t\t\t\t\t// allow blank comma at end to not be a field\n\t\t\t\t\t\t\t\tif(val.string) { current_class.fields.push( val.string ); }\n\n\t\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\t\tlet old_context = context_stack.pop();\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"close object:\", old_context, context_stack );\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"object pop stack (close obj)\", context_stack.length, old_context );\n\t\t\t\t\t\t\t\tparse_context = CONTEXT_UNKNOWN; // this will restore as IN_ARRAY or OBJECT_FIELD\n\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\tval.name = old_context.name;\n\t\t\t\t\t\t\t\telements = old_context.elements;\n\t\t\t\t\t\t\t\t//element_array = old_context.element_array;\n\t\t\t\t\t\t\t\tcurrent_class = old_context.current_class;\n\t\t\t\t\t\t\t\tcurrent_class_field = old_context.current_class_field;\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"A Pop old class field counter:\", current_class_field, val.name );\n\t\t\t\t\t\t\t\tarrayType = old_context.arrayType;\n\t\t\t\t\t\t\t\tval.value_type = old_context.valueType;\n\t\t\t\t\t\t\t\tval.className = old_context.className;\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \" !!!!!C Pop Classname:\", val.className );\n\t\t\t\t\t\t\t\trootObject = null;\n\n\t\t\t\t\t\t\t\tdropContext( old_context );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrowError( \"State error; gathering class fields, and lost the class\", cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( ( parse_context == CONTEXT_OBJECT_FIELD ) || ( parse_context == CONTEXT_CLASS_VALUE ) ) {\n\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\tif( current_class ) {\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"C Stepping current class field:\", current_class_field, val.name, arrayType );\n\t\t\t\t\t\t\t\t\tval.name = current_class.fields[current_class_field++];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"Closing object; set value name, and push...\", current_class_field, val );\n\t\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"close object; empty object\", val, elements );\n\n\t\t\t\t\t\t\t\tval.value_type = VALUE_OBJECT;\n\t\t\t\t\t\t\t\tif( current_proto && current_proto.protoDef ) {\n\t\t\t\t\t\t\t\t\tconsole.log( \"SOMETHING SHOULD AHVE BEEN REPLACED HERE??\", current_proto );\n\t\t\t\t\t\t\t\t\tconsole.log( \"The other version only revives on init\" );\n\t\t\t\t\t\t\t\t\telements = new current_proto.protoDef.cb( elements, undefined, undefined );\n\t\t\t\t\t\t\t\t\t//elements = new current_proto.protoCon( elements );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tval.contains = elements;\n\t\t\t\t\t\t\t\tval.string = \"\";\n\n\t\t\t\t\t\t\tlet old_context = context_stack.pop();\n\t\t\t\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"object pop stack (close obj)\", context_stack.length, old_context );\n\t\t\t\t\t\t\tparse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD\n\t\t\t\t\t\t\tval.name = old_context.name;\n\t\t\t\t\t\t\telements = old_context.elements;\n\t\t\t\t\t\t\t//element_array = old_context.element_array;\n\t\t\t\t\t\t\tcurrent_class = old_context.current_class;\n\t\t\t\t\t\t\tcurrent_proto = old_context.current_proto;\n\t\t\t\t\t\t\tcurrent_class_field = old_context.current_class_field;\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"B Pop old class field counter:\", context_stack, current_class_field, val.name );\n\t\t\t\t\t\t\tarrayType = old_context.arrayType;\n\t\t\t\t\t\t\tval.value_type = old_context.valueType;\n\t\t\t\t\t\t\tval.className = old_context.className;\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \" !!!!!D Pop Classname:\", val.className );\n\t\t\t\t\t\t\tdropContext( old_context );\n\n\t\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( ( parse_context == CONTEXT_OBJECT_FIELD_VALUE ) ) {\n\t\t\t\t\t\t\t// first, add the last value\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"close object; push item '%s' %d\", val.name, val.value_type );\n\t\t\t\t\t\t\tif( val.value_type === VALUE_UNSET ) {\n\t\t\t\t\t\t\t\tthrowError( \"Fault while parsing; unexpected\", cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\tval.value_type = VALUE_OBJECT;\n\t\t\t\t\t\t\tval.contains = elements;\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\n\t\t\t\t\t\t\t//let old_context = context_stack.pop();\n\t\t\t\t\t\t\tlet old_context = context_stack.pop();\n\t\t\t\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"object pop stack (close object)\", context_stack.length, old_context );\n\t\t\t\t\t\t\tparse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD\n\t\t\t\t\t\t\tval.name = old_context.name;\n\t\t\t\t\t\t\telements = old_context.elements;\n\t\t\t\t\t\t\tcurrent_proto = old_context.current_proto;\n\t\t\t\t\t\t\tcurrent_class = old_context.current_class;\n\t\t\t\t\t\t\tcurrent_class_field = old_context.current_class_field;\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"C Pop old class field counter:\", context_stack, current_class_field, val.name );\n\t\t\t\t\t\t\tarrayType = old_context.arrayType;\n\t\t\t\t\t\t\tval.value_type = old_context.valueType;\n\t\t\t\t\t\t\tval.className = old_context.className;\n\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \" !!!!!E Pop Classname:\", val.className );\n\t\t\t\t\t\t\t//element_array = old_context.element_array;\n\t\t\t\t\t\t\tdropContext( old_context );\n\t\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthrowError( \"Fault while parsing; unexpected\", cInt );\n\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnegative = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 93/*']'*/:\n\t\t\t\t\t\tif( word >= WORD_POS_AFTER_FIELD ) {\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"close array, push last element: %d\", val.value_type );\n\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t// name is set when saving a context.\n\t\t\t\t\t\t\t\t// a better sanity check would be val.name === elements.length;\n\t\t\t\t\t\t\t\t//if( val.name ) if( val.name !== elements.length ) console.log( \"Ya this should blow up\" );\n\t\t\t\t\t\t\t\tarrayPush();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tval.contains = elements;\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlet old_context = context_stack.pop();\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_STACK && console.log( \"object pop stack (close array)\", context_stack.length );\n\t\t\t\t\t\t\t\tval.name = old_context.name;\n\t\t\t\t\t\t\t\tval.className = old_context.className;\n\t\t\t\t\t\t\t\tparse_context = old_context.context;\n\t\t\t\t\t\t\t\telements = old_context.elements;\n\t\t\t\t\t\t\t\t//element_array = old_context.element_array;\n\t\t\t\t\t\t\t\tcurrent_proto = old_context.current_proto;\n\t\t\t\t\t\t\t\tcurrent_class = old_context.current_class;\n\t\t\t\t\t\t\t\tcurrent_class_field = old_context.current_class_field;\n\t\t\t\t\t\t\t\tarrayType = old_context.arrayType;\n\t\t\t\t\t\t\t\tval.value_type = old_context.valueType;\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"close array:\", old_context );\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"D Pop old class field counter:\", context_stack, current_class_field, val );\n\t\t\t\t\t\t\t\tdropContext( old_context );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tval.value_type = VALUE_ARRAY;\n\t\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrowError( `bad context ${parse_context}; fault while parsing`, cInt );// fault\n\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnegative = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 44/*','*/:\n\t\t\t\t\t\tif( word < WORD_POS_AFTER_FIELD && word != WORD_POS_RESET ) {\n\t\t\t\t\t\t\trecoverIdent(cInt);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( word == WORD_POS_END || word == WORD_POS_FIELD ) word = WORD_POS_RESET; // allow collect new keyword\n\t\t\t\t\t\t//if(//_DEBUG_PARSING) \n\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"comma context:\", parse_context, val );\n\t\t\t\t\t\tif( parse_context == CONTEXT_CLASS_FIELD ) {\n\t\t\t\t\t\t\tif( current_class ) {\n\t\t\t\t\t\t\t\t//console.log( \"Saving field name(set word to IS A FIELD):\", val.string );\n\t\t\t\t\t\t\t\tcurrent_class.fields.push( val.string );\n\t\t\t\t\t\t\t\tval.string = '';\n\t\t\t\t\t\t\t\tword = WORD_POS_FIELD;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrowError( \"State error; gathering class fields, and lost the class\", cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD ) {\n\t\t\t\t\t\t\tif( current_class ) {\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"D Stepping current class field:\", current_class_field, val.name );\n\t\t\t\t\t\t\t\tval.name = current_class.fields[current_class_field++];\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"should have a completed value at a comma.:\", current_class_field, val );\n\t\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"pushing object field:\", val );\n\t\t\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// this is an empty comma...\n\t\t\t\t\t\t\t\tif( val.string || val.value_type )\n\t\t\t\t\t\t\t\t\tthrowError( \"State error; comma in field name and/or lost the class\", cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if( parse_context == CONTEXT_CLASS_VALUE ) {\n\t\t\t\t\t\t\tif( current_class ) {\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"reviving values in class...\", arrayType, current_class.fields[current_class_field ], val );\n\t\t\t\t\t\t\t\tif( arrayType != -3 && !val.name ) {\n\t\t\t\t\t\t\t\t\t// this should have still had a name....\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"E Stepping current class field:\", current_class_field, val, arrayType );\n\t\t\t\t\t\t\t\t\tval.name = current_class.fields[current_class_field++];\n\t\t\t\t\t\t\t\t\t//else val.name = current_class.fields[current_class_field++];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"should have a completed value at a comma.:\", current_class_field, val );\n\t\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t\tif( arrayType != -3 )\n\t\t\t\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t//throwError( \"State error; gathering class values, and lost the class\", cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tval.name = null;\n\t\t\t\t\t\t} else if( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\t\t\tif( val.value_type == VALUE_UNSET )\n\t\t\t\t\t\t\t\tval.value_type = VALUE_EMPTY; // in an array, elements after a comma should init as undefined...\n\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"back in array; push item %d\", val.value_type );\n\t\t\t\t\t\t\tarrayPush();\n\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t// undefined allows [,,,] to be 4 values and [1,2,3,] to be 4 values with an undefined at end.\n\t\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD_VALUE && val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t// after an array value, it will have returned to OBJECT_FIELD anyway\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"comma after field value, push field to object: %s\", val.name, val.value_type );\n\t\t\t\t\t\t\tparse_context = CONTEXT_OBJECT_FIELD;\n\t\t\t\t\t\t\tif( val.value_type != VALUE_UNSET ) {\n\t\t\t\t\t\t\t\tobjectPush();\n\t\t\t\t\t\t\t\tRESET_VAL();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\tthrowError( \"bad context; excessive commas while parsing;\", cInt );// fault\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnegative = false;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tswitch( cInt ) {\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\tif( ( parse_context == CONTEXT_UNKNOWN )\n\t\t\t\t\t\t || ( parse_context == CONTEXT_OBJECT_FIELD_VALUE && word == WORD_POS_FIELD )\n\t\t\t\t\t\t || ( ( parse_context == CONTEXT_OBJECT_FIELD ) || word == WORD_POS_FIELD )\n\t\t\t\t\t\t || ( parse_context == CONTEXT_CLASS_FIELD ) ) {\n\t\t\t\t\t\t\tswitch( cInt ) {\n\t\t\t\t\t\t\tcase 96://'`':\n\t\t\t\t\t\t\tcase 34://'\"':\n\t\t\t\t\t\t\tcase 39://'\\'':\n\t\t\t\t\t\t\t\tif( word == WORD_POS_RESET || word == WORD_POS_FIELD ) {\n\t\t\t\t\t\t\t\t\tif( val.string.length ) {\n\t\t\t\t\t\t\t\t\t\tconsole.log( \"IN ARRAY AND FIXING?\" );\n\t\t\t\t\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\t\t\t\t\tval.string = '';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlet string_status = gatherString(cInt );\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"string gather for object field name :\", val.string, string_status );\n\t\t\t\t\t\t\t\t\tif( string_status ) {\n\t\t\t\t\t\t\t\t\t\tval.value_type = VALUE_STRING;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tgatheringStringFirstChar = cInt;\n\t\t\t\t\t\t\t\t\t\tgatheringString = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthrowError( \"fault while parsing; quote not at start of field name\", cInt );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 10://'\\n':\n\t\t\t\t\t\t\t\tpos.line++;\n\t\t\t\t\t\t\t\tpos.col = 1;\n\t\t\t\t\t\t\t\t// fall through to normal space handling - just updated line/col position\n\t\t\t\t\t\t\tcase 13://'\\r':\n\t\t\t\t\t\t\tcase 32://' ':\n\t\t\t\t\t\t\tcase 0x2028://' ':\n\t\t\t\t\t\t\tcase 0x2029://' ':\n\t\t\t\t\t\t\tcase 9://'\\t':\n\t\t\t\t\t\t\tcase 0xFEFF: // ZWNBS is WS though\n\t\t\t\t\t\t\t\t //_DEBUG_WHITESPACE && console.log( \"THIS SPACE\", word, parse_context, val );\n\t\t\t\t\t\t\t\tif( parse_context === CONTEXT_UNKNOWN && word === WORD_POS_END ) { // allow collect new keyword\n\t\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\t\tif( parse_context === CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif( word === WORD_POS_RESET || word === WORD_POS_AFTER_FIELD ) { // ignore leading and trailing whitepsace\n\t\t\t\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN && val.value_type ) {\n\t\t\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if( word === WORD_POS_FIELD ) {\n\t\t\t\t\t\t\t\t\tif( parse_context === CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif( val.string.length )\n\t\t\t\t\t\t\t\t\t\tconsole.log( \"STEP TO NEXT TOKEN.\" );\n\t\t\t\t\t\t\t\t\t\tword = WORD_POS_AFTER_FIELD;\n\t\t\t\t\t\t\t\t\t\t//val.className = val.string; val.string = '';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\t\tthrowError( \"fault while parsing; whitepsace unexpected\", cInt );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// skip whitespace\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t//if( /((\\n|\\r|\\t)|s|S|[ \\{\\}\\(\\)\\<\\>\\!\\+-\\*\\/\\.\\:\\, ])/.\n\t\t\t\t\t\t\t\tif( testNonIdentifierCharacters ) {\n\t\t\t\t\t\t\t\tlet identRow = nonIdent.find( row=>(row.firstChar >= cInt )&& (row.lastChar > cInt) )\n\t\t\t\t\t\t\t\tif( identRow && ( identRow.bits[(cInt - identRow.firstChar) / 24]\n\t\t\t\t\t\t\t\t & (1 << ((cInt - identRow.firstChar) % 24)))) {\n\t\t\t\t\t\t\t\t//if( nonIdent[(cInt/(24*16))|0] && nonIdent[(cInt/(24*16))|0][(( cInt % (24*16) )/24)|0] & ( 1 << (cInt%24)) ) {\n\t\t\t\t\t\t\t\t\t// invalid start/continue\n\t\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\t\tthrowError( `fault while parsing object field name; \\\\u${cInt}`, cInt );\t// fault\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t//console.log( \"TICK\" );\n\t\t\t\t\t\t\t\tif( word == WORD_POS_RESET && ( ( cInt >= 48/*'0'*/ && cInt <= 57/*'9'*/ ) || ( cInt == 43/*'+'*/ ) || ( cInt == 46/*'.'*/ ) || ( cInt == 45/*'-'*/ ) ) ) {\n\t\t\t\t\t\t\t\t\tfromHex = false;\n\t\t\t\t\t\t\t\t\texponent = false;\n\t\t\t\t\t\t\t\t\tdate_format = false;\n\t\t\t\t\t\t\t\t\tisBigInt = false;\n\n\t\t\t\t\t\t\t\t\texponent_sign = false;\n\t\t\t\t\t\t\t\t\texponent_digit = false;\n\t\t\t\t\t\t\t\t\tdecimal = false;\n\t\t\t\t\t\t\t\t\tval.string = str;\n\t\t\t\t\t\t\t\t\tinput.n = n;\n\t\t\t\t\t\t\t\t\tcollectNumber();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif( word === WORD_POS_AFTER_FIELD ) {\n\t\t\t\t\t\t\t\t\tstatus = false;\n\t\t\t\t\t\t\t\t\tthrowError( \"fault while parsing; character unexpected\", cInt );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif( word === WORD_POS_RESET ) {\n\t\t\t\t\t\t\t\t\tword = WORD_POS_FIELD;\n\t\t\t\t\t\t\t\t\tval.value_type = VALUE_STRING;\n\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"START/CONTINUE IDENTIFER\" );\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\tif( val.value_type == VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t\tif( word !== WORD_POS_RESET && word !== WORD_POS_END )\n\t\t\t\t\t\t\t\t\t\trecoverIdent( cInt );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif( word === WORD_POS_END || word === WORD_POS_FIELD ) {\n\t\t\t\t\t\t\t\t\t\t// final word of the line... \n\t\t\t\t\t\t\t\t\t\t// whispace changes the 'word' state to not 'end'\n\t\t\t\t\t\t\t\t\t\t// until the next character, which may restore it to\n\t\t\t\t\t\t\t\t\t\t// 'end' and this will resume collecting the same string.\n\t\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif( parse_context == CONTEXT_OBJECT_FIELD ) {\n\t\t\t\t\t\t\t\t\t\tif( word == WORD_POS_FIELD ) {\n\t\t\t\t\t\t\t\t\t\t\tval.string+=str;\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tthrowError( \"Multiple values found in field name\", cInt );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif( parse_context == CONTEXT_OBJECT_FIELD_VALUE ) {\n\t\t\t\t\t\t\t\t\t\tthrowError( \"String unexpected\", cInt );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak; // default\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET && ( ( cInt >= 48/*'0'*/ && cInt <= 57/*'9'*/ ) || ( cInt == 43/*'+'*/ ) || ( cInt == 46/*'.'*/ ) || ( cInt == 45/*'-'*/ ) ) ) {\n\t\t\t\t\t\t\t\tfromHex = false;\n\t\t\t\t\t\t\t\texponent = false;\n\t\t\t\t\t\t\t\tdate_format = false;\n\t\t\t\t\t\t\t\tisBigInt = false;\n\n\t\t\t\t\t\t\t\texponent_sign = false;\n\t\t\t\t\t\t\t\texponent_digit = false;\n\t\t\t\t\t\t\t\tdecimal = false;\n\t\t\t\t\t\t\t\tval.string = str;\n\t\t\t\t\t\t\t\tinput.n = n;\n\t\t\t\t\t\t\t\tcollectNumber();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t//console.log( \"TICK\")\n\t\t\t\t\t\t\t\tif( val.value_type == VALUE_UNSET ) {\n\t\t\t\t\t\t\t\t\tif( word != WORD_POS_RESET ) {\n\t\t\t\t\t\t\t\t\t\trecoverIdent( cInt );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t\tval.value_type = VALUE_STRING;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif( parse_context == CONTEXT_OBJECT_FIELD ) {\n\t\t\t\t\t\t\t\t\t\tthrowError( \"Multiple values found in field name\", cInt );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if( parse_context == CONTEXT_OBJECT_FIELD_VALUE ) {\n\n\t\t\t\t\t\t\t\t\t\tif( val.value_type != VALUE_STRING ) {\n\t\t\t\t\t\t\t\t\t\t\tif( val.value_type == VALUE_OBJECT || val.value_type == VALUE_ARRAY ){\n\t\t\t\t\t\t\t\t\t\t\t\tthrowError( \"String unexpected\", cInt );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\trecoverIdent(cInt);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif( word == WORD_POS_AFTER_FIELD ){\n\t\t\t\t\t\t\t\t\t\t\tconst protoDef = getProto();\n\t\t\t\t\t\t\t\t\t\t\tif( protoDef){\n\t\t\t\t\t\t\t\t\t\t\t\tword == WORD_POS_END; // last string.\n\t\t\t\t\t\t\t\t\t\t\t\tval.string = str;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse \n\t\t\t\t\t\t\t\t\t\t\t\tthrowError( \"String unexpected\", cInt );\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif( word == WORD_POS_END ) {\n\t\t\t\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\t\t\t\t\tthrowError( \"String unexpected\", cInt );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\t\t\t\t\t\tif( word == WORD_POS_AFTER_FIELD ){\n\t\t\t\t\t\t\t\t\t\t\tif( !val.className ){\n\t\t\t\t\t\t\t\t\t\t\t\t//\tgetProto()\n\t\t\t\t\t\t\t\t\t\t\t\tval.className = val.string;\n\t\t\t\t\t\t\t\t\t\t\t\tval.string = '';\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif( word == WORD_POS_END )\n\t\t\t\t\t\t\t\t\t\t\t\tval.string += str;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t//recoverIdent(cInt);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak; // default\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 96://'`':\n\t\t\t\t\t\tcase 34://'\"':\n\t\t\t\t\t\tcase 39://'\\'':\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif( val.string ) val.className = val.string; val.string = '';\n\t\t\t\t\t\t\tlet string_status = gatherString( cInt );\n\t\t\t\t\t\t\t//_DEBUG_PARSING && console.log( \"string gather for object field value :\", val.string, string_status, completed, input.n, buf.length );\n\t\t\t\t\t\t\tif( string_status ) {\n\t\t\t\t\t\t\t\tval.value_type = VALUE_STRING;\n\t\t\t\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tgatheringStringFirstChar = cInt;\n\t\t\t\t\t\t\t\tgatheringString = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 10://'\\n':\n\t\t\t\t\t\t\tpos.line++;\n\t\t\t\t\t\t\tpos.col = 1;\n\t\t\t\t\t\t\t//falls through\n\t\t\t\t\t\tcase 32://' ':\n\t\t\t\t\t\tcase 9://'\\t':\n\t\t\t\t\t\tcase 13://'\\r':\n\t\t\t\t\t\tcase 0x2028: // LS (Line separator)\n\t\t\t\t\t\tcase 0x2029: // PS (paragraph separate)\n\t\t\t\t\t\tcase 0xFEFF://'\\uFEFF':\n\t\t\t\t\t\t\t//_DEBUG_WHITESPACE && console.log( \"Whitespace...\", word, parse_context );\n\t\t\t\t\t\t\tif( word == WORD_POS_END ) {\n\t\t\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN ) {\n\t\t\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD_VALUE ) {\n\t\t\t\t\t\t\t\t\tword = WORD_POS_AFTER_FIELD_VALUE;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else if( parse_context == CONTEXT_OBJECT_FIELD ) {\n\t\t\t\t\t\t\t\t\tword = WORD_POS_AFTER_FIELD;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else if( parse_context == CONTEXT_IN_ARRAY ) {\n\t\t\t\t\t\t\t\t\tword = WORD_POS_AFTER_FIELD;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET || ( word == WORD_POS_AFTER_FIELD ))\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\telse if( word == WORD_POS_FIELD ) {\n\t\t\t\t\t\t\t\tif( val.string.length )\n\t\t\t\t\t\t\t\t\tword = WORD_POS_AFTER_FIELD;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif( word < WORD_POS_END ) \n\t\t\t\t\t\t\t\t\trecoverIdent( cInt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t//----------------------------------------------------------\n\t\t\t\t\t// catch characters for true/false/null/undefined which are values outside of quotes\n\t\t\t\t\t\tcase 116://'t':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) word = WORD_POS_TRUE_1;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_6 ) word = WORD_POS_INFINITY_7;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 114://'r':\n\t\t\t\t\t\t\tif( word == WORD_POS_TRUE_1 ) word = WORD_POS_TRUE_2;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 117://'u':\n\t\t\t\t\t\t\tif( word == WORD_POS_TRUE_2 ) word = WORD_POS_TRUE_3;\n\t\t\t\t\t\t\telse if( word == WORD_POS_NULL_1 ) word = WORD_POS_NULL_2;\n\t\t\t\t\t\t\telse if( word == WORD_POS_RESET ) word = WORD_POS_UNDEFINED_1;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 101://'e':\n\t\t\t\t\t\t\tif( word == WORD_POS_TRUE_3 ) {\n\t\t\t\t\t\t\t\tval.value_type = VALUE_TRUE;\n\t\t\t\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t\t\t} else if( word == WORD_POS_FALSE_4 ) {\n\t\t\t\t\t\t\t\tval.value_type = VALUE_FALSE;\n\t\t\t\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t\t\t} else if( word == WORD_POS_UNDEFINED_3 ) word = WORD_POS_UNDEFINED_4;\n\t\t\t\t\t\t\telse if( word == WORD_POS_UNDEFINED_7 ) word = WORD_POS_UNDEFINED_8;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 110://'n':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) word = WORD_POS_NULL_1;\n\t\t\t\t\t\t\telse if( word == WORD_POS_UNDEFINED_1 ) word = WORD_POS_UNDEFINED_2;\n\t\t\t\t\t\t\telse if( word == WORD_POS_UNDEFINED_6 ) word = WORD_POS_UNDEFINED_7;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_1 ) word = WORD_POS_INFINITY_2;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_4 ) word = WORD_POS_INFINITY_5;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 100://'d':\n\t\t\t\t\t\t\tif( word == WORD_POS_UNDEFINED_2 ) word = WORD_POS_UNDEFINED_3;\n\t\t\t\t\t\t\telse if( word == WORD_POS_UNDEFINED_8 ) { val.value_type=VALUE_UNDEFINED; word = WORD_POS_END; }\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 105://'i':\n\t\t\t\t\t\t\tif( word == WORD_POS_UNDEFINED_5 ) word = WORD_POS_UNDEFINED_6;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_3 ) word = WORD_POS_INFINITY_4;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_5 ) word = WORD_POS_INFINITY_6;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 108://'l':\n\t\t\t\t\t\t\tif( word == WORD_POS_NULL_2 ) word = WORD_POS_NULL_3;\n\t\t\t\t\t\t\telse if( word == WORD_POS_NULL_3 ) {\n\t\t\t\t\t\t\t\tval.value_type = VALUE_NULL;\n\t\t\t\t\t\t\t\tword = WORD_POS_END;\n\t\t\t\t\t\t\t} else if( word == WORD_POS_FALSE_2 ) word = WORD_POS_FALSE_3;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 102://'f':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) word = WORD_POS_FALSE_1;\n\t\t\t\t\t\t\telse if( word == WORD_POS_UNDEFINED_4 ) word = WORD_POS_UNDEFINED_5;\n\t\t\t\t\t\t\telse if( word == WORD_POS_INFINITY_2 ) word = WORD_POS_INFINITY_3;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 97://'a':\n\t\t\t\t\t\t\tif( word == WORD_POS_FALSE_1 ) word = WORD_POS_FALSE_2;\n\t\t\t\t\t\t\telse if( word == WORD_POS_NAN_1 ) word = WORD_POS_NAN_2;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 115://'s':\n\t\t\t\t\t\t\tif( word == WORD_POS_FALSE_3 ) word = WORD_POS_FALSE_4;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 73://'I':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) word = WORD_POS_INFINITY_1;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 78://'N':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) word = WORD_POS_NAN_1;\n\t\t\t\t\t\t\telse if( word == WORD_POS_NAN_2 ) { val.value_type = negative ? VALUE_NEG_NAN : VALUE_NAN; negative = false; word = WORD_POS_END; }\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 121://'y':\n\t\t\t\t\t\t\tif( word == WORD_POS_INFINITY_7 ) { val.value_type = negative ? VALUE_NEG_INFINITY : VALUE_INFINITY; negative = false; word = WORD_POS_END; }\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 45://'-':\n\t\t\t\t\t\t\tif( word == WORD_POS_RESET ) negative = !negative;\n\t\t\t\t\t\t\telse { recoverIdent(cInt); }// fault\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 43://'+':\n\t\t\t\t\t\t\tif( word !== WORD_POS_RESET ) { recoverIdent(cInt); }\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak; // default of high level switch\n\t\t\t\t\t//\n\t\t\t\t\t//----------------------------------------------------------\n\t\t\t\t\t}\n\t\t\t\t\tif( completed ) {\n\t\t\t\t\t\tif( word == WORD_POS_END ) {\n\t\t\t\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif( n == buf.length ) {\n\t\t\t\t\tdropBuffer( input );\n\t\t\t\t\tif( gatheringString || gatheringNumber || parse_context == CONTEXT_OBJECT_FIELD ) {\n\t\t\t\t\t\tretval = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif( parse_context == CONTEXT_UNKNOWN && ( val.value_type != VALUE_UNSET || result ) ) {\n\t\t\t\t\t\t\tcompleted = true;\n\t\t\t\t\t\t\tretval = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// put these back into the stack.\n\t\t\t\t\tinput.n = n;\n\t\t\t\t\tinQueue.unshift( input );\n\t\t\t\t\tretval = 2; // if returning buffers, then obviously there's more in this one.\n\t\t\t\t}\n\t\t\t\tif( completed ) {\n\t\t\t\t\trootObject = null;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( !status ) return -1;\n\t\t\tif( completed && val.value_type != VALUE_UNSET ) {\n\t\t\t\tword = WORD_POS_RESET;\n\t\t\t\tresult = convertValue();\n\t\t\t\t//_DEBUG_PARSING && console.log( \"Result(3):\", result );\n\t\t\t\tnegative = false;\n\t\t\t\tval.string = '';\n\t\t\t\tval.value_type = VALUE_UNSET;\n\t\t\t}\n\t\t\tcompleted = false;\n\t\t\treturn retval;\n\t\t}\n\t}\n}\n\n\n\nconst _parser = [Object.freeze( JSOX.begin() )];\nlet _parse_level = 0;\n/**\n * @param {string} msg \n * @param {(this: unknown, key: string, value: unknown) => any} [reviver] \n * @returns {unknown}\n */\nJSOX.parse = function( msg, reviver ) {\n\tlet parse_level = _parse_level++;\n\tlet parser;\n\tif( _parser.length <= parse_level )\n\t\t_parser.push( Object.freeze( JSOX.begin() ) );\n\tparser = _parser[parse_level];\n\tif (typeof msg !== \"string\") msg = String(msg);\n\tparser.reset();\n\tconst writeResult = parser._write( msg, true );\n\tif( writeResult > 0 ) {\n\t\tif( writeResult > 1 ){\n\t\t\t// probably a carriage return.\n\t\t\t//console.log( \"Extra data at end of message\");\n\t\t}\n\t\tlet result = parser.value();\n\t\tif( ( \"undefined\" === typeof result ) && writeResult > 1 ){\n\t\t\tthrow new Error( \"Pending value could not complete\");\n\t\t}\n\n\t\tresult = typeof reviver === 'function' ? (function walk(holder, key) {\n\t\t\tlet k, v, value = holder[key];\n\t\t\tif (value && typeof value === 'object') {\n\t\t\t\tfor (k in value) {\n\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\tv = walk(value, k);\n\t\t\t\t\t\tif (v !== undefined) {\n\t\t\t\t\t\t\tvalue[k] = v;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdelete value[k];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn reviver.call(holder, key, value);\n\t\t}({'': result}, '')) : result;\n\t\t_parse_level--;\n\t\treturn result;\n\t}\n\tparser.finalError();\n\treturn undefined;\n}\n\n\nfunction this_value() {/*//_DEBUG_STRINGIFY&&console.log( \"this:\", this, \"valueof:\", this&&this.valueOf() );*/ \n\treturn this&&this.valueOf();\n}\n\n/**\n * Define a class to be used for serialization; the class allows emitting the class fields ahead of time, and just provide values later.\n * @param {string} name \n * @param {object} obj \n */\nJSOX.defineClass = function( name, obj ) {\n\tlet cls;\n\tlet denormKeys = Object.keys(obj);\n\tfor( let i = 1; i < denormKeys.length; i++ ) {\n\t\tlet a, b;\n\t\tif( ( a = denormKeys[i-1] ) > ( b = denormKeys[i] ) ) {\n\t\t\tdenormKeys[i-1] = b;\n\t\t\tdenormKeys[i] = a;\n\t\t\tif( i ) i-=2; // go back 2, this might need to go further pack.\n\t\t\telse i--; // only 1 to check.\n\t\t}\n\t}\n\t//console.log( \"normalized:\", denormKeys );\n\tcommonClasses.push( cls = { name : name\n\t\t , tag:denormKeys.toString()\n\t\t , proto : Object.getPrototypeOf(obj)\n\t\t , fields : Object.keys(obj) } );\n\tfor(let n = 1; n < cls.fields.length; n++) {\n\t\tif( cls.fields[n] < cls.fields[n-1] ) {\n\t\t\tlet tmp = cls.fields[n-1];\n\t\t\tcls.fields[n-1] = cls.fields[n];\n\t\t\tcls.fields[n] = tmp;\n\t\t\tif( n > 1 )\n\t\t\t\tn-=2;\n\t\t}\n\t}\n\tif( cls.proto === Object.getPrototypeOf( {} ) ) cls.proto = null;\n}\n\n/**\n * define a class to be used for serialization\n * @param {string} named\n * @param {class} ptype\n * @param {(any)=>any} f\n */\nJSOX.toJSOX =\nJSOX.registerToJSOX = function( name, ptype, f ) {\n\t//console.log( \"SET OBJECT TYPE:\", ptype, ptype.prototype, Object.prototype, ptype.constructor );\n\tif( !ptype.prototype || ptype.prototype !== Object.prototype ) {\n\t\tif( toProtoTypes.get(ptype.prototype) ) throw new Error( \"Existing toJSOX has been registered for prototype\" );\n\t\t//_DEBUG_PARSING && console.log( \"PUSH PROTOTYPE\" );\n\t\ttoProtoTypes.set( ptype.prototype, { external:true, name:name||f.constructor.name, cb:f } );\n\t} else {\n\t\tlet key = Object.keys( ptype ).toString();\n\t\tif( toObjectTypes.get(key) ) throw new Error( \"Existing toJSOX has been registered for object type\" );\n\t\t//console.log( \"TEST SET OBJECT TYPE:\", key );\n\t\ttoObjectTypes.set( key, { external:true, name:name, cb:f } );\n\t}\n}\n/**\n * define a class to be used for deserialization\n * @param {string} prototypeName \n * @param {class} o \n * @param {(any)=>any} f \n */\nJSOX.fromJSOX = function( prototypeName, o, f ) {\n\tfunction privateProto() { }\n\t\tif( !o ) o = privateProto.prototype;\n\t\tif( fromProtoTypes.get(prototypeName) ) throw new Error( \"Existing fromJSOX has been registered for prototype\" );\n\t\tif( o && !(\"constructor\" in o )){\n\t\t\tthrow new Error( \"Please pass a prototype like thing...\");\n\t}\n\tfromProtoTypes.set( prototypeName, {protoCon: o.prototype.constructor, cb:f } );\n\n}\nJSOX.registerFromJSOX = function( prototypeName, o /*, f*/ ) {\n\tthrow new Error( \"deprecated; please adjust code to use fromJSOX:\" + prototypeName + o.toString() );\n}\nJSOX.addType = function( prototypeName, prototype, to, from ) {\n\tJSOX.toJSOX( prototypeName, prototype, to );\n\tJSOX.fromJSOX( prototypeName, prototype, from );\n}\n\nJSOX.registerToFrom = function( prototypeName, prototype/*, to, from*/ ) {\n\tthrow new Error( \"registerToFrom deprecated; please use addType:\" + prototypeName + prototype.toString() );\n}\n\n/**\n * Create a stringifier to convert objects to JSOX text. Allows defining custom serialization for objects.\n * @returns {Stringifier}\n */\nJSOX.stringifier = function() {\n\tlet classes = [];\n\tlet useQuote = '\"';\n\n\tlet fieldMap = new WeakMap();\n\tconst path = [];\n\tlet encoding = [];\n\tconst localToProtoTypes = new WeakMap();\n\tconst localToObjectTypes = new Map();\n\tlet objectToJSOX = null;\n\tconst stringifying = []; // things that have been stringified through external toJSOX; allows second pass to skip this toJSOX pass and encode 'normally'\n\tlet ignoreNonEnumerable = false;\n\tfunction getIdentifier(s) {\n\t\n\t\tif( ( \"string\" === typeof s ) && s === '' ) return '\"\"';\n\t\tif( ( \"number\" === typeof s ) && !isNaN( s ) ) {\n\t\t\treturn [\"'\",s.toString(),\"'\"].join('');\n\t\t}\n\t\t// should check also for if any non ident in string...\n\t\tif( s.includes( \"\\u{FEFF}\" ) ) return (useQuote + JSOX.escape(s) +useQuote);\n\t\treturn ( ( s in keywords /* [ \"true\",\"false\",\"null\",\"NaN\",\"Infinity\",\"undefined\"].find( keyword=>keyword===s )*/\n\t\t\t|| /[0-9\\-]/.test(s[0])\n\t\t\t|| /[\\n\\r\\t #\\[\\]{}()<>\\~!+*/.:,\\-\"'`]/.test( s ) )?(useQuote + JSOX.escape(s) +useQuote):s )\n\t}\n\n\n\t/* init prototypes */\n\tif( !toProtoTypes.get( Object.prototype ) )\n\t{\n\t\ttoProtoTypes.set( Object.prototype, { external:false, name:Object.prototype.constructor.name, cb:null } );\n\t \n\t\t// function https://stackoverflow.com/a/17415677/4619267\n\t\ttoProtoTypes.set( Date.prototype, { external:false,\n\t\t\tname : \"Date\",\n\t\t\tcb : function () {\n\t\t\t\t\tif( this.getTime()=== -62167219200000) \n\t\t\t\t\t{\n\t\t\t\t\t\treturn \"0000-01-01T00:00:00.000Z\";\n\t\t\t\t\t}\n\t\t\t\t\tlet tzo = -this.getTimezoneOffset(),\n\t\t\t\t\tdif = tzo >= 0 ? '+' : '-',\n\t\t\t\t\tpad = function(num) {\n\t\t\t\t\t\tlet norm = Math.floor(Math.abs(num));\n\t\t\t\t\t\treturn (norm < 10 ? '0' : '') + norm;\n\t\t\t\t\t},\n\t\t\t\t\tpad3 = function(num) {\n\t\t\t\t\t\tlet norm = Math.floor(Math.abs(num));\n\t\t\t\t\t\treturn (norm < 100 ? '0' : '') + (norm < 10 ? '0' : '') + norm;\n\t\t\t\t\t};\n\t\t\t\treturn [this.getFullYear() ,\n\t\t\t\t\t'-' , pad(this.getMonth() + 1) ,\n\t\t\t\t\t'-' , pad(this.getDate()) ,\n\t\t\t\t\t'T' , pad(this.getHours()) ,\n\t\t\t\t\t':' , pad(this.getMinutes()) ,\n\t\t\t\t\t':' , pad(this.getSeconds()) ,\n\t\t\t\t\t'.' + pad3(this.getMilliseconds()) +\n\t\t\t\t\tdif , pad(tzo / 60) ,\n\t\t\t\t\t':' , pad(tzo % 60)].join(\"\");\n\t\t\t} \n\t\t} );\n\t\ttoProtoTypes.set( DateNS.prototype, { external:false,\n\t\t\tname : \"DateNS\",\n\t\t\tcb : function () {\n\t\t\t\tlet tzo = -this.getTimezoneOffset(),\n\t\t\t\t\tdif = tzo >= 0 ? '+' : '-',\n\t\t\t\t\tpad = function(num) {\n\t\t\t\t\t\tlet norm = Math.floor(Math.abs(num));\n\t\t\t\t\t\treturn (norm < 10 ? '0' : '') + norm;\n\t\t\t\t\t},\n\t\t\t\t\tpad3 = function(num) {\n\t\t\t\t\t\tlet norm = Math.floor(Math.abs(num));\n\t\t\t\t\t\treturn (norm < 100 ? '0' : '') + (norm < 10 ? '0' : '') + norm;\n\t\t\t\t\t},\n\t\t\t\t\tpad6 = function(num) {\n\t\t\t\t\t\tlet norm = Math.floor(Math.abs(num));\n\t\t\t\t\t\treturn (norm < 100000 ? '0' : '') + (norm < 10000 ? '0' : '') + (norm < 1000 ? '0' : '') + (norm < 100 ? '0' : '') + (norm < 10 ? '0' : '') + norm;\n\t\t\t\t\t};\n\t\t\t\treturn [this.getFullYear() ,\n\t\t\t\t\t'-' , pad(this.getMonth() + 1) ,\n\t\t\t\t\t'-' , pad(this.getDate()) ,\n\t\t\t\t\t'T' , pad(this.getHours()) ,\n\t\t\t\t\t':' , pad(this.getMinutes()) ,\n\t\t\t\t\t':' , pad(this.getSeconds()) ,\n\t\t\t\t\t'.' + pad3(this.getMilliseconds()) + pad6(this.ns) +\n\t\t\t\t\tdif , pad(tzo / 60) ,\n\t\t\t\t\t':' , pad(tzo % 60)].join(\"\");\n\t\t\t} \n\t\t} );\n\t\ttoProtoTypes.set( Boolean.prototype, { external:false, name:\"Boolean\", cb:this_value } );\n\t\ttoProtoTypes.set( Number.prototype, { external:false, name:\"Number\"\n\t\t , cb:function(){ \n\t\t\t\tif( isNaN(this) ) return \"NaN\";\n\t\t\t\treturn (isFinite(this))\n\t\t\t\t\t? String(this)\n\t\t\t\t\t: (this<0)?\"-Infinity\":\"Infinity\";\n\t\t }\n\t\t} );\n\t\ttoProtoTypes.set( String.prototype, { external:false\n\t\t , name : \"String\"\n\t\t , cb:function(){ return '\"' + JSOX.escape(this_value.apply(this)) + '\"' } } );\n\t\tif( typeof BigInt === \"function\" )\n\t\t\ttoProtoTypes.set( BigInt.prototype\n\t\t\t , { external:false, name:\"BigInt\", cb:function() { return this + 'n' } } );\n\t \n\t\ttoProtoTypes.set( ArrayBuffer.prototype, { external:true, name:\"ab\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this))+\"]\" }\n\t\t} );\n\t \n\t\ttoProtoTypes.set( Uint8Array.prototype, { external:true, name:\"u8\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Uint8ClampedArray.prototype, { external:true, name:\"uc8\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Int8Array.prototype, { external:true, name:\"s8\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Uint16Array.prototype, { external:true, name:\"u16\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Int16Array.prototype, { external:true, name:\"s16\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Uint32Array.prototype, { external:true, name:\"u32\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Int32Array.prototype, { external:true, name:\"s32\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\t/*\n\t\tif( typeof Uint64Array != \"undefined\" )\n\t\t\ttoProtoTypes.set( Uint64Array.prototype, { external:true, name:\"u64\"\n\t\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t\t} );\n\t\tif( typeof Int64Array != \"undefined\" )\n\t\t\ttoProtoTypes.set( Int64Array.prototype, { external:true, name:\"s64\"\n\t\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t\t} );\n\t\t*/\n\t\ttoProtoTypes.set( Float32Array.prototype, { external:true, name:\"f32\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Float64Array.prototype, { external:true, name:\"f64\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t\ttoProtoTypes.set( Float64Array.prototype, { external:true, name:\"f64\"\n\t\t , cb:function() { return \"[\"+getIdentifier(base64ArrayBuffer(this.buffer))+\"]\" }\n\t\t} );\n\t \n\t\ttoProtoTypes.set( RegExp.prototype, mapToJSOX = { external:true, name:\"regex\"\n\t\t , cb:function(o,stringifier){\n\t\t\t\treturn \"'\"+escape(this.source)+\"'\";\n\t\t\t}\n\t\t} );\n\t\tfromProtoTypes.set( \"regex\", { protoCon:RegExp, cb:function (field,val){\n\t\t\treturn new RegExp( this );\n\t\t} } );\n\n\t\ttoProtoTypes.set( Map.prototype, mapToJSOX = { external:true, name:\"map\"\n\t\t , cb:null\n\t\t} );\n\t\tfromProtoTypes.set( \"map\", { protoCon:Map, cb:function (field,val){\n\t\t\tif( field ) {\n\t\t\t\tthis.set( field, val );\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn this;\n\t\t} } );\n\t \n\t\ttoProtoTypes.set( Array.prototype, arrayToJSOX = { external:false, name:Array.prototype.constructor.name\n\t\t , cb: null\t\t \n\t\t} );\n\n\t}\n\n\tconst stringifier = {\n\t\tdefineClass(name,obj) { \n\t\t\tlet cls; \n\t\t\tlet denormKeys = Object.keys(obj);\n\t\t\tfor( let i = 1; i < denormKeys.length; i++ ) {\n\t\t\t\t// normalize class key order\n\t\t\t\tlet a, b;\n\t\t\t\tif( ( a = denormKeys[i-1] ) > ( b = denormKeys[i] ) ) {\n\t\t\t\t\tdenormKeys[i-1] = b;\n\t\t\t\t\tdenormKeys[i] = a;\n\t\t\t\t\tif( i ) i-=2; // go back 2, this might need to go further pack.\n\t\t\t\t\telse i--; // only 1 to check.\n\t\t\t\t}\n\t\t\t}\n\t\t\tclasses.push( cls = { name : name\n\t\t\t , tag:denormKeys.toString()\n\t\t\t , proto : Object.getPrototypeOf(obj)\n\t\t\t , fields : Object.keys(obj) } );\n\n\t\t\tfor(let n = 1; n < cls.fields.length; n++) {\n\t\t\t\tif( cls.fields[n] < cls.fields[n-1] ) {\n\t\t\t\t\tlet tmp = cls.fields[n-1];\n\t\t\t\t\tcls.fields[n-1] = cls.fields[n];\n\t\t\t\t\tcls.fields[n] = tmp;\n\t\t\t\t\tif( n > 1 )\n\t\t\t\t\t\tn-=2;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif( cls.proto === Object.getPrototypeOf( {} ) ) cls.proto = null;\n\t\t},\n\t\tsetDefaultObjectToJSOX( cb ) { objectToJSOX = cb },\n\t\tisEncoding(o) {\n\t\t\t//console.log( \"is object encoding?\", encoding.length, o, encoding );\n\t\t\treturn !!encoding.find( (eo,i)=>eo===o && i < (encoding.length-1) )\n\t\t},\n\t\tencodeObject(o) {\n\t\t\tif( objectToJSOX ) \n\t\t\t\treturn objectToJSOX.apply(o, [this]);\n\t\t\treturn o;\n\t\t},\n\t\tstringify(o,r,s) { return stringify(o,r,s) },\n\t\tsetQuote(q) { useQuote = q; },\n\t\tregisterToJSOX(n,p,f) { return this.toJSOX( n,p,f ) },\n\t\ttoJSOX( name, ptype, f ) {\n\t\t\tif( ptype.prototype && ptype.prototype !== Object.prototype ) {\n\t\t\t\tif( localToProtoTypes.get(ptype.prototype) ) throw new Error( \"Existing toJSOX has been registered for prototype\" );\n\t\t\t\tlocalToProtoTypes.set( ptype.prototype, { external:true, name:name||f.constructor.name, cb:f } );\n\t\t\t} else {\n\t\t\t\tlet key = Object.keys( ptype ).toString();\n\t\t\t\tif( localToObjectTypes.get(key) ) throw new Error( \"Existing toJSOX has been registered for object type\" );\n\t\t\t\tlocalToObjectTypes.set( key, { external:true, name:name, cb:f } );\n\t\t\t}\n\t\t},\n\t\tget ignoreNonEnumerable() { return ignoreNonEnumerable; },\n\t\tset ignoreNonEnumerable(val) { ignoreNonEnumerable = val; },\n\t}\n\treturn stringifier;\n\n\t/**\n\t * get a reference to a previously seen object\n\t * @param {any} here \n\t * @returns reference to existing object, or undefined if not found.\n\t */\n\tfunction getReference( here ) {\n\t\tif( here === null ) return undefined;\n\t\tlet field = fieldMap.get( here );\n\t\t//_DEBUG_STRINGIFY && console.log( \"path:\", _JSON.stringify(path), field );\n\t\tif( !field ) {\n\t\t\tfieldMap.set( here, _JSON.stringify(path) );\n\t\t\treturn undefined;\n\t\t}\n\t\treturn \"ref\"+field;\n\t}\n\n\n\t/**\n\t * find the prototype definition for a class\n\t * @param {object} o \n\t * @param {map} useK \n\t * @returns object\n\t */\n\tfunction matchObject(o,useK) {\n\t\tlet k;\n\t\tlet cls;\n\t\tlet prt = Object.getPrototypeOf(o);\n\t\tcls = classes.find( cls=>{\n\t\t\tif( cls.proto && cls.proto === prt ) return true;\n\t\t} );\n\t\tif( cls ) return cls;\n\n\t\tif( classes.length || commonClasses.length ) {\n\t\t\tif( useK ) {\n\t\t\t\tuseK = useK.map( v=>{ if( typeof v === \"string\" ) return v; else return undefined; } );\n\t\t\t\tk = useK.toString();\n\t\t\t} else {\n\t\t\t\tlet denormKeys = Object.keys(o);\n\t\t\t\tfor( let i = 1; i < denormKeys.length; i++ ) {\n\t\t\t\t\tlet a, b;\n\t\t\t\t\tif( ( a = denormKeys[i-1] ) > ( b = denormKeys[i] ) ) {\n\t\t\t\t\t\tdenormKeys[i-1] = b;\n\t\t\t\t\t\tdenormKeys[i] = a;\n\t\t\t\t\t\tif( i ) i-=2; // go back 2, this might need to go further pack.\n\t\t\t\t\t\telse i--; // only 1 to check.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tk = denormKeys.toString();\n\t\t\t}\n\t\t\tcls = classes.find( cls=>{\n\t\t\t\tif( cls.tag === k ) return true;\n\t\t\t} );\n\t\t\tif( !cls )\n\t\t\t\tcls = commonClasses.find( cls=>{\n\t\t\t\t\tif( cls.tag === k ) return true;\n\t\t\t\t} );\n\t\t}\n\t\treturn cls;\n\t}\n\n\t/**\n\t * Serialize an object to JSOX text.\n\t * @param {any} object \n\t * @param {(key:string,value:any)=>string} replacer \n\t * @param {string|number} space \n\t * @returns \n\t */\n\tfunction stringify( object, replacer, space ) {\n\t\tif( object === undefined ) return \"undefined\";\n\t\tif( object === null ) return;\n\t\tlet gap;\n\t\tlet indent;\n\t\tlet rep;\n\n\t\tlet i;\n\t\tconst spaceType = typeof space;\n\t\tconst repType = typeof replacer;\n\t\tgap = \"\";\n\t\tindent = \"\";\n\n\t\t// If the space parameter is a number, make an indent string containing that\n\t\t// many spaces.\n\n\t\tif (spaceType === \"number\") {\n\t\t\tfor (i = 0; i < space; i += 1) {\n\t\t\t\tindent += \" \";\n\t\t\t}\n\n\t\t// If the space parameter is a string, it will be used as the indent string.\n\t\t} else if (spaceType === \"string\") {\n\t\t\tindent = space;\n\t\t}\n\n\t\t// If there is a replacer, it must be a function or an array.\n\t\t// Otherwise, throw an error.\n\n\t\trep = replacer;\n\t\tif( replacer && repType !== \"function\"\n\t\t && ( repType !== \"object\"\n\t\t || typeof replacer.length !== \"number\"\n\t\t )) {\n\t\t\tthrow new Error(\"JSOX.stringify\");\n\t\t}\n\n\t\tpath.length = 0;\n\t\tfieldMap = new WeakMap();\n\n\t\tconst finalResult = str( \"\", {\"\":object} );\n\t\tcommonClasses.length = 0;\n\t\treturn finalResult;\n\n\t\t// from https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L181\n\t\tfunction str(key, holder) {\n\t\t\tvar mind = gap;\n\t\t\tconst doArrayToJSOX_ = arrayToJSOX.cb;\n\t\t\tconst mapToObject_ = mapToJSOX.cb;\t\t \n\t\t\tarrayToJSOX.cb = doArrayToJSOX;\n\t\t\tmapToJSOX.cb = mapToObject;\n\t\t\tconst v = str_(key,holder);\n\t\t\tarrayToJSOX.cb = doArrayToJSOX_;\n\t\t\tmapToJSOX.cb = mapToObject_;\n\t\t\treturn v;\n\n\t\t\tfunction doArrayToJSOX() {\n\t\t\t\tlet v;\n\t\t\t\tlet partial = [];\n\t\t\t\tlet thisNodeNameIndex = path.length;\n\n\t\t\t\t// The value is an array. Stringify every element. Use null as a placeholder\n\t\t\t\t// for non-JSOX values.\n\t\t\t\n\t\t\t\tfor (let i = 0; i < this.length; i += 1) {\n\t\t\t\t\tpath[thisNodeNameIndex] = i;\n\t\t\t\t\tpartial[i] = str(i, this) || \"null\";\n\t\t\t\t}\n\t\t\t\tpath.length = thisNodeNameIndex;\n\t\t\t\t//console.log( \"remove encoding item\", thisNodeNameIndex, encoding.length);\n\t\t\t\tencoding.length = thisNodeNameIndex;\n\t\t\t\n\t\t\t\t// Join all of the elements together, separated with commas, and wrap them in\n\t\t\t\t// brackets.\n\t\t\t\tv = ( partial.length === 0\n\t\t\t\t\t? \"[]\"\n\t\t\t\t\t: gap\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\"[\\n\"\n\t\t\t\t\t\t\t, gap\n\t\t\t\t\t\t\t, partial.join(\",\\n\" + gap)\n\t\t\t\t\t\t\t, \"\\n\"\n\t\t\t\t\t\t\t, mind\n\t\t\t\t\t\t\t, \"]\"\n\t\t\t\t\t\t].join(\"\")\n\t\t\t\t\t\t: \"[\" + partial.join(\",\") + \"]\" );\n\t\t\t\treturn v;\n\t\t\t} \n\t\t\tfunction mapToObject(){\n\t\t\t\t//_DEBUG_PARSING_DETAILS && console.log( \"---------- NEW MAP -------------\" );\n\t\t\t\tlet tmp = {tmp:null};\n\t\t\t\tlet out = '{'\n\t\t\t\tlet first = true;\n\t\t\t\t//console.log( \"CONVERT:\", map);\n\t\t\t\tfor (let [key, value] of this) {\n\t\t\t\t\t//console.log( \"er...\", key, value )\n\t\t\t\t\ttmp.tmp = value;\n\t\t\t\t\tlet thisNodeNameIndex = path.length;\n\t\t\t\t\tpath[thisNodeNameIndex] = key;\n\t\t\t\t\t\t\t\n\t\t\t\t\tout += (first?\"\":\",\") + getIdentifier(key) +':' + str(\"tmp\", tmp);\n\t\t\t\t\tpath.length = thisNodeNameIndex;\n\t\t\t\t\tfirst = false;\n\t\t\t\t}\n\t\t\t\tout += '}';\n\t\t\t\t//console.log( \"out is:\", out );\n\t\t\t\treturn out;\n\t\t\t}\n\n\t\t// Produce a string from holder[key].\n\t\tfunction str_(key, holder) {\n\n\t\t\tlet i; // The loop counter.\n\t\t\tlet k; // The member key.\n\t\t\tlet v; // The member value.\n\t\t\tlet length;\n\t\t\tlet partialClass;\n\t\t\tlet partial;\n\t\t\tlet thisNodeNameIndex = path.length;\n\t\t\tlet isValue = true;\n\t\t\tlet value = holder[key];\n\t\t\tlet isObject = (typeof value === \"object\");\n\t\t\tlet c;\n\n\t\t\tif( isObject && ( value !== null ) ) {\n\t\t\t\tif( objectToJSOX ){\n\t\t\t\t\tif( !stringifying.find( val=>val===value ) ) {\n\t\t\t\t\t\tstringifying.push( value );\n\t\t\t\t\t\tencoding[thisNodeNameIndex] = value;\n\t\t\t\t\t\tisValue = false;\n\t\t\t\t\t\tvalue = objectToJSOX.apply(value, [stringifier]);\n\t\t\t\t\t\t//console.log( \"Converted by object lookup -it's now a different type\"\n\t\t\t\t\t\t//\t, protoConverter, objectConverter );\n\t\t\t\t\t\tisObject = ( typeof value === \"object\" );\n\t\t\t\t\t\tstringifying.pop();\n\t\t\t\t\t\tencoding.length = thisNodeNameIndex;\n\t\t\t\t\t\tisObject = (typeof value === \"object\");\n\t\t\t\t\t}\n\t\t\t\t\t//console.log( \"Value convereted to:\", key, value );\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst objType = (value !== undefined && value !== null) && Object.getPrototypeOf( value );\n\t\t\t\n\t\t\tlet protoConverter = objType\n\t\t\t\t&& ( localToProtoTypes.get( objType ) \n\t\t\t\t|| toProtoTypes.get( objType ) \n\t\t\t\t|| null )\n\t\t\tlet objectConverter = !protoConverter && (value !== undefined && value !== null) \n\t\t\t\t&& ( localToObjectTypes.get( Object.keys( value ).toString() ) \n\t\t\t\t|| toObjectTypes.get( Object.keys( value ).toString() ) \n\t\t\t\t|| null )\n\n\t\t\t// If we were called with a replacer function, then call the replacer to\n\t\t\t// obtain a replacement value.\n\n\t\t\tif (typeof rep === \"function\") {\n\t\t\t\tisValue = false;\n\t\t\t\tvalue = rep.call(holder, key, value);\n\t\t\t}\n\t\t\t\t//console.log( \"PROTOTYPE:\", Object.getPrototypeOf( value ) )\n\t\t\t\t//console.log( \"PROTOTYPE:\", toProtoTypes.get(Object.getPrototypeOf( value )) )\n\t\t\t\t//if( protoConverter )\n\t\t\t//_DEBUG_STRINGIFY && console.log( \"TEST()\", value, protoConverter, objectConverter );\n\n\t\t\tlet toJSOX = ( protoConverter && protoConverter.cb ) \n\t\t\t || ( objectConverter && objectConverter.cb );\n\t\t\t// If the value has a toJSOX method, call it to obtain a replacement value.\n\t\t\t//_DEBUG_STRINGIFY && console.log( \"type:\", typeof value, protoConverter, !!toJSOX, path );\n\n\t\t\tif( value !== undefined\n\t\t\t && value !== null\n\t\t\t\t&& typeof value === \"object\"\n\t\t\t && typeof toJSOX === \"function\"\n\t\t\t) {\n\t\t\t\tif( !stringifying.find( val=>val===value ) ) {\n\t\t\t\t\tif( typeof value === \"object\" ) {\n\t\t\t\t\t\tv = getReference( value );\n\t\t\t\t\t\tif( v )\treturn v;\n\t\t\t\t\t}\n\n\t\t\t\t\tstringifying.push( value );\n\t\t\t\t\tencoding[thisNodeNameIndex] = value;\n\t\t\t\t\tvalue = toJSOX.call(value, stringifier);\n\t\t\t\t\tisValue = false;\n\t\t\t\t\tstringifying.pop();\n\t\t\t\t\tif( protoConverter && protoConverter.name ) {\n\t\t\t\t\t\t// stringify may return a unquoted string\n\t\t\t\t\t\t// which needs an extra space betwen its tag and value.\n\t\t\t\t\t\tif( \"string\" === typeof value \n\t\t\t\t\t\t\t&& value[0] !== '-'\n\t\t\t\t\t\t\t&& (value[0] < '0' || value[0] > '9' )\n\t\t\t\t\t\t\t&& value[0] !== '\"'\n\t\t\t\t\t\t\t&& value[0] !== '\\'' \n\t\t\t\t\t\t\t&& value[0] !== '`' \n\t\t\t\t\t\t\t&& value[0] !== '[' \n\t\t\t\t\t\t\t&& value[0] !== '{' \n\t\t\t\t\t\t\t){\n\t\t\t\t\t\t\tvalue = ' ' + value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//console.log( \"Value converted:\", value );\n\t\t\t\t\tencoding.length = thisNodeNameIndex;\n\t\t\t\t} else {\n\t\t\t\t\tv = getReference( value );\n\t\t\t\t}\n\t\t} else \n\t\t\t\tif( typeof value === \"object\" ) {\n\t\t\t\t\tv = getReference( value );\n\t\t\t\t\tif( v ) return v;\n\t\t\t\t}\n\n\t\t\t// What happens next depends on the value's type.\n\t\t\tswitch (typeof value) {\n\t\t\tcase \"bigint\":\n\t\t\t\treturn value + 'n';\n\t\t\tcase \"string\":\n\t\t\t\t{\n\t\t\t\t\t//console.log( `Value was converted before? [${value}]`);\n\t\t\t\t\tvalue = isValue?getIdentifier(value):value;\n\t\t\t\t\tlet c = '';\n\t\t\t\t\tif( key===\"\" )\n\t\t\t\t\t\tc = classes.map( cls=> cls.name+\"{\"+cls.fields.join(\",\")+\"}\" ).join(gap?\"\\n\":\"\")+\n\t\t\t\t\t\t commonClasses.map( cls=> cls.name+\"{\"+cls.fields.join(\",\")+\"}\" ).join(gap?\"\\n\":\"\")\n\t\t\t\t\t\t\t\t+(gap?\"\\n\":\"\");\n\t\t\t\t\tif( protoConverter && protoConverter.external ) \n\t\t\t\t\t\treturn c + protoConverter.name + value;\n\t\t\t\t\tif( objectConverter && objectConverter.external ) \n\t\t\t\t\t\treturn c + objectConverter.name + value;\n\t\t\t\t\treturn c + value;//useQuote+JSOX.escape( value )+useQuote;\n\t\t\t\t}\n\t\t\tcase \"number\":\n\t\t\tcase \"boolean\":\n\t\t\tcase \"null\":\n\n\t\t\t\t// If the value is a boolean or null, convert it to a string. Note:\n\t\t\t\t// typeof null does not produce \"null\". The case is included here in\n\t\t\t\t// the remote chance that this gets fixed someday.\n\n\t\t\t\treturn String(value);\n\n\t\t\t\t// If the type is \"object\", we might be dealing with an object or an array or\n\t\t\t\t// null.\n\n\t\t\tcase \"object\":\n\t\t\t\t//_DEBUG_STRINGIFY && console.log( \"ENTERINT OBJECT EMISSION WITH:\", v );\n\t\t\t\tif( v ) return \"ref\"+v;\n\n\t\t\t\t// Due to a specification blunder in ECMAScript, typeof null is \"object\",\n\t\t\t\t// so watch out for that case.\n\t\t\t\tif (!value) {\n\t\t\t\t\treturn \"null\";\n\t\t\t\t}\n\n\t\t\t\t// Make an array to hold the partial results of stringifying this object value.\n\t\t\t\tgap += indent;\n\t\t\t\tpartialClass = null;\n\t\t\t\tpartial = [];\n\n\t\t\t\t// If the replacer is an array, use it to select the members to be stringified.\n\t\t\t\tif (rep && typeof rep === \"object\") {\n\t\t\t\t\tlength = rep.length;\n\t\t\t\t\tpartialClass = matchObject( value, rep );\n\t\t\t\t\tfor (i = 0; i < length; i += 1) {\n\t\t\t\t\t\tif (typeof rep[i] === \"string\") {\n\t\t\t\t\t\t\tk = rep[i];\n\t\t\t\t\t\t\tpath[thisNodeNameIndex] = k;\n\t\t\t\t\t\t\tv = str(k, value);\n\n\t\t\t\t\t\t\tif (v !== undefined ) {\n\t\t\t\t\t\t\t\tif( partialClass ) {\n\t\t\t\t\t\t\t\t\tpartial.push(v);\n\t\t\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t\t\tpartial.push( getIdentifier(k) \n\t\t\t\t\t\t\t\t\t+ (\n\t\t\t\t\t\t\t\t\t\t(gap)\n\t\t\t\t\t\t\t\t\t\t\t? \": \"\n\t\t\t\t\t\t\t\t\t\t\t: \":\"\n\t\t\t\t\t\t\t\t\t) + v);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpath.splice( thisNodeNameIndex, 1 );\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise, iterate through all of the keys in the object.\n\t\t\t\t\tpartialClass = matchObject( value );\n\t\t\t\t\tlet keys = [];\n\t\t\t\t\tfor (k in value) {\n\t\t\t\t\t\tif( ignoreNonEnumerable )\n\t\t\t\t\t\t\tif( !Object.prototype.propertyIsEnumerable.call( value, k ) ){\n\t\t\t\t\t\t\t\t//_DEBUG_STRINGIFY && console.log( \"skipping non-enuerable?\", k );\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\tlet n;\n\t\t\t\t\t\t\tfor( n = 0; n < keys.length; n++ ) \n\t\t\t\t\t\t\t\tif( keys[n] > k ) {\t\n\t\t\t\t\t\t\t\t\tkeys.splice(n,0,k );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif( n == keys.length )\n\t\t\t\t\t\t\t\tkeys.push(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor(let n = 0; n < keys.length; n++) {\n\t\t\t\t\t\tk = keys[n];\n\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\tpath[thisNodeNameIndex] = k;\n\t\t\t\t\t\t\tv = str(k, value);\n\n\t\t\t\t\t\t\tif (v !== undefined ) {\n\t\t\t\t\t\t\t\tif( partialClass ) {\n\t\t\t\t\t\t\t\t\tpartial.push(v);\n\t\t\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t\t\tpartial.push(getIdentifier(k) + (\n\t\t\t\t\t\t\t\t\t\t(gap)\n\t\t\t\t\t\t\t\t\t\t\t? \": \"\n\t\t\t\t\t\t\t\t\t\t\t: \":\"\n\t\t\t\t\t\t\t\t\t) + v);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpath.splice( thisNodeNameIndex, 1 );\n\t\t\t\t}\n\n\t\t\t\t// Join all of the member texts together, separated with commas,\n\t\t\t\t// and wrap them in braces.\n\t\t\t\t//_DEBUG_STRINGIFY && console.log( \"partial:\", partial )\n\n\t\t\t\t//let c;\n\t\t\t\tif( key===\"\" )\n\t\t\t\t\tc = ( classes.map( cls=> cls.name+\"{\"+cls.fields.join(\",\")+\"}\" ).join(gap?\"\\n\":\"\")\n\t\t\t\t\t\t|| commonClasses.map( cls=> cls.name+\"{\"+cls.fields.join(\",\")+\"}\" ).join(gap?\"\\n\":\"\"))+(gap?\"\\n\":\"\");\n\t\t\t\telse\n\t\t\t\t\tc = '';\n\n\t\t\t\tif( protoConverter && protoConverter.external ) \n\t\t\t\t\tc = c + getIdentifier(protoConverter.name);\n\n\t\t\t\t//_DEBUG_STRINGIFY && console.log( \"PREFIX FOR THIS FIELD:\", c );\n\t\t\t\tlet ident = null;\n\t\t\t\tif( partialClass )\n\t\t\t\t\tident = getIdentifier( partialClass.name ) ;\n\t\t\t\tv = c +\n\t\t\t\t\t( partial.length === 0\n\t\t\t\t\t? \"{}\"\n\t\t\t\t\t: gap\n\t\t\t\t\t\t\t? (partialClass?ident:\"\")+\"{\\n\" + gap + partial.join(\",\\n\" + gap) + \"\\n\" + mind + \"}\"\n\t\t\t\t\t\t\t: (partialClass?ident:\"\")+\"{\" + partial.join(\",\") + \"}\"\n\t\t\t\t\t);\n\n\t\t\t\tgap = mind;\n\t\t\t\treturn v;\n\t\t\t}\n\t\t}\n\t}\n\n\t}\n}\n\n\t// Converts an ArrayBuffer directly to base64, without any intermediate 'convert to string then\n\t// use window.btoa' step. According to my tests, this appears to be a faster approach:\n\t// http://jsperf.com/encoding-xhr-image-data/5\n\t// doesn't have to be reversable....\n\tconst encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_'\n\tconst decodings = { '~':-1\n\t\t,'=':-1\n\t\t,'$':62\n\t\t,'_':63\n\t\t,'+':62\n\t\t,'-':62\n\t\t,'.':62\n\t\t,'/':63\n\t\t,',':63\n\t};\n\t\n\tfor( let x = 0; x < encodings.length; x++ ) {\n\t\tdecodings[encodings[x]] = x;\n\t}\n\tObject.freeze( decodings );\n\t\n\tfunction base64ArrayBuffer(arrayBuffer) {\n\t\tlet base64 = ''\n\t\n\t\tlet bytes = new Uint8Array(arrayBuffer)\n\t\tlet byteLength = bytes.byteLength\n\t\tlet byteRemainder = byteLength % 3\n\t\tlet mainLength = byteLength - byteRemainder\n\t\n\t\tlet a, b, c, d\n\t\tlet chunk\n\t\t//throw \"who's using this?\"\n\t\t//console.log( \"buffer..\", arrayBuffer )\n\t\t// Main loop deals with bytes in chunks of 3\n\t\tfor (let i = 0; i < mainLength; i = i + 3) {\n\t\t\t// Combine the three bytes into a single integer\n\t\t\tchunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]\n\n\t\t\t// Use bitmasks to extract 6-bit segments from the triplet\n\t\t\ta = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18\n\t\t\tb = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12\n\t\t\tc = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6\n\t\t\td = chunk & 63 // 63 = 2^6 - 1\n\t\n\t\t\t// Convert the raw binary segments to the appropriate ASCII encoding\n\t\t\tbase64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]\n\t\t}\n\t\n\t// Deal with the remaining bytes and padding\n\t\tif (byteRemainder == 1) {\n\t\t\tchunk = bytes[mainLength]\n\t\t\ta = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2\n\t\t\t// Set the 4 least significant bits to zero\n\t\t\tb = (chunk & 3) << 4 // 3 = 2^2 - 1\n\t\t\tbase64 += encodings[a] + encodings[b] + '=='\n\t\t} else if (byteRemainder == 2) {\n\t\t\tchunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]\n\t\t\ta = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10\n\t\t\tb = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4\n\t\t\t// Set the 2 least significant bits to zero\n\t\t\tc = (chunk & 15) << 2 // 15 = 2^4 - 1\n\t\t\tbase64 += encodings[a] + encodings[b] + encodings[c] + '='\n\t\t}\n\t\t//console.log( \"dup?\", base64)\n\t\treturn base64\n\t}\n\t\n\t\n\tfunction DecodeBase64( buf ) {\t\n\t\tlet outsize;\n\t\tif( buf.length % 4 == 1 )\n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 3;\n\t\telse if( buf.length % 4 == 2 )\n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 2;\n\t\telse if( buf.length % 4 == 3 )\n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 1;\n\t\telse if( decodings[buf[buf.length - 3]] == -1 )\n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 3;\n\t\telse if( decodings[buf[buf.length - 2]] == -1 ) \n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 2;\n\t\telse if( decodings[buf[buf.length - 1]] == -1 ) \n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3) - 1;\n\t\telse\n\t\t\toutsize = ((((buf.length + 3) / 4)|0) * 3);\n\t\tlet ab = new ArrayBuffer( outsize );\n\t\tlet out = new Uint8Array(ab);\n\n\t\tlet n;\n\t\tlet l = (buf.length+3)>>2;\n\t\tfor( n = 0; n < l; n++ ) {\n\t\t\tlet index0 = decodings[buf[n*4]];\n\t\t\tlet index1 = (n*4+1)<buf.length?decodings[buf[n*4+1]]:-1;\n\t\t\tlet index2 = (index1>=0) && (n*4+2)<buf.length?decodings[buf[n*4+2]]:-1 || 0;\n\t\t\tlet index3 = (index2>=0) && (n*4+3)<buf.length?decodings[buf[n*4+3]]:-1 || 0;\n\t\t\tif( index1 >= 0 )\n\t\t\t\tout[n*3+0] = (( index0 ) << 2 | ( index1 ) >> 4);\n\t\t\tif( index2 >= 0 )\n\t\t\t\tout[n*3+1] = (( index1 ) << 4 | ( ( ( index2 ) >> 2 ) & 0x0f ));\n\t\t\tif( index3 >= 0 )\n\t\t\t\tout[n*3+2] = (( index2 ) << 6 | ( ( index3 ) & 0x3F ));\n\t\t}\n\n\t\treturn ab;\n\t}\n\t\n/**\n * @param {unknown} object \n * @param {(this: unknown, key: string, value: unknown)} [replacer] \n * @param {string | number} [space] \n * @returns {string}\n */\t\nJSOX.stringify = function( object, replacer, space ) {\n\tlet stringifier = JSOX.stringifier();\n\treturn stringifier.stringify( object, replacer, space );\n}\n\nconst nonIdent = \n[ [ 0,256,[ 0xffd9ff,0xff6aff,0x1fc00,0x380000,0x0,0xfffff8,0xffffff,0x7fffff] ]\n].map( row=>{ return{ firstChar : row[0], lastChar: row[1], bits : row[2] }; } );\n\n//} privateizeEverything();\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9ub2RlX21vZHVsZXMvLnBucG0vanNveEAxLjIuMTIxL25vZGVfbW9kdWxlcy9qc294L2xpYi9qc294Lm1qcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUE7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0NBQWdDO0FBQ2hDOztBQUVBLGtCQUFrQixrREFBa0Q7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0EsMkNBQTJDLDhCQUE4QjtBQUN6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvRUFBb0Usd0JBQXdCOztBQUU1RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1COztBQUVuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUIseUJBQXlCLG1CQUFt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Q0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBLDhFQUE4RSxDQUFFO0FBQ2hGLDhFQUE4RSxDQUFFO0FBQ2hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLFdBQVcsOENBQThDO0FBQ3pELFdBQVcsaUJBQWlCO0FBQzVCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLFFBQVEseURBQXlEOztBQUUvRSxJQUFJO0FBQ1MiLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXJjbWludGVsL1Byb2plY3RzL2UtdGliLmNvbS9ub2RlX21vZHVsZXMvLnBucG0vanNveEAxLjIuMTIxL25vZGVfbW9kdWxlcy9qc294L2xpYi9qc294Lm1qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvL1widXNlIHN0cmljdFwiO1xuLy8ganNveC5qc1xuLy8gSlNPWCBKYXZhU2NyaXB0IE9iamVjdCBlWGNoYW5nZS4gSW5oZXJpdHMgaHVtYW4gZmVhdHVyZXMgb2YgY29tbWVudHNcbi8vIGFuZCBleHRlbmRlZCBmb3JtYXR0aW5nIGZyb20gSlNPTjY7IGFkZHMgbWFjcm9zLCBiaWcgbnVtYmVyIGFuZCBkYXRlXG4vLyBzdXBwb3J0LiAgU2VlIFJFQURNRS5tZCBmb3IgZGV0YWlscy5cbi8vXG4vLyBUaGlzIGZpbGUgaXMgYmFzZWQgb2ZmIG9mIGh0dHBzOi8vZ2l0aHViLmNvbS9KU09ONi8gIC4vbGliL2pzb242LmpzXG4vLyB3aGljaCBpcyBiYXNlZCBvZmYgb2YgaHR0cHM6Ly9naXRodWIuY29tL2QzeDByL3NhY2sgIC4vc3JjL25ldGxpYi9odG1sNS53ZWJzb2NrZXQvanNvbjZfcGFyc2VyLmNcbi8vXG5cbi8vY29uc3QgdXRpbCA9IHJlcXVpcmUoJ3V0aWwnKTsgLy8gZGVidWcgaW5zcGVjdC5cbi8vaW1wb3J0IHV0aWwgZnJvbSAndXRpbCc7IFxuXG5jb25zdCBfSlNPTj1KU09OOyAvLyBpbiBjYXNlIHNvbWVvbmUgZG9lcyBzb21ldGhpbmcgbGlrZSBKU09OPUpTT1g7IHdlIHN0aWxsIG5lZWQgYSBwcmltaXRpdmUgX0pTT04gZm9yIGludGVybmFsIHN0cmluZ2lmaWNhdGlvblxuaWYoIFwidW5kZWZpbmVkXCIgPT09IHR5cGVvZiBleHBvcnRzIClcblx0dmFyIGV4cG9ydHMgPSB7fTtcbmNvbnN0IEpTT1ggPSBleHBvcnRzIHx8IHt9O1xuZXhwb3J0cy5KU09YID0gSlNPWDtcblxuSlNPWC52ZXJzaW9uID0gXCIxLjIuMTIxXCI7XG5cbi8vZnVuY3Rpb24gcHJpdmF0ZWl6ZUV2ZXJ5dGhpbmcoKSB7XG4vL2NvbnN0IF9ERUJVR19MTCA9IGZhbHNlO1xuLy9jb25zdCBfREVCVUdfUEFSU0lORyA9IGZhbHNlO1xuLy9jb25zdCBfREVCVUdfU1RSSU5HSUZZID0gZmFsc2U7XG4vL2NvbnN0IF9ERUJVR19QQVJTSU5HX1NUQUNLID0gZmFsc2U7XG4vL2NvbnN0IF9ERUJVR19QQVJTSU5HX05VTUJFUlMgPSBmYWxzZTtcbi8vY29uc3QgX0RFQlVHX1BBUlNJTkdfREVUQUlMUyA9IGZhbHNlO1xuLy9jb25zdCBfREVCVUdfUEFSU0lOR19DT05URVhUID0gZmFsc2U7XG4vL2NvbnN0IF9ERUJVR19SRUZFUkVOQ0VTID0gZmFsc2U7IC8vIHRoaXMgdHJhY2tzIGZvbGxpbmcgY29udGV4dCBzdGFjayB3aGVuIHRoZSBjb21wb25lbnRzIGhhdmUgbm90IGJlZW4gY29tcGxldGVkLlxuLy9jb25zdCBfREVCVUdfV0hJVEVTUEFDRSA9IGZhbHNlOyBcbmNvbnN0IGhhc0JpZ0ludCA9ICh0eXBlb2YgQmlnSW50ID09PSBcImZ1bmN0aW9uXCIpO1xuY29uc3QgdGVzdE5vbklkZW50aWZpZXJDaGFyYWN0ZXJzID0gZmFsc2U7IC8vIG1heWJlIGFuIG9wdGlvbiB0byBlbmFibGU7IHJlZmVyZW5jZXMgb3RoZXJ3aXNlIHVudXNlZCB0YWJsZS5cbmNvbnN0IFZBTFVFX1VOREVGSU5FRCA9IC0xXG5jb25zdCBWQUxVRV9VTlNFVCA9IDBcbmNvbnN0IFZBTFVFX05VTEwgPSAxXG5jb25zdCBWQUxVRV9UUlVFID0gMlxuY29uc3QgVkFMVUVfRkFMU0UgPSAzXG5jb25zdCBWQUxVRV9TVFJJTkcgPSA0XG5jb25zdCBWQUxVRV9OVU1CRVIgPSA1XG5jb25zdCBWQUxVRV9PQkpFQ1QgPSA2XG5jb25zdCBWQUxVRV9ORUdfTkFOID0gN1xuY29uc3QgVkFMVUVfTkFOID0gOFxuY29uc3QgVkFMVUVfTkVHX0lORklOSVRZID0gOVxuY29uc3QgVkFMVUVfSU5GSU5JVFkgPSAxMFxuLy9jb25zdCBWQUxVRV9EQVRFID0gMTEgIC8vIHVudXNlZCB5ZXQ7IHRoaXMgaXMgYWN0dWFsbCBhIHN1YlR5cGUgb2YgVkFMVUVfTlVNQkVSXG5jb25zdCBWQUxVRV9FTVBUWSA9IDEyIC8vIFssXSBtYWtlcyBhbiBhcnJheSB3aXRoICdlbXB0eSBpdGVtJ1xuY29uc3QgVkFMVUVfQVJSQVkgPSAxMyAvL1xuLy8gaW50ZXJuYWxseSBhcnJheVR5cGUgPSAtMSBpcyBhIG5vcm1hbCBhcnJheVxuLy8gYXJyYXlUeXBlID0gLTIgaXMgYSByZWZlcmVuY2UgYXJyYXksIHdoaWNoLCB3aGljaCBjbG9zZWQgaXMgcmVzb2x2ZWQgdG9cbi8vICAgICB0aGUgc3BlY2lmaWVkIG9iamVjdC5cbi8vIGFycmF5VHlwZSA9IC0zIGlzIGEgbm9ybWFsIGFycmF5LCB0aGF0IGhhcyBhbHJlYWR5IGhhZCB0aGlzIGVsZW1lbnQgcHVzaGVkLlxuY29uc3Qga25vd25BcnJheVR5cGVOYW1lcyA9IFtcImFiXCIsXCJ1OFwiLFwiY3U4XCIsXCJzOFwiLFwidTE2XCIsXCJzMTZcIixcInUzMlwiLFwiczMyXCIsXCJ1NjRcIixcInM2NFwiLFwiZjMyXCIsXCJmNjRcIl07XG5sZXQgYXJyYXlUb0pTT1ggPSBudWxsO1xubGV0IG1hcFRvSlNPWCA9IG51bGw7XG5jb25zdCBrbm93bkFycmF5VHlwZXMgPSBbQXJyYXlCdWZmZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICxVaW50OEFycmF5LFVpbnQ4Q2xhbXBlZEFycmF5LEludDhBcnJheVxuICAgICAgICAgICAgICAgICAgICAgICAgLFVpbnQxNkFycmF5LEludDE2QXJyYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICxVaW50MzJBcnJheSxJbnQzMkFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAsbnVsbCxudWxsLy8sVWludDY0QXJyYXksSW50NjRBcnJheVxuICAgICAgICAgICAgICAgICAgICAgICAgLEZsb2F0MzJBcnJheSxGbG9hdDY0QXJyYXldO1xuLy8gc29tZWhvdyBtYXggaXNuJ3QgdXNlZC4uLiBpdCB3b3VsZCBiZSB0aGUgTkVYVCBhdmFpbGFibGUgVkFMVUVfWFhYIHZhbHVlLi4uXG4vL2NvbnN0IFZBTFVFX0FSUkFZX01BWCA9IFZBTFVFX0FSUkFZICsga25vd25BcnJheVR5cGVzLmxlbmd0aCArIDE7IC8vIDEgdHlwZSBpcyBub3QgdHlwZWQ7IGp1c3QgYW4gYXJyYXkuXG5cbmNvbnN0IFdPUkRfUE9TX1JFU0VUID0gMDtcbmNvbnN0IFdPUkRfUE9TX1RSVUVfMSA9IDE7XG5jb25zdCBXT1JEX1BPU19UUlVFXzIgPSAyO1xuY29uc3QgV09SRF9QT1NfVFJVRV8zID0gMztcbmNvbnN0IFdPUkRfUE9TX0ZBTFNFXzEgPSA1O1xuY29uc3QgV09SRF9QT1NfRkFMU0VfMiA9IDY7XG5jb25zdCBXT1JEX1BPU19GQUxTRV8zID0gNztcbmNvbnN0IFdPUkRfUE9TX0ZBTFNFXzQgPSA4O1xuY29uc3QgV09SRF9QT1NfTlVMTF8xID0gOTtcbmNvbnN0IFdPUkRfUE9TX05VTExfMiA9IDEwO1xuY29uc3QgV09SRF9QT1NfTlVMTF8zID0gMTE7XG5jb25zdCBXT1JEX1BPU19VTkRFRklORURfMSA9IDEyO1xuY29uc3QgV09SRF9QT1NfVU5ERUZJTkVEXzIgPSAxMztcbmNvbnN0IFdPUkRfUE9TX1VOREVGSU5FRF8zID0gMTQ7XG5jb25zdCBXT1JEX1BPU19VTkRFRklORURfNCA9IDE1O1xuY29uc3QgV09SRF9QT1NfVU5ERUZJTkVEXzUgPSAxNjtcbmNvbnN0IFdPUkRfUE9TX1VOREVGSU5FRF82ID0gMTc7XG5jb25zdCBXT1JEX1BPU19VTkRFRklORURfNyA9IDE4O1xuY29uc3QgV09SRF9QT1NfVU5ERUZJTkVEXzggPSAxOTtcbmNvbnN0IFdPUkRfUE9TX05BTl8xID0gMjA7XG5jb25zdCBXT1JEX1BPU19OQU5fMiA9IDIxO1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfMSA9IDIyO1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfMiA9IDIzO1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfMyA9IDI0O1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfNCA9IDI1O1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfNSA9IDI2O1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfNiA9IDI3O1xuY29uc3QgV09SRF9QT1NfSU5GSU5JVFlfNyA9IDI4O1xuXG5jb25zdCBXT1JEX1BPU19GSUVMRCA9IDI5O1xuY29uc3QgV09SRF9QT1NfQUZURVJfRklFTEQgPSAzMDtcbmNvbnN0IFdPUkRfUE9TX0VORCA9IDMxO1xuY29uc3QgV09SRF9QT1NfQUZURVJfRklFTERfVkFMVUUgPSAzMjtcbi8vY29uc3QgV09SRF9QT1NfQklOQVJZID0gMzI7XG5cbmNvbnN0IENPTlRFWFRfVU5LTk9XTiA9IDBcbmNvbnN0IENPTlRFWFRfSU5fQVJSQVkgPSAxXG5jb25zdCBDT05URVhUX09CSkVDVF9GSUVMRCA9IDJcbmNvbnN0IENPTlRFWFRfT0JKRUNUX0ZJRUxEX1ZBTFVFID0gM1xuY29uc3QgQ09OVEVYVF9DTEFTU19GSUVMRCA9IDRcbmNvbnN0IENPTlRFWFRfQ0xBU1NfVkFMVUUgPSA1XG5jb25zdCBDT05URVhUX0NMQVNTX0ZJRUxEX1ZBTFVFID0gNlxuY29uc3Qga2V5d29yZHMgPSB7XHRbXCJ0cnVlXCJdOnRydWUsW1wiZmFsc2VcIl06ZmFsc2UsW1wibnVsbFwiXTpudWxsLFtcIk5hTlwiXTpOYU4sW1wiSW5maW5pdHlcIl06SW5maW5pdHksW1widW5kZWZpbmVkXCJdOnVuZGVmaW5lZCB9XG5cbi8qXG5FeHRlbmQgRGF0ZSB0eXBlIHdpdGggYSBuYW5vc2Vjb25kIGZpZWxkLlxuKi9cbmNsYXNzIERhdGVOUyBleHRlbmRzIERhdGUge1xuXHRjb25zdHJ1Y3RvcihhLGIgKSB7XG5cdFx0c3VwZXIoYSk7XG5cdFx0dGhpcy5ucyA9IGJ8fDA7XG5cdH1cdFxufVxuXG5KU09YLkRhdGVOUyA9IERhdGVOUztcblxuY29uc3QgY29udGV4dHMgPSBbXTtcbmZ1bmN0aW9uIGdldENvbnRleHQoKSB7XG5cdGxldCBjdHggPSBjb250ZXh0cy5wb3AoKTtcblx0aWYoICFjdHggKVxuXHRcdGN0eCA9IHsgY29udGV4dCA6IENPTlRFWFRfVU5LTk9XTlxuXHRcdCAgICAgICwgY3VycmVudF9wcm90byA6IG51bGxcblx0XHQgICAgICAsIGN1cnJlbnRfY2xhc3MgOiBudWxsXG5cdFx0ICAgICAgLCBjdXJyZW50X2NsYXNzX2ZpZWxkIDogMFxuXHRcdCAgICAgICwgYXJyYXlUeXBlIDogLTFcblx0XHQgICAgICAsIHZhbHVlVHlwZSA6IFZBTFVFX1VOU0VUXG5cdFx0ICAgICAgLCBlbGVtZW50cyA6IG51bGxcblx0XHQgICAgICB9O1xuXHRyZXR1cm4gY3R4O1xufVxuZnVuY3Rpb24gZHJvcENvbnRleHQoY3R4KSB7IFxuXHRjb250ZXh0cy5wdXNoKCBjdHggKSBcbn1cblxuSlNPWC51cGRhdGVDb250ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgLy9pZiggdG9Qcm90b1R5cGVzLmdldCggTWFwLnByb3RvdHlwZSApICkgcmV0dXJuO1xuICAgIC8vY29uc29sZS5sb2coIFwiRG8gaW5pdCBwcm90b3lwZXMgZm9yIG5ldyBjb250ZXh0IG9iamVjdHMuLi5cIiApO1xuICAgIC8vaW5pdFByb3RvdHlwZXMoKTtcbn1cblxuY29uc3QgYnVmZmVycyA9IFtdO1xuZnVuY3Rpb24gZ2V0QnVmZmVyKCkgeyBsZXQgYnVmID0gYnVmZmVycy5wb3AoKTsgaWYoICFidWYgKSBidWYgPSB7IGJ1ZjpudWxsLCBuOjAgfTsgZWxzZSBidWYubiA9IDA7IHJldHVybiBidWY7IH1cbmZ1bmN0aW9uIGRyb3BCdWZmZXIoYnVmKSB7IGJ1ZmZlcnMucHVzaCggYnVmICk7IH1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuSlNPWC5lc2NhcGUgPSBmdW5jdGlvbihzdHJpbmcpIHtcblx0bGV0IG47XG5cdGxldCBvdXRwdXQgPSAnJztcblx0aWYoICFzdHJpbmcgKSByZXR1cm4gc3RyaW5nO1xuXHRmb3IoIG4gPSAwOyBuIDwgc3RyaW5nLmxlbmd0aDsgbisrICkge1xuXHRcdGlmKCAoIHN0cmluZ1tuXSA9PSAnXCInICkgfHwgKCBzdHJpbmdbbl0gPT0gJ1xcXFwnICkgfHwgKCBzdHJpbmdbbl0gPT0gJ2AnICl8fCAoIHN0cmluZ1tuXSA9PSAnXFwnJyApKSB7XG5cdFx0XHRvdXRwdXQgKz0gJ1xcXFwnO1xuXHRcdH1cblx0XHRvdXRwdXQgKz0gc3RyaW5nW25dO1xuXHR9XG5cdHJldHVybiBvdXRwdXQ7XG59XG5cblxubGV0IHRvUHJvdG9UeXBlcyA9IG5ldyBXZWFrTWFwKCk7XG5sZXQgdG9PYmplY3RUeXBlcyA9IG5ldyBNYXAoKTtcbmxldCBmcm9tUHJvdG9UeXBlcyA9IG5ldyBNYXAoKTtcbmxldCBjb21tb25DbGFzc2VzID0gW107XG5cbkpTT1gucmVzZXQgPSByZXNldEpTT1g7XG5cbmZ1bmN0aW9uIHJlc2V0SlNPWCgpIHtcblx0dG9Qcm90b1R5cGVzID0gbmV3IFdlYWtNYXAoKTtcblx0dG9PYmplY3RUeXBlcyA9IG5ldyBNYXAoKTtcblx0ZnJvbVByb3RvVHlwZXMgPSBuZXcgTWFwKCk7XG5cdGNvbW1vbkNsYXNzZXMgPSBbXTtcdFxufVxuXG4vKipcbiAqIEBwYXJhbSB7KHZhbHVlOmFueSl9IFtjYl1cbiAqIEBwYXJhbSB7KHRoaXM6IHVua25vd24sIGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4gYW55fSBbcmV2aXZlcl0gXG4gKiBAcmV0dXJucyB7bm9uZX1cbiovXG5KU09YLmJlZ2luID0gZnVuY3Rpb24oIGNiLCByZXZpdmVyICkge1xuXG5cdGNvbnN0IHZhbCA9IHsgbmFtZSA6IG51bGwsXHQgIC8vIG5hbWUgb2YgdGhpcyB2YWx1ZSAoaWYgaXQncyBjb250YWluZWQgaW4gYW4gb2JqZWN0KVxuXHRcdFx0dmFsdWVfdHlwZTogVkFMVUVfVU5TRVQsIC8vIHZhbHVlIGZyb20gYWJvdmUgaW5kaWNpYXRpbmcgdGhlIHR5cGUgb2YgdGhpcyB2YWx1ZVxuXHRcdFx0c3RyaW5nIDogJycsICAgLy8gdGhlIHN0cmluZyB2YWx1ZSBvZiB0aGlzIHZhbHVlIChzdHJpbmdzIGFuZCBudW1iZXIgdHlwZXMgb25seSlcblx0XHRcdGNvbnRhaW5zIDogbnVsbCxcblx0XHRcdGNsYXNzTmFtZSA6IG51bGwsXG5cdFx0fTtcblx0XG5cdGNvbnN0IHBvcyA9IHsgbGluZToxLCBjb2w6MSB9O1xuXHRsZXRcdG4gPSAwO1xuXHRsZXQgICAgIHN0cjtcblx0bGV0XHRsb2NhbEZyb21Qcm90b1R5cGVzID0gbmV3IE1hcCgpO1xuXHRsZXRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVCxcblx0XHRzdGF0dXMgPSB0cnVlLFxuXHRcdHJlZGVmaW5lQ2xhc3MgPSBmYWxzZSxcblx0XHRuZWdhdGl2ZSA9IGZhbHNlLFxuXHRcdHJlc3VsdCA9IG51bGwsXG5cdFx0cm9vdE9iamVjdCA9IG51bGwsXG5cdFx0ZWxlbWVudHMgPSB1bmRlZmluZWQsXG5cdFx0Y29udGV4dF9zdGFjayA9IHtcblx0XHRcdGZpcnN0IDogbnVsbCxcblx0XHRcdGxhc3QgOiBudWxsLFxuXHRcdFx0c2F2ZWQgOiBudWxsLFxuXHRcdFx0cHVzaChub2RlKSB7XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfQ09OVEVYVCAmJiBjb25zb2xlLmxvZyggXCJwdXNoaW5nIGNvbnRleHQ6XCIsIG5vZGUgKTtcblx0XHRcdFx0bGV0IHJlY292ZXIgPSB0aGlzLnNhdmVkO1xuXHRcdFx0XHRpZiggcmVjb3ZlciApIHsgdGhpcy5zYXZlZCA9IHJlY292ZXIubmV4dDsgXG5cdFx0XHRcdFx0cmVjb3Zlci5ub2RlID0gbm9kZTsgXG5cdFx0XHRcdFx0cmVjb3Zlci5uZXh0ID0gbnVsbDsgXG5cdFx0XHRcdFx0cmVjb3Zlci5wcmlvciA9IHRoaXMubGFzdDsgfVxuXHRcdFx0XHRlbHNlIHsgcmVjb3ZlciA9IHsgbm9kZSA6IG5vZGUsIG5leHQgOiBudWxsLCBwcmlvciA6IHRoaXMubGFzdCB9OyB9XG5cdFx0XHRcdGlmKCAhdGhpcy5sYXN0ICkgdGhpcy5maXJzdCA9IHJlY292ZXI7XG5cdFx0XHRcdGVsc2UgdGhpcy5sYXN0Lm5leHQgPSByZWNvdmVyO1xuXHRcdFx0XHR0aGlzLmxhc3QgPSByZWNvdmVyO1xuXHRcdFx0XHR0aGlzLmxlbmd0aCsrO1xuXHRcdFx0fSxcblx0XHRcdHBvcCgpIHtcblx0XHRcdFx0bGV0IHJlc3VsdCA9IHRoaXMubGFzdDtcblx0XHRcdFx0Ly8gdGhyb3VnaCBub3JtYWwgdXNhZ2UgdGhpcyBsaW5lIGNhbiBuZXZlciBiZSB1c2VkLlxuXHRcdFx0XHQvL2lmKCAhcmVzdWx0ICkgcmV0dXJuIG51bGw7XG5cdFx0XHRcdGlmKCAhKHRoaXMubGFzdCA9IHJlc3VsdC5wcmlvciApICkgdGhpcy5maXJzdCA9IG51bGw7XG5cdFx0XHRcdHJlc3VsdC5uZXh0ID0gdGhpcy5zYXZlZDtcblx0XHRcdFx0aWYoIHRoaXMubGFzdCApIHRoaXMubGFzdC5uZXh0ID0gbnVsbDtcblx0XHRcdFx0aWYoICFyZXN1bHQubmV4dCApIHJlc3VsdC5maXJzdCA9IG51bGw7XG5cdFx0XHRcdHRoaXMuc2F2ZWQgPSByZXN1bHQ7XG5cdFx0XHRcdHRoaXMubGVuZ3RoLS07XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfQ09OVEVYVCAmJiBjb25zb2xlLmxvZyggXCJwb3BwaW5nIGNvbnRleHQ6XCIsIHJlc3VsdC5ub2RlICk7XG5cdFx0XHRcdHJldHVybiByZXN1bHQubm9kZTtcblx0XHRcdH0sXG5cdFx0XHRsZW5ndGggOiAwLFxuXHRcdFx0LypkdW1wKCkgeyAgLy8gLy9fREVCVUdfQ09OVEVYVF9TVEFDS1xuXHRcdFx0XHRjb25zb2xlLmxvZyggXCJTVEFDSyBMRU5HVEg6XCIsIHRoaXMubGVuZ3RoICk7XG5cdFx0XHRcdGxldCBjdXI9IHRoaXMuZmlyc3Q7XG5cdFx0XHRcdGxldCBsZXZlbCA9IDA7XG5cdFx0XHRcdHdoaWxlKCBjdXIgKSB7XG5cdFx0XHRcdFx0Y29uc29sZS5sb2coIFwiQ29udGV4dDpcIiwgbGV2ZWwsIGN1ci5ub2RlICk7XG5cdFx0XHRcdFx0bGV2ZWwrKztcblx0XHRcdFx0XHRjdXIgPSBjdXIubmV4dDtcblx0XHRcdFx0fVxuXHRcdFx0fSovXG5cdFx0fSxcblx0XHRjbGFzc2VzID0gW10sICAvLyBjbGFzcyB0ZW1wbGF0ZXMgdGhhdCBoYXZlIGJlZW4gZGVmaW5lZC5cblx0XHRwcm90b1R5cGVzID0ge30sXG5cdFx0Y3VycmVudF9wcm90byA9IG51bGwsICAvLyB0aGUgY3VycmVudCBjbGFzcyBiZWluZyBkZWZpbmVkIG9yIGJlaW5nIHJlZmVyZW5jZWQuXG5cdFx0Y3VycmVudF9jbGFzcyA9IG51bGwsICAvLyB0aGUgY3VycmVudCBjbGFzcyBiZWluZyBkZWZpbmVkIG9yIGJlaW5nIHJlZmVyZW5jZWQuXG5cdFx0Y3VycmVudF9jbGFzc19maWVsZCA9IDAsXG5cdFx0YXJyYXlUeXBlID0gLTEsICAvLyB0aGUgY3VycmVudCBjbGFzcyBiZWluZyBkZWZpbmVkIG9yIGJlaW5nIHJlZmVyZW5jZWQuXG5cdFx0cGFyc2VfY29udGV4dCA9IENPTlRFWFRfVU5LTk9XTixcblx0XHRjb21tZW50ID0gMCxcblx0XHRmcm9tSGV4ID0gZmFsc2UsXG5cdFx0ZGVjaW1hbCA9IGZhbHNlLFxuXHRcdGV4cG9uZW50ID0gZmFsc2UsXG5cdFx0ZXhwb25lbnRfc2lnbiA9IGZhbHNlLFxuXHRcdGV4cG9uZW50X2RpZ2l0ID0gZmFsc2UsXG5cdFx0aW5RdWV1ZSA9IHtcblx0XHRcdGZpcnN0IDogbnVsbCxcblx0XHRcdGxhc3QgOiBudWxsLFxuXHRcdFx0c2F2ZWQgOiBudWxsLFxuXHRcdFx0cHVzaChub2RlKSB7XG5cdFx0XHRcdGxldCByZWNvdmVyID0gdGhpcy5zYXZlZDtcblx0XHRcdFx0aWYoIHJlY292ZXIgKSB7IHRoaXMuc2F2ZWQgPSByZWNvdmVyLm5leHQ7IHJlY292ZXIubm9kZSA9IG5vZGU7IHJlY292ZXIubmV4dCA9IG51bGw7IHJlY292ZXIucHJpb3IgPSB0aGlzLmxhc3Q7IH1cblx0XHRcdFx0ZWxzZSB7IHJlY292ZXIgPSB7IG5vZGUgOiBub2RlLCBuZXh0IDogbnVsbCwgcHJpb3IgOiB0aGlzLmxhc3QgfTsgfVxuXHRcdFx0XHRpZiggIXRoaXMubGFzdCApIHRoaXMuZmlyc3QgPSByZWNvdmVyO1xuXHRcdFx0XHRlbHNlIHRoaXMubGFzdC5uZXh0ID0gcmVjb3Zlcjtcblx0XHRcdFx0dGhpcy5sYXN0ID0gcmVjb3Zlcjtcblx0XHRcdH0sXG5cdFx0XHRzaGlmdCgpIHtcblx0XHRcdFx0bGV0IHJlc3VsdCA9IHRoaXMuZmlyc3Q7XG5cdFx0XHRcdGlmKCAhcmVzdWx0ICkgcmV0dXJuIG51bGw7XG5cdFx0XHRcdGlmKCAhKHRoaXMuZmlyc3QgPSByZXN1bHQubmV4dCApICkgdGhpcy5sYXN0ID0gbnVsbDtcblx0XHRcdFx0cmVzdWx0Lm5leHQgPSB0aGlzLnNhdmVkOyB0aGlzLnNhdmVkID0gcmVzdWx0O1xuXHRcdFx0XHRyZXR1cm4gcmVzdWx0Lm5vZGU7XG5cdFx0XHR9LFxuXHRcdFx0dW5zaGlmdChub2RlKSB7XG5cdFx0XHRcdGxldCByZWNvdmVyID0gdGhpcy5zYXZlZDtcblx0XHRcdFx0Ly8gdGhpcyBpcyBhbHdheXMgdHJ1ZSBpbiB0aGlzIHVzYWdlLlxuXHRcdFx0XHQvL2lmKCByZWNvdmVyICkgeyBcblx0XHRcdFx0XHR0aGlzLnNhdmVkID0gcmVjb3Zlci5uZXh0OyByZWNvdmVyLm5vZGUgPSBub2RlOyByZWNvdmVyLm5leHQgPSB0aGlzLmZpcnN0OyByZWNvdmVyLnByaW9yID0gbnVsbDsgXG5cdFx0XHRcdC8vfVxuXHRcdFx0XHQvL2Vsc2UgeyByZWNvdmVyID0geyBub2RlIDogbm9kZSwgbmV4dCA6IHRoaXMuZmlyc3QsIHByaW9yIDogbnVsbCB9OyB9XG5cdFx0XHRcdGlmKCAhdGhpcy5maXJzdCApIHRoaXMubGFzdCA9IHJlY292ZXI7XG5cdFx0XHRcdHRoaXMuZmlyc3QgPSByZWNvdmVyO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Z2F0aGVyaW5nU3RyaW5nRmlyc3RDaGFyID0gbnVsbCxcblx0XHRnYXRoZXJpbmdTdHJpbmcgPSBmYWxzZSxcblx0XHRnYXRoZXJpbmdOdW1iZXIgPSBmYWxzZSxcblx0XHRzdHJpbmdFc2NhcGUgPSBmYWxzZSxcblx0XHRjcl9lc2NhcGVkID0gZmFsc2UsXG5cdFx0dW5pY29kZVdpZGUgPSBmYWxzZSxcblx0XHRzdHJpbmdVbmljb2RlID0gZmFsc2UsXG5cdFx0c3RyaW5nSGV4ID0gZmFsc2UsXG5cdFx0aGV4X2NoYXIgPSAwLFxuXHRcdGhleF9jaGFyX2xlbiA9IDAsXG5cdFx0Y29tcGxldGVkID0gZmFsc2UsXG5cdFx0ZGF0ZV9mb3JtYXQgPSBmYWxzZSxcblx0XHRpc0JpZ0ludCA9IGZhbHNlXG5cdFx0O1xuXG5cdGZ1bmN0aW9uIHRocm93RW5kRXJyb3IoIGxlYWRlciApIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoIGAke2xlYWRlcn0gYXQgJHtufSBbJHtwb3MubGluZX06JHtwb3MuY29sfV1gKTtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lIGEgY2xhc3MgdGhhdCBjYW4gYmUgdXNlZCB0byBkZXNlcmlhbGl6ZSBvYmplY3RzIG9mIHRoaXMgdHlwZS5cblx0XHQgKiBAcGFyYW0ge3N0cmluZ30gcHJvdG90eXBlTmFtZSBcblx0XHQgKiBAcGFyYW0ge3R5cGV9IG8gXG5cdFx0ICogQHBhcmFtIHsoYW55KT0+YW55fSBmIFxuXHRcdCAqL1xuXHRcdGZyb21KU09YKCBwcm90b3R5cGVOYW1lLCBvLCBmICkge1xuXHRcdFx0aWYoIGxvY2FsRnJvbVByb3RvVHlwZXMuZ2V0KHByb3RvdHlwZU5hbWUpICkgdGhyb3cgbmV3IEVycm9yKCBcIkV4aXN0aW5nIGZyb21KU09YIGhhcyBiZWVuIHJlZ2lzdGVyZWQgZm9yIHByb3RvdHlwZVwiICk7XG5cdFx0XHRmdW5jdGlvbiBwcml2YXRlUHJvdG8oKSB7IH1cblx0XHRcdGlmKCAhbyApIG8gPSBwcml2YXRlUHJvdG87XG5cdFx0XHRpZiggbyAmJiAhKFwiY29uc3RydWN0b3JcIiBpbiBvICkpe1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiUGxlYXNlIHBhc3MgYSBwcm90b3R5cGUgbGlrZSB0aGluZy4uLlwiKTtcblx0XHRcdH1cblx0XHRcdGxvY2FsRnJvbVByb3RvVHlwZXMuc2V0KCBwcm90b3R5cGVOYW1lLCB7IHByb3RvQ29uOm8ucHJvdG90eXBlLmNvbnN0cnVjdG9yLCBjYjpmIH0gKTtcblx0XHR9LFxuXHRcdHJlZ2lzdGVyRnJvbUpTT1goIHByb3RvdHlwZU5hbWUsIG8vKiwgZiovICkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcInJlZ2lzdGVyRnJvbUpTT1ggaXMgZGVwcmVjYXRlZCwgcGxlYXNlIHVwZGF0ZSB0byB1c2UgZnJvbUpTT1ggaW5zdGVhZDpcIiArIHByb3RvdHlwZU5hbWUgKyBvLnRvU3RyaW5nKCkgKTtcblx0XHR9LFxuXHRcdGZpbmFsRXJyb3IoKSB7XG5cdFx0XHRpZiggY29tbWVudCAhPT0gMCApIHsgLy8gbW9zdCBvZiB0aGUgdGltZSBldmVyeXRoaW5nJ3MgZ29vZC5cblx0XHRcdFx0aWYoIGNvbW1lbnQgPT09IDEgKSB0aHJvd0VuZEVycm9yKCBcIkNvbW1lbnQgYmVnYW4gYXQgZW5kIG9mIGRvY3VtZW50XCIgKTtcblx0XHRcdFx0aWYoIGNvbW1lbnQgPT09IDIgKSAvKmNvbnNvbGUubG9nKCBcIldhcm5pbmc6ICcvLycgY29tbWVudCB3aXRob3V0IGVuZCBvZiBsaW5lIGVuZGVkIGRvY3VtZW50XCIgKSovO1xuXHRcdFx0XHRpZiggY29tbWVudCA9PT0gMyApIHRocm93RW5kRXJyb3IoIFwiT3BlbiBjb21tZW50ICcvKicgaXMgbWlzc2luZyBjbG9zZSBhdCBlbmQgb2YgZG9jdW1lbnRcIiApO1xuXHRcdFx0XHRpZiggY29tbWVudCA9PT0gNCApIHRocm93RW5kRXJyb3IoIFwiSW5jb21wbGV0ZSAnLyogKicgY2xvc2UgYXQgZW5kIG9mIGRvY3VtZW50XCIgKTtcblx0XHRcdH1cblx0XHRcdGlmKCBnYXRoZXJpbmdTdHJpbmcgKSB0aHJvd0VuZEVycm9yKCBcIkluY29tcGxldGUgc3RyaW5nXCIgKTtcblx0XHR9LFxuXHRcdHZhbHVlKCkge1xuXHRcdFx0dGhpcy5maW5hbEVycm9yKCk7XG5cdFx0XHRsZXQgciA9IHJlc3VsdDtcblx0XHRcdHJlc3VsdCA9IHVuZGVmaW5lZDtcblx0XHRcdHJldHVybiByO1xuXHRcdH0sXG5cdFx0LyoqXG5cdFx0ICogUmVzZXQgdGhlIHBhcnNlciB0byBhIGJsYW5rIHN0YXRlLlxuXHRcdCAqL1xuXHRcdHJlc2V0KCkge1xuXHRcdFx0d29yZCA9IFdPUkRfUE9TX1JFU0VUO1xuXHRcdFx0c3RhdHVzID0gdHJ1ZTtcblx0XHRcdGlmKCBpblF1ZXVlLmxhc3QgKSBpblF1ZXVlLmxhc3QubmV4dCA9IGluUXVldWUuc2F2ZTtcblx0XHRcdGluUXVldWUuc2F2ZSA9IGluUXVldWUuZmlyc3Q7XG5cdFx0XHRpblF1ZXVlLmZpcnN0ID0gaW5RdWV1ZS5sYXN0ID0gbnVsbDtcblx0XHRcdGlmKCBjb250ZXh0X3N0YWNrLmxhc3QgKSBjb250ZXh0X3N0YWNrLmxhc3QubmV4dCA9IGNvbnRleHRfc3RhY2suc2F2ZTtcblx0XHRcdGNvbnRleHRfc3RhY2subGVuZ3RoID0gMDtcblx0XHRcdGNvbnRleHRfc3RhY2suc2F2ZSA9IGluUXVldWUuZmlyc3Q7XG5cdFx0XHRjb250ZXh0X3N0YWNrLmZpcnN0ID0gY29udGV4dF9zdGFjay5sYXN0ID0gbnVsbDsvLz0gW107XG5cdFx0XHRlbGVtZW50cyA9IHVuZGVmaW5lZDtcblx0XHRcdHBhcnNlX2NvbnRleHQgPSBDT05URVhUX1VOS05PV047XG5cdFx0XHRjbGFzc2VzID0gW107XG5cdFx0XHRwcm90b1R5cGVzID0ge307XG5cdFx0XHRjdXJyZW50X3Byb3RvID0gbnVsbDtcblx0XHRcdGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuXHRcdFx0Y3VycmVudF9jbGFzc19maWVsZCA9IDA7XG5cdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1VOU0VUO1xuXHRcdFx0dmFsLm5hbWUgPSBudWxsO1xuXHRcdFx0dmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0dmFsLmNsYXNzTmFtZSA9IG51bGw7XG5cdFx0XHRwb3MubGluZSA9IDE7XG5cdFx0XHRwb3MuY29sID0gMTtcblx0XHRcdG5lZ2F0aXZlID0gZmFsc2U7XG5cdFx0XHRjb21tZW50ID0gMDtcblx0XHRcdGNvbXBsZXRlZCA9IGZhbHNlO1xuXHRcdFx0Z2F0aGVyaW5nU3RyaW5nID0gZmFsc2U7XG5cdFx0XHRzdHJpbmdFc2NhcGUgPSBmYWxzZTsgIC8vIHN0cmluZyBzdHJpbmdFc2NhcGUgaW50cm9cblx0XHRcdGNyX2VzY2FwZWQgPSBmYWxzZTsgICAvLyBjYXJyYWlnZSByZXR1cm4gZXNjYXBlZFxuXHRcdFx0ZGF0ZV9mb3JtYXQgPSBmYWxzZTtcblx0XHRcdC8vc3RyaW5nVW5pY29kZSA9IGZhbHNlOyAgLy8gcmVhZGluZyBcXHVcblx0XHRcdC8vdW5pY29kZVdpZGUgPSBmYWxzZTsgIC8vIHJlYWRpbmcgXFx1e30gaW4gc3RyaW5nXG5cdFx0XHQvL3N0cmluZ0hleCA9IGZhbHNlOyAgLy8gcmVhZGluZyBcXHggaW4gc3RyaW5nXG5cdFx0fSxcblx0XHR1c2VQcm90b3R5cGUoY2xhc3NOYW1lLHByb3RvVHlwZSApIHsgcHJvdG9UeXBlc1tjbGFzc05hbWVdID0gcHJvdG9UeXBlOyB9LFxuXHRcdC8qKlxuXHRcdCAqIEFkZCBpbnB1dCB0byB0aGUgcGFyc2VyIHRvIGdldCBwYXJzZWQuXG5cdFx0ICogQHBhcmFtIHtzdHJpbmd9IG1zZyBcblx0XHQgKi9cblx0XHR3cml0ZShtc2cpIHtcblx0XHRcdGxldCByZXRjb2RlO1xuXHRcdFx0aWYgKHR5cGVvZiBtc2cgIT09IFwic3RyaW5nXCIgJiYgdHlwZW9mIG1zZyAhPT0gXCJ1bmRlZmluZWRcIikgbXNnID0gU3RyaW5nKG1zZyk7XG5cdFx0XHRpZiggIXN0YXR1cyApIHRocm93IG5ldyBFcnJvciggXCJQYXJzZXIgaXMgc3RpbGwgaW4gYW4gZXJyb3Igc3RhdGUsIHBsZWFzZSByZXNldCBiZWZvcmUgcmVzdW1pbmdcIiApO1xuXHRcdFx0Zm9yKCByZXRjb2RlID0gdGhpcy5fd3JpdGUobXNnLGZhbHNlKTsgcmV0Y29kZSA+IDA7IHJldGNvZGUgPSB0aGlzLl93cml0ZSgpICkge1xuXHRcdFx0XHRpZiggdHlwZW9mIHJldml2ZXIgPT09ICdmdW5jdGlvbicgKSAoZnVuY3Rpb24gd2Fsayhob2xkZXIsIGtleSkge1xuXHRcdFx0XHRcdGxldCBrLCB2LCB2YWx1ZSA9IGhvbGRlcltrZXldO1xuXHRcdFx0XHRcdGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG5cdFx0XHRcdFx0XHRmb3IgKGsgaW4gdmFsdWUpIHtcblx0XHRcdFx0XHRcdFx0aWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgaykpIHtcblx0XHRcdFx0XHRcdFx0XHR2ID0gd2Fsayh2YWx1ZSwgayk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHYgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFsdWVba10gPSB2O1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRkZWxldGUgdmFsdWVba107XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiByZXZpdmVyLmNhbGwoaG9sZGVyLCBrZXksIHZhbHVlKTtcblx0XHRcdFx0fSh7Jyc6IHJlc3VsdH0sICcnKSk7XG5cdFx0XHRcdHJlc3VsdCA9IGNiKCByZXN1bHQgKTtcblxuXHRcdFx0XHRpZiggcmV0Y29kZSA8IDIgKVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0LyoqXG5cdFx0ICogUGFyc2UgYSBzdHJpbmcgYW5kIHJldHVybiB0aGUgcmVzdWx0LlxuXHRcdCAqIEBwYXJhbSB7c3RyaW5nfSBtc2dcblx0XHQgKiBAcGFyYW0geyhrZXk6c3RyaW5nLHZhbHVlOmFueSk9PmFueX0gW3Jldml2ZXJdXG5cdFx0ICogQHJldHVybnMge2FueX1cblx0XHQgKi9cblx0XHRwYXJzZShtc2cscmV2aXZlcikge1xuXHRcdFx0aWYgKHR5cGVvZiBtc2cgIT09IFwic3RyaW5nXCIpIG1zZyA9IFN0cmluZyhtc2cpO1xuXHRcdFx0dGhpcy5yZXNldCgpO1xuXHRcdFx0Y29uc3Qgd3JpdGVSZXN1bHQgPSB0aGlzLl93cml0ZSggbXNnLCB0cnVlICk7XG5cdFx0XHRpZiggd3JpdGVSZXN1bHQgPiAwICkge1xuXHRcdFx0XHRpZiggd3JpdGVSZXN1bHQgPiAxICl7XG5cdFx0XHRcdFx0Ly8gcHJvYmFibHkgYSBjYXJyaWFnZSByZXR1cm4uXG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJFeHRyYSBkYXRhIGF0IGVuZCBvZiBtZXNzYWdlXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGxldCByZXN1bHQgPSB0aGlzLnZhbHVlKCk7XG5cdFx0XHRcdGlmKCAoIFwidW5kZWZpbmVkXCIgPT09IHR5cGVvZiByZXN1bHQgKSAmJiB3cml0ZVJlc3VsdCA+IDEgKXtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiUGVuZGluZyB2YWx1ZSBjb3VsZCBub3QgY29tcGxldGVcIik7XG5cdFx0XHRcdH1cblx0ICAgICAgICAgICAgICAgIFxuXHRcdFx0XHRyZXN1bHQgPSB0eXBlb2YgcmV2aXZlciA9PT0gJ2Z1bmN0aW9uJyA/IChmdW5jdGlvbiB3YWxrKGhvbGRlciwga2V5KSB7XG5cdFx0XHRcdFx0bGV0IGssIHYsIHZhbHVlID0gaG9sZGVyW2tleV07XG5cdFx0XHRcdFx0aWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdFx0XHRcdGZvciAoayBpbiB2YWx1ZSkge1xuXHRcdFx0XHRcdFx0XHRpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBrKSkge1xuXHRcdFx0XHRcdFx0XHRcdHYgPSB3YWxrKHZhbHVlLCBrKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAodiAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YWx1ZVtrXSA9IHY7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdGRlbGV0ZSB2YWx1ZVtrXTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHJldml2ZXIuY2FsbChob2xkZXIsIGtleSwgdmFsdWUpO1xuXHRcdFx0XHR9KHsnJzogcmVzdWx0fSwgJycpKSA6IHJlc3VsdDtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdDtcblx0XHRcdH1cblx0XHRcdHRoaXMuZmluYWxFcnJvcigpO1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblxuXHRcdFx0XG5cdFx0XHRyZXR1cm4gdGhpcy53cml0ZShtc2cgKTtcblx0XHR9LFxuXHRcdF93cml0ZShtc2csY29tcGxldGVfYXRfZW5kKSB7XG5cdFx0XHRsZXQgY0ludDtcblx0XHRcdGxldCBpbnB1dDtcblx0XHRcdGxldCBidWY7XG5cdFx0XHRsZXQgcmV0dmFsID0gMDtcblx0XHRcdGZ1bmN0aW9uIHRocm93RXJyb3IoIGxlYWRlciwgYyApIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBgJHtsZWFkZXJ9ICcke1N0cmluZy5mcm9tQ29kZVBvaW50KCBjICl9JyB1bmV4cGVjdGVkIGF0ICR7bn0gKG5lYXIgJyR7YnVmLnN1YnN0cihuPjQ/KG4tNCk6MCxuPjQ/Mzoobi0xKSl9WyR7U3RyaW5nLmZyb21Db2RlUG9pbnQoIGMgKX1dJHtidWYuc3Vic3RyKG4sIDEwKX0nKSBbJHtwb3MubGluZX06JHtwb3MuY29sfV1gKTtcblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gUkVTRVRfVkFMKCkgIHtcblx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9VTlNFVDtcblx0XHRcdFx0dmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0XHR2YWwuY29udGFpbnMgPSBudWxsO1xuXHRcdFx0XHQvL3ZhbC5jbGFzc05hbWUgPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiBjb252ZXJ0VmFsdWUoKSB7XG5cdFx0XHRcdGxldCBmcCA9IG51bGw7XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiQ09OVkVSVCBWQUw6XCIsIHZhbCApO1xuXHRcdFx0XHRzd2l0Y2goIHZhbC52YWx1ZV90eXBlICl7XG5cdFx0XHRcdGNhc2UgVkFMVUVfTlVNQkVSOlxuXHRcdFx0XHRcdC8vMTUwMjY3ODMzNzA0N1xuXHRcdFx0XHRcdGlmKCAoICggdmFsLnN0cmluZy5sZW5ndGggPiAxMyApIHx8ICggdmFsLnN0cmluZy5sZW5ndGggPT0gMTMgJiYgdmFsWzBdPicyJyApIClcblx0XHRcdFx0XHQgICAgJiYgIWRhdGVfZm9ybWF0ICYmICFleHBvbmVudF9kaWdpdCAmJiAhZXhwb25lbnRfc2lnbiAmJiAhZGVjaW1hbCApIHtcblx0XHRcdFx0XHRcdGlzQmlnSW50ID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYoIGlzQmlnSW50ICkgeyBpZiggaGFzQmlnSW50ICkgcmV0dXJuIEJpZ0ludCh2YWwuc3RyaW5nKTsgZWxzZSB0aHJvdyBuZXcgRXJyb3IoIFwibm8gYnVpbHRpbiBCaWdJbnQoKVwiLCAwICkgfVxuXHRcdFx0XHRcdGlmKCBkYXRlX2Zvcm1hdCApIHsgXG5cdFx0XHRcdFx0XHRjb25zdCByID0gdmFsLnN0cmluZy5tYXRjaCgvXFwuKFxcZFxcZFxcZFxcZCopLyApO1xuXHRcdFx0XHRcdFx0Y29uc3QgZnJhYyA9ICggciApPyggciApWzFdOm51bGw7XG5cdFx0XHRcdFx0XHRpZiggIWZyYWMgfHwgKGZyYWMubGVuZ3RoIDwgNCkgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IHIgPSBuZXcgRGF0ZSggdmFsLnN0cmluZyApOyBcblx0XHRcdFx0XHRcdFx0aWYoaXNOYU4oci5nZXRUaW1lKCkpKSB0aHJvd0Vycm9yKCBcIkJhZCBEYXRlIGZvcm1hdFwiLCBjSW50ICk7IHJldHVybiByOyAgXG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRsZXQgbnMgPSBmcmFjLnN1YnN0ciggMyApO1xuXHRcdFx0XHRcdFx0XHR3aGlsZSggbnMubGVuZ3RoIDwgNiApIG5zID0gbnMrJzAnO1xuXHRcdFx0XHRcdFx0XHRjb25zdCByID0gbmV3IERhdGVOUyggdmFsLnN0cmluZywgTnVtYmVyKG5zICkgKTsgXG5cdFx0XHRcdFx0XHRcdGlmKGlzTmFOKHIuZ2V0VGltZSgpKSkgdGhyb3dFcnJvciggXCJCYWQgRGF0ZU5TIGZvcm1hdFwiICsgcityLmdldFRpbWUoKSwgY0ludCApOyByZXR1cm4gcjsgIFxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Ly9jb25zdCByID0gbmV3IERhdGUoIHZhbC5zdHJpbmcgKTsgaWYoaXNOYU4oci5nZXRUaW1lKCkpKSB0aHJvd0Vycm9yKCBcIkJhZCBudW1iZXIgZm9ybWF0XCIsIGNJbnQgKTsgcmV0dXJuIHI7ICBcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuICAobmVnYXRpdmU/LTE6MSkgKiBOdW1iZXIoIHZhbC5zdHJpbmcgKTtcblx0XHRcdFx0Y2FzZSBWQUxVRV9TVFJJTkc6XG5cdFx0XHRcdFx0aWYoIHZhbC5jbGFzc05hbWUgKSB7XG5cdFx0XHRcdFx0XHRmcCA9IGxvY2FsRnJvbVByb3RvVHlwZXMuZ2V0KCB2YWwuY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0XHRpZiggIWZwIClcblx0XHRcdFx0XHRcdFx0ZnAgPSBmcm9tUHJvdG9UeXBlcy5nZXQoIHZhbC5jbGFzc05hbWUgKTtcblx0XHRcdFx0XHRcdGlmKCBmcCAmJiBmcC5jYiApIHtcblx0XHRcdFx0XHRcdFx0dmFsLmNsYXNzTmFtZSA9IG51bGw7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBmcC5jYi5jYWxsKCB2YWwuc3RyaW5nICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyAnW29iamVjdCBPYmplY3RdJyB0aHJvd3MgdGhpcyBlcnJvci5cblx0XHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIkRvdWJsZSBzdHJpbmcgZXJyb3IsIG5vIGNvbnN0cnVjdG9yIGZvcjogbmV3IFwiICsgdmFsLmNsYXNzTmFtZSArIFwiKFwiK3ZhbC5zdHJpbmcrXCIpXCIgKVxuXHRcdFx0XHRcdFx0fVx0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB2YWwuc3RyaW5nO1xuXHRcdFx0XHRjYXNlIFZBTFVFX1RSVUU6XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdGNhc2UgVkFMVUVfRkFMU0U6XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHRjYXNlIFZBTFVFX05FR19OQU46XG5cdFx0XHRcdFx0cmV0dXJuIC1OYU47XG5cdFx0XHRcdGNhc2UgVkFMVUVfTkFOOlxuXHRcdFx0XHRcdHJldHVybiBOYU47XG5cdFx0XHRcdGNhc2UgVkFMVUVfTkVHX0lORklOSVRZOlxuXHRcdFx0XHRcdHJldHVybiAtSW5maW5pdHk7XG5cdFx0XHRcdGNhc2UgVkFMVUVfSU5GSU5JVFk6XG5cdFx0XHRcdFx0cmV0dXJuIEluZmluaXR5O1xuXHRcdFx0XHRjYXNlIFZBTFVFX05VTEw6XG5cdFx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHRcdGNhc2UgVkFMVUVfVU5ERUZJTkVEOlxuXHRcdFx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0XHRcdGNhc2UgVkFMVUVfRU1QVFk6XG5cdFx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdFx0Y2FzZSBWQUxVRV9PQkpFQ1Q6XG5cdFx0XHRcdFx0aWYoIHZhbC5jbGFzc05hbWUgKSB7IFxuXHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcImNsYXNzIHJldml2ZXJcIiApO1xuXHRcdFx0XHRcdFx0ZnAgPSBsb2NhbEZyb21Qcm90b1R5cGVzLmdldCggdmFsLmNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdFx0aWYoICFmcCApXG5cdFx0XHRcdFx0XHRcdGZwID0gZnJvbVByb3RvVHlwZXMuZ2V0KCB2YWwuY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gbnVsbDtcblx0XHRcdFx0XHRcdGlmKCBmcCAmJiBmcC5jYiApIHJldHVybiB2YWwuY29udGFpbnMgPSBmcC5jYi5jYWxsKCB2YWwuY29udGFpbnMgKTsgXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB2YWwuY29udGFpbnM7XG5cdFx0XHRcdGNhc2UgVkFMVUVfQVJSQVk6XG5cdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIkFycmF5IGNvbnZlcnNpb246XCIsIGFycmF5VHlwZSwgdmFsLmNvbnRhaW5zICk7XG5cdFx0XHRcdFx0aWYoIGFycmF5VHlwZSA+PSAwICkge1xuXHRcdFx0XHRcdFx0bGV0IGFiO1xuXHRcdFx0XHRcdFx0aWYoIHZhbC5jb250YWlucy5sZW5ndGggKVxuXHRcdFx0XHRcdFx0XHRhYiA9IERlY29kZUJhc2U2NCggdmFsLmNvbnRhaW5zWzBdIClcblx0XHRcdFx0XHRcdGVsc2UgYWIgPSBEZWNvZGVCYXNlNjQoIHZhbC5zdHJpbmcgKTtcblx0XHRcdFx0XHRcdGlmKCBhcnJheVR5cGUgPT09IDAgKSB7XG5cdFx0XHRcdFx0XHRcdGFycmF5VHlwZSA9IC0xO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gYWI7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBuZXdhYiA9IG5ldyBrbm93bkFycmF5VHlwZXNbYXJyYXlUeXBlXSggYWIgKTtcblx0XHRcdFx0XHRcdFx0YXJyYXlUeXBlID0gLTE7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBuZXdhYjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYoIGFycmF5VHlwZSA9PT0gLTIgKSB7XG5cdFx0XHRcdFx0XHRsZXQgb2JqID0gcm9vdE9iamVjdDtcblx0XHRcdFx0XHRcdC8vbGV0IGN0eCA9IGNvbnRleHRfc3RhY2suZmlyc3Q7XG5cdFx0XHRcdFx0XHRsZXQgbHZsO1xuXHRcdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJSZXNvbHZpbmcgUmVmZXJlbmNlLi4uXCIsIGNvbnRleHRfc3RhY2subGVuZ3RoICk7XG5cdFx0XHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIi0tZWxlbWVudHMgYW5kIGFycmF5XCIsIGVsZW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGNvbnN0IHBhdGhsZW4gPSB2YWwuY29udGFpbnMubGVuZ3RoO1xuXHRcdFx0XHRcdFx0Zm9yKCBsdmwgPSAwOyBsdmwgPCBwYXRobGVuOyBsdmwrKyApIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgaWR4ID0gdmFsLmNvbnRhaW5zW2x2bF07XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiTG9va2luZyB1cCBpZHg6XCIsIGlkeCwgXCJvZlwiLCB2YWwuY29udGFpbnMsIFwiaW5cIiwgb2JqICk7XG5cdFx0XHRcdFx0XHRcdGxldCBuZXh0T2JqID0gb2JqW2lkeF07XG5cblx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAgJiYgY29uc29sZS5sb2coIFwiUmVzb2x2ZSBwYXRoOlwiLCBsdmwsIGlkeCxcImluXCIsIG9iaiwgY29udGV4dF9zdGFjay5sZW5ndGgsIHZhbC5jb250YWlucy50b1N0cmluZygpICk7XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiTkVYVCBPQkpFQ1Q6XCIsIG5leHRPYmogKTtcblx0XHRcdFx0XHRcdFx0aWYoICFuZXh0T2JqICkge1xuXHRcdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRcdGxldCBjdHggPSBjb250ZXh0X3N0YWNrLmZpcnN0O1xuXHRcdFx0XHRcdFx0XHRcdFx0bGV0IHAgPSAwO1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19DT05URVhUICYmIGNvbnRleHRfc3RhY2suZHVtcCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0d2hpbGUoIGN0eCAmJiBwIDwgcGF0aGxlbiAmJiBwIDwgY29udGV4dF9zdGFjay5sZW5ndGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNvbnN0IHRoaXNLZXkgPSB2YWwuY29udGFpbnNbcF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCAhY3R4Lm5leHQgfHwgdGhpc0tleSAhPT0gY3R4Lm5leHQubm9kZS5uYW1lICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrOyAgLy8gY2FuJ3QgZm9sbG93IGNvbnRleHQgc3RhY2sgYW55IGZ1cnRoZXIuLi4uIFxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiQ2hlY2tpbmcgY29udGV4dDpcIiwgb2JqLCBcInA9XCIscCwgXCJrZXk9XCIsdGhpc0tleSwgXCJjdHgoYW5kIC5uZXh0KT1cIix1dGlsLmluc3BlY3QoY3R4KSk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vY29uc29sZS5kaXIoY3R4LCB7IGRlcHRoOiBudWxsIH0pXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCBjdHgubmV4dCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiggXCJudW1iZXJcIiA9PT0gdHlwZW9mIHRoaXNLZXkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjb25zdCBhY3R1YWxPYmplY3QgPSBjdHgubmV4dC5ub2RlLmVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAmJiBjb25zb2xlLmxvZyggXCJOdW1iZXIgaW4gaW5kZXguLi4gdHJhY2luZyBzdGFjay4uLlwiLCBvYmosIGFjdHVhbE9iamVjdCwgY3R4ICYmIGN0eC5uZXh0ICYmIGN0eC5uZXh0Lm5leHQgJiYgY3R4Lm5leHQubmV4dC5ub2RlICk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCBhY3R1YWxPYmplY3QgJiYgdGhpc0tleSA+PSBhY3R1YWxPYmplY3QubGVuZ3RoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcIkFUIFwiLCBwLCBhY3R1YWxPYmplY3QubGVuZ3RoLCB2YWwuY29udGFpbnMubGVuZ3RoICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCBwID09PSAoY29udGV4dF9zdGFjay5sZW5ndGgtMSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAmJiBcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y29uc29sZS5sb2coIFwiVGhpcyBpcyBhY3R1YWxseSBhdCB0aGUgY3VycmVudCBvYmplY3Qgc28gdXNlIHRoYXRcIiwgcCwgdmFsLmNvbnRhaW5zLCBlbGVtZW50cyApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG5leHRPYmogPSBlbGVtZW50cztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwKys7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y3R4ID0gY3R4Lm5leHQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcImlzIG5leHQuLi4gXCIsIHRoaXNLZXksIGFjdHVhbE9iamVjdC5sZW5ndGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCBjdHgubmV4dC5uZXh0ICYmIHRoaXNLZXkgPT09IGFjdHVhbE9iamVjdC5sZW5ndGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcImlzIG5leHQuLi4gXCIpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRuZXh0T2JqID0gY3R4Lm5leHQubmV4dC5ub2RlLmVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y3R4ID0gY3R4Lm5leHQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwKys7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRvYmogPSBuZXh0T2JqO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiRkFJTElORyBIRVJFXCIsIGN0eC5uZXh0LCBjdHgubmV4dC5uZXh0LCBlbGVtZW50cywgb2JqICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAmJiBjb25zb2xlLmxvZyggXCJOb3RoaW5nIGFmdGVyLCBzbyB0aGlzIGlzIGp1c3QgVEhJUz9cIiApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG5leHRPYmogPSBlbGVtZW50cztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRwKys7IC8vIG1ha2Ugc3VyZSB0byBleGl0LlxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9vYmogPSBuZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAmJiBjb25zb2xlLmxvZyggXCJmaWVsZCBBVCBpbmRleFwiLCBwLFwib2ZcIiwgdmFsLmNvbnRhaW5zLmxlbmd0aCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoIHRoaXNLZXkgIT09IGN0eC5uZXh0Lm5vZGUubmFtZSApe1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcIkV4cGVjdDpcIiwgdGhpc0tleSwgY3R4Lm5leHQubm9kZS5uYW1lLCBjdHgubmV4dC5ub2RlLmVsZW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG5leHRPYmogPSAoIGN0eC5uZXh0Lm5vZGUuZWxlbWVudHNbdGhpc0tleV0gKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly90aHJvdyBuZXcgRXJyb3IoIFwiVW5leHBlY3RlZCBwYXRoLWNvbnRleHQgcmVsYXRpb25zaGlwXCIgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRsdmwgPSBwO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiVXBkYXRpbmcgbmV4dCBvYmplY3QoTkVXKSB0b1wiLCBjdHgubmV4dC5ub2RlLCBlbGVtZW50cywgdGhpc0tleSlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoIGN0eC5uZXh0Lm5leHQgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG5leHRPYmogPSBjdHgubmV4dC5uZXh0Lm5vZGUuZWxlbWVudHM7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1JFRkVSRU5DRVMgJiYgY29uc29sZS5sb2coIFwiTm90aGluZyBhZnRlciwgc28gdGhpcyBpcyBqdXN0IFRISVM/XCIgKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRuZXh0T2JqID0gZWxlbWVudHM7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUkVGRVJFTkNFUyAmJiBjb25zb2xlLmxvZyggXCJ1c2luZyBuYW1lZCBlbGVtZW50IGZyb21cIiwgY3R4Lm5leHQubm9kZS5lbGVtZW50cywgXCI9XCIsIG5leHRPYmogKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL2lmKCAvL19ERUJVR19SRUZFUkVOQ0VTICkgIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL1x0Y29uc3QgYSA9IGN0eC5uZXh0Lm5vZGUuZWxlbWVudHM7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9cdGNvbnNvbGUubG9nKCBcIlN0YWNrIER1bXA6XCJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL1x0XHQsIGE/YS5sZW5ndGg6YVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vXHRcdCwgY3R4Lm5leHQubm9kZS5uYW1lXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9cdFx0LCB0aGlzS2V5XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9cdFx0KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL31cblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRuZXh0T2JqID0gbmV4dE9ialt0aGlzS2V5XTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcIkRvaW5nIG5leHQgY29udGV4dD8/XCIsIHAsIGNvbnRleHRfc3RhY2subGVuZ3RoLCB2YWwuY29udGFpbnMubGVuZ3RoICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGN0eCA9IGN0eC5uZXh0O1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRwKys7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcIkRvbmUgd2l0aCBjb250ZXh0IHN0YWNrLi4ubGV2ZWxcIiwgbHZsLCBcInBcIiwgcCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIHAgPCBwYXRobGVuIClcblx0XHRcdFx0XHRcdFx0XHRcdFx0bHZsID0gcC0xO1xuXHRcdFx0XHRcdFx0XHRcdFx0ZWxzZSBsdmwgPSBwO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19SRUZFUkVOQ0VTICYmIGNvbnNvbGUubG9nKCBcIkVuZCBvZiBwcm9jZXNzaW5nIGxldmVsOlwiLCBsdmwgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRpZiggKFwib2JqZWN0XCIgPT09IHR5cGVvZiBuZXh0T2JqICkgJiYgIW5leHRPYmogKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIlBhdGggZGlkIG5vdCByZXNvbHZlIHByb3Blcmx5OlwiICsgIHZhbC5jb250YWlucyArIFwiIGF0IFwiICsgaWR4ICsgJygnICsgbHZsICsgJyknICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0b2JqID0gbmV4dE9iajtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiUmVzdWx0aW5nIHJlc29sdmVkIG9iamVjdDpcIiwgb2JqICk7XG5cdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiU0VUVElORyBNT0RFIFRPIC0zIChyZXNvbHZlZCAtMilcIiApO1xuXHRcdFx0XHRcdFx0YXJyYXlUeXBlID0gLTM7XG5cdFx0XHRcdFx0XHRyZXR1cm4gb2JqO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiggdmFsLmNsYXNzTmFtZSApIHsgXG5cdFx0XHRcdFx0XHRmcCA9IGxvY2FsRnJvbVByb3RvVHlwZXMuZ2V0KCB2YWwuY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0XHRpZiggIWZwIClcblx0XHRcdFx0XHRcdFx0ZnAgPSBmcm9tUHJvdG9UeXBlcy5nZXQoIHZhbC5jbGFzc05hbWUgKTtcblx0XHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSBudWxsOyBcblx0XHRcdFx0XHRcdGlmKCBmcCAmJiBmcC5jYiApIHJldHVybiBmcC5jYi5jYWxsKCB2YWwuY29udGFpbnMgKTsgXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB2YWwuY29udGFpbnM7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0Y29uc29sZS5sb2coIFwiVW5oYW5kbGVkIHZhbHVlIGNvbnZlcnNpb24uXCIsIHZhbCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIGFycmF5UHVzaCgpIHtcblx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJQVVNIIFRPIEFSUkFZOlwiLCB2YWwgKTtcblx0XHRcdFx0aWYoIGFycmF5VHlwZSA9PSAtMyApICB7XG5cdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyhcIiBBcnJheSB0eXBlIC0zP1wiLCB2YWwudmFsdWVfdHlwZSwgZWxlbWVudHMgKTtcblx0XHRcdFx0XHRpZiggdmFsLnZhbHVlX3R5cGUgPT09IFZBTFVFX09CSkVDVCApIHtcblx0XHRcdFx0XHRcdGVsZW1lbnRzLnB1c2goIHZhbC5jb250YWlucyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRhcnJheVR5cGUgPSAtMTsgLy8gbmV4dCBvbmUgc2hvdWxkIGJlIGFsbG93ZWQ/XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9IC8vZWxzZVxuXHRcdFx0XHQvL1x0Y29uc29sZS5sb2coIFwiRmluYWxseSBhIHB1c2ggdGhhdCdzIG5vdCBhbHJlYWR5IHB1c2hlZCFcIiwgKTtcblx0XHRcdFx0c3dpdGNoKCB2YWwudmFsdWVfdHlwZSApe1xuXHRcdFx0XHRjYXNlIFZBTFVFX0VNUFRZOlxuXHRcdFx0XHRcdGVsZW1lbnRzLnB1c2goIHVuZGVmaW5lZCApO1xuXHRcdFx0XHRcdGRlbGV0ZSBlbGVtZW50c1tlbGVtZW50cy5sZW5ndGgtMV07XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0ZWxlbWVudHMucHVzaCggY29udmVydFZhbHVlKCkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHRSRVNFVF9WQUwoKTtcblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gb2JqZWN0UHVzaCgpIHtcblx0XHRcdFx0aWYoIGFycmF5VHlwZSA9PT0gLTMgJiYgdmFsLnZhbHVlX3R5cGUgPT09IFZBTFVFX0FSUkFZICkge1xuXHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiQXJyYXkgaGFzIGFscmVhZHkgYmVlbiBzZXQgaW4gb2JqZWN0LlwiICk7XG5cdFx0XHRcdFx0Ly9lbGVtZW50c1t2YWwubmFtZV0gPSB2YWwuY29udGFpbnM7XG5cdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0YXJyYXlUeXBlID0gLTE7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSA9PT0gVkFMVUVfRU1QVFkgKSByZXR1cm47XG5cdFx0XHRcdGlmKCAhdmFsLm5hbWUgJiYgY3VycmVudF9jbGFzcyApIHtcblx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiQSBTdGVwcGluZyBjdXJyZW50IGNsYXNzIGZpZWxkOlwiLCBjdXJyZW50X2NsYXNzX2ZpZWxkLCB2YWwubmFtZSApO1xuXHRcdFx0XHRcdHZhbC5uYW1lID0gY3VycmVudF9jbGFzcy5maWVsZHNbY3VycmVudF9jbGFzc19maWVsZCsrXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRsZXQgdmFsdWUgPSBjb252ZXJ0VmFsdWUoKTtcblxuXHRcdFx0XHRpZiggY3VycmVudF9wcm90byAmJiBjdXJyZW50X3Byb3RvLnByb3RvRGVmICYmIGN1cnJlbnRfcHJvdG8ucHJvdG9EZWYuY2IgKSB7XG5cdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIlNPTUVUSElORyBTSE9VTEQgQUhWRSBCRUVOIFJFUExBQ0VEIEhFUkU/P1wiLCBjdXJyZW50X3Byb3RvICk7XG5cdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIihuZWVkIHRvIGRvIGZyb21wcm90b3RveXBlcyBoZXJlKSBvYmplY3Q6XCIsIHZhbCwgdmFsdWUgKTtcblx0XHRcdFx0XHR2YWx1ZSA9IGN1cnJlbnRfcHJvdG8ucHJvdG9EZWYuY2IuY2FsbCggZWxlbWVudHMsIHZhbC5uYW1lLCB2YWx1ZSApO1xuXHRcdFx0XHRcdGlmKCB2YWx1ZSApIGVsZW1lbnRzW3ZhbC5uYW1lXSA9IHZhbHVlO1xuXHRcdFx0XHRcdC8vZWxlbWVudHMgPSBuZXcgY3VycmVudF9wcm90by5wcm90b0NvbiggZWxlbWVudHMgKTtcblx0XHRcdFx0fWVsc2Uge1xuXHRcdFx0XHQgICAgICAgIC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJEZWZhdWx0IG5vIHNwZWNpYWwgY2xhc3MgcmV2aXZlclwiLCB2YWwubmFtZSwgdmFsdWUgKTtcblx0XHRcdFx0XHRlbGVtZW50c1t2YWwubmFtZV0gPSB2YWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiVXBkYXRlZCB2YWx1ZTpcIiwgY3VycmVudF9jbGFzc19maWVsZCwgdmFsLm5hbWUsIGVsZW1lbnRzW3ZhbC5uYW1lXSApO1xuXHRcdFx0XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiKysrIEFkZGVkIG9iamVjdCBmaWVsZDpcIiwgdmFsLm5hbWUsIGVsZW1lbnRzLCBlbGVtZW50c1t2YWwubmFtZV0sIHJvb3RPYmplY3QgKTtcblx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIHJlY292ZXJJZGVudChjSW50KSB7XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcmJmNvbnNvbGUubG9nKCBcIlJlY292ZXIgSWRlbnQgY2hhcjpcIiwgY0ludCwgdmFsLCBTdHJpbmcuZnJvbUNvZGVQb2ludChjSW50KSwgXCJ3b3JkOlwiLCB3b3JkICk7XG5cdFx0XHRcdGlmKCB3b3JkICE9PSBXT1JEX1BPU19SRVNFVCApIHtcblx0XHRcdFx0XHRpZiggbmVnYXRpdmUgKSB7IFxuXHRcdFx0XHRcdFx0Ly92YWwuc3RyaW5nICs9IFwiLVwiOyBuZWdhdGl2ZSA9IGZhbHNlOyBcblx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiTmVnYXRpdmUgb3V0c2lkZSBvZiBxdW90ZXMsIGJlaW5nIGNvbnZlcnRlZCB0byBhIHN0cmluZyAod291bGQgbG9zZSBjb3VudCBvZiBsZWFkaW5nICctJyBjaGFyYWN0ZXJzKVwiLCBjSW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHN3aXRjaCggd29yZCApIHtcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0VORDpcblx0XHRcdFx0XHRcdHN3aXRjaCggdmFsLnZhbHVlX3R5cGUgKSB7XG5cdFx0XHRcdFx0XHRjYXNlIFZBTFVFX1RSVUU6ICB2YWwuc3RyaW5nICs9IFwidHJ1ZVwiOyBicmVha1xuXHRcdFx0XHRcdFx0Y2FzZSBWQUxVRV9GQUxTRTogIHZhbC5zdHJpbmcgKz0gXCJmYWxzZVwiOyBicmVha1xuXHRcdFx0XHRcdFx0Y2FzZSBWQUxVRV9OVUxMOiAgdmFsLnN0cmluZyArPSBcIm51bGxcIjsgYnJlYWtcblx0XHRcdFx0XHRcdGNhc2UgVkFMVUVfSU5GSU5JVFk6ICB2YWwuc3RyaW5nICs9IFwiSW5maW5pdHlcIjsgYnJlYWtcblx0XHRcdFx0XHRcdGNhc2UgVkFMVUVfTkVHX0lORklOSVRZOiAgdmFsLnN0cmluZyArPSBcIi1JbmZpbml0eVwiOyB0aHJvd0Vycm9yKCBcIk5lZ2F0aXZlIG91dHNpZGUgb2YgcXVvdGVzLCBiZWluZyBjb252ZXJ0ZWQgdG8gYSBzdHJpbmdcIiwgY0ludCApOyBicmVha1xuXHRcdFx0XHRcdFx0Y2FzZSBWQUxVRV9OQU46ICB2YWwuc3RyaW5nICs9IFwiTmFOXCI7IGJyZWFrXG5cdFx0XHRcdFx0XHRjYXNlIFZBTFVFX05FR19OQU46ICB2YWwuc3RyaW5nICs9IFwiLU5hTlwiOyB0aHJvd0Vycm9yKCBcIk5lZ2F0aXZlIG91dHNpZGUgb2YgcXVvdGVzLCBiZWluZyBjb252ZXJ0ZWQgdG8gYSBzdHJpbmdcIiwgY0ludCApOyBicmVha1xuXHRcdFx0XHRcdFx0Y2FzZSBWQUxVRV9VTkRFRklORUQ6ICB2YWwuc3RyaW5nICs9IFwidW5kZWZpbmVkXCI7IGJyZWFrXG5cdFx0XHRcdFx0XHRjYXNlIFZBTFVFX1NUUklORzogYnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIFZBTFVFX1VOU0VUOiBicmVhaztcblx0XHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCBcIlZhbHVlIG9mIHR5cGUgXCIgKyB2YWwudmFsdWVfdHlwZSArIFwiIGlzIG5vdCByZXN0b3JlZC4uLlwiICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX1RSVUVfMSA6ICB2YWwuc3RyaW5nICs9IFwidFwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX1RSVUVfMiA6ICB2YWwuc3RyaW5nICs9IFwidHJcIjsgYnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBXT1JEX1BPU19UUlVFXzMgOiB2YWwuc3RyaW5nICs9IFwidHJ1XCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfRkFMU0VfMSA6IHZhbC5zdHJpbmcgKz0gXCJmXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfRkFMU0VfMiA6IHZhbC5zdHJpbmcgKz0gXCJmYVwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0ZBTFNFXzMgOiB2YWwuc3RyaW5nICs9IFwiZmFsXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfRkFMU0VfNCA6IHZhbC5zdHJpbmcgKz0gXCJmYWxzXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfTlVMTF8xIDogdmFsLnN0cmluZyArPSBcIm5cIjsgYnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBXT1JEX1BPU19OVUxMXzIgOiB2YWwuc3RyaW5nICs9IFwibnVcIjsgYnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBXT1JEX1BPU19OVUxMXzMgOiB2YWwuc3RyaW5nICs9IFwibnVsXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfVU5ERUZJTkVEXzEgOiB2YWwuc3RyaW5nICs9IFwidVwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX1VOREVGSU5FRF8yIDogdmFsLnN0cmluZyArPSBcInVuXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfVU5ERUZJTkVEXzMgOiB2YWwuc3RyaW5nICs9IFwidW5kXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfVU5ERUZJTkVEXzQgOiB2YWwuc3RyaW5nICs9IFwidW5kZVwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX1VOREVGSU5FRF81IDogdmFsLnN0cmluZyArPSBcInVuZGVmXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfVU5ERUZJTkVEXzYgOiB2YWwuc3RyaW5nICs9IFwidW5kZWZpXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfVU5ERUZJTkVEXzcgOiB2YWwuc3RyaW5nICs9IFwidW5kZWZpblwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX1VOREVGSU5FRF84IDogdmFsLnN0cmluZyArPSBcInVuZGVmaW5lXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfTkFOXzEgOiB2YWwuc3RyaW5nICs9IFwiTlwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX05BTl8yIDogdmFsLnN0cmluZyArPSBcIk5hXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfSU5GSU5JVFlfMSA6IHZhbC5zdHJpbmcgKz0gXCJJXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfSU5GSU5JVFlfMiA6IHZhbC5zdHJpbmcgKz0gXCJJblwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0lORklOSVRZXzMgOiB2YWwuc3RyaW5nICs9IFwiSW5mXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfSU5GSU5JVFlfNCA6IHZhbC5zdHJpbmcgKz0gXCJJbmZpXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfSU5GSU5JVFlfNSA6IHZhbC5zdHJpbmcgKz0gXCJJbmZpblwiOyBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0lORklOSVRZXzYgOiB2YWwuc3RyaW5nICs9IFwiSW5maW5pXCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfSU5GSU5JVFlfNyA6IHZhbC5zdHJpbmcgKz0gXCJJbmZpbml0XCI7IGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgV09SRF9QT1NfUkVTRVQgOiBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0ZJRUxEIDogYnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBXT1JEX1BPU19BRlRFUl9GSUVMRDpcblx0XHRcdFx0XHQgICAgLy90aHJvd0Vycm9yKCBcIlN0cmluZy1rZXl3b3JkIHJlY292ZXJ5IGZhaWwgKGFmdGVyIHdoaXRlc3BhY2UpXCIsIGNJbnQpO1xuXHRcdFx0XHRcdCAgICBicmVhaztcblx0XHRcdFx0XHRjYXNlIFdPUkRfUE9TX0FGVEVSX0ZJRUxEX1ZBTFVFOlxuXHRcdFx0XHRcdCAgICB0aHJvd0Vycm9yKCBcIlN0cmluZy1rZXl3b3JkIHJlY292ZXJ5IGZhaWwgKGFmdGVyIHdoaXRlc3BhY2UpXCIsIGNJbnQgKTtcblx0XHRcdFx0XHQgICAgYnJlYWs7XG5cdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiV29yZCBjb250ZXh0OiBcIiArIHdvcmQgKyBcIiB1bmhhbmRsZWRcIiApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1NUUklORztcdFx0XHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRpZiggd29yZCA8IFdPUkRfUE9TX0ZJRUxEKVxuXHRcdFx0XHRcdCAgICB3b3JkID0gV09SRF9QT1NfRU5EO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19FTkQ7XG5cdFx0XHRcdFx0Ly9pZiggdmFsLnZhbHVlX3R5cGUgPT09IFZBTFVFX1VOU0VUICYmIHZhbC5zdHJpbmcubGVuZ3RoIClcblx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfU1RSSU5HXG5cdFx0XHRcdH1cblx0XHRcdFx0aWYoIGNJbnQgPT0gMTIzLyoneycqLyApXG5cdFx0XHRcdFx0b3Blbk9iamVjdCgpO1xuXHRcdFx0XHRlbHNlIGlmKCBjSW50ID09IDkxLyonWycqLyApXG5cdFx0XHRcdFx0b3BlbkFycmF5KCk7XG5cdFx0XHRcdGVsc2UgaWYoIGNJbnQgPT0gNDQvKicsJyovICkge1xuXHRcdFx0XHRcdC8vIGNvbW1hIHNlcGFyYXRlcyB0aGUgc3RyaW5nLCBpdCBnZXRzIGNvbnN1bWVkLlxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIGlnbm9yZSB3aGl0ZSBzcGFjZS5cblx0XHRcdFx0XHRpZiggY0ludCA9PSAzMi8qJyAnKi8gfHwgY0ludCA9PSAxMyB8fCBjSW50ID09IDEwIHx8IGNJbnQgPT0gOSB8fCBjSW50ID09IDB4RkVGRiB8fCBjSW50ID09IDB4MjAyOCB8fCBjSW50ID09IDB4MjAyOSApIHtcblx0XHRcdFx0XHRcdC8vX0RFQlVHX1dISVRFU1BBQ0UgJiYgY29uc29sZS5sb2coIFwiSUdOT1JFIFdISVRFU1BBQ0VcIiApO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmKCBjSW50ID09IDQ0LyonLCcqLyB8fCBjSW50ID09IDEyNS8qJ30nKi8gfHwgY0ludCA9PSA5My8qJ10nKi8gfHwgY0ludCA9PSA1OC8qJzonKi8gKVxuXHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJJbnZhbGlkIGNoYXJhY3RlciBuZWFyIGlkZW50aWZpZXJcIiwgY0ludCApO1xuXHRcdFx0XHRcdGVsc2UgLy9pZiggdHlwZW9mIGNJbnQgPT09IFwibnVtYmVyXCIpXG5cdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0fVxuXHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIlZBTCBTVFJJTkcgSVM6XCIsIHZhbC5zdHJpbmcsIHN0ciApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBnYXRoZXIgYSBzdHJpbmcgZnJvbSBhbiBpbnB1dCBzdHJlYW07IHN0YXJ0X2MgaXMgdGhlIG9wZW5pbmcgcXVvdGUgdG8gZmluZCBhIHJlbGF0ZWQgY2xvc2UgcXVvdGUuXG5cdFx0XHRmdW5jdGlvbiBnYXRoZXJTdHJpbmcoIHN0YXJ0X2MgKSB7XG5cdFx0XHRcdGxldCByZXR2YWwgPSAwO1xuXHRcdFx0XHR3aGlsZSggcmV0dmFsID09IDAgJiYgKCBuIDwgYnVmLmxlbmd0aCApICkge1xuXHRcdFx0XHRcdHN0ciA9IGJ1Zi5jaGFyQXQobik7XG5cdFx0XHRcdFx0bGV0IGNJbnQgPSBidWYuY29kZVBvaW50QXQobisrKTtcblx0XHRcdFx0XHRpZiggY0ludCA+PSAweDEwMDAwICkgeyBzdHIgKz0gYnVmLmNoYXJBdChuKTsgbisrOyB9XG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJnYXRoZXJpbmcuLi4uXCIsIHN0cmluZ0VzY2FwZSwgc3RyLCBjSW50LCB1bmljb2RlV2lkZSwgc3RyaW5nSGV4LCBzdHJpbmdVbmljb2RlLCBoZXhfY2hhcl9sZW4gKTtcblx0XHRcdFx0XHRwb3MuY29sKys7XG5cdFx0XHRcdFx0aWYoIGNJbnQgPT0gc3RhcnRfYyApIHsgLy8oIGNJbnQgPT0gMzQvKidcIicqLyApIHx8ICggY0ludCA9PSAzOS8qJ1xcJycqLyApIHx8ICggY0ludCA9PSA5Ni8qJ2AnKi8gKSApXG5cdFx0XHRcdFx0XHRpZiggc3RyaW5nRXNjYXBlICkgeyBcblx0XHRcdFx0XHRcdFx0aWYoIHN0cmluZ0hleCApXG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJJbmNvbXBsZXRlIGhleGlkZWNpbWFsIHNlcXVlbmNlXCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggc3RyaW5nVW5pY29kZSApXG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJJbmNvbXBsZXRlIGxvbmcgdW5pY29kZSBzZXF1ZW5jZVwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHVuaWNvZGVXaWRlIClcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcIkluY29tcGxldGUgdW5pY29kZSBzZXF1ZW5jZVwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdGlmKCBjcl9lc2NhcGVkICkge1xuXHRcdFx0XHRcdFx0XHRcdGNyX2VzY2FwZWQgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRyZXR2YWwgPSAxOyAvLyBjb21wbGV0ZSBzdHJpbmcsIGVzY2FwZWQgXFxyXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHRcdFx0c3RyaW5nRXNjYXBlID0gZmFsc2U7IH1cblx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBxdW90ZSBtYXRjaGVzLCBhbmQgaXMgbm90IHByb2Nlc3NpbmcgYW4gZXNjYXBlIHNlcXVlbmNlLlxuXHRcdFx0XHRcdFx0XHRyZXR2YWwgPSAxO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsc2UgaWYoIHN0cmluZ0VzY2FwZSApIHtcblx0XHRcdFx0XHRcdGlmKCB1bmljb2RlV2lkZSApIHtcblx0XHRcdFx0XHRcdFx0aWYoIGNJbnQgPT0gMTI1LyonfScqLyApIHtcblx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IFN0cmluZy5mcm9tQ29kZVBvaW50KCBoZXhfY2hhciApO1xuXHRcdFx0XHRcdFx0XHRcdHVuaWNvZGVXaWRlID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0c3RyaW5nVW5pY29kZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGhleF9jaGFyICo9IDE2O1xuXHRcdFx0XHRcdFx0XHRpZiggY0ludCA+PSA0OC8qJzAnKi8gJiYgY0ludCA8PSA1Ny8qJzknKi8gKSAgICAgIGhleF9jaGFyICs9IGNJbnQgLSAweDMwO1xuXHRcdFx0XHRcdFx0XHRlbHNlIGlmKCBjSW50ID49IDY1LyonQScqLyAmJiBjSW50IDw9IDcwLyonRicqLyApIGhleF9jaGFyICs9ICggY0ludCAtIDY1ICkgKyAxMDtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggY0ludCA+PSA5Ny8qJ2EnKi8gJiYgY0ludCA8PSAxMDIvKidmJyovICkgaGV4X2NoYXIgKz0gKCBjSW50IC0gOTcgKSArIDEwO1xuXHRcdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcIihlc2NhcGVkIGNoYXJhY3RlciwgcGFyc2luZyBoZXggb2YgXFxcXHUpXCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0XHRyZXR2YWwgPSAtMTtcblx0XHRcdFx0XHRcdFx0XHR1bmljb2RlV2lkZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSBpZiggc3RyaW5nSGV4IHx8IHN0cmluZ1VuaWNvZGUgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBoZXhfY2hhcl9sZW4gPT09IDAgJiYgY0ludCA9PT0gMTIzLyoneycqLyApIHtcblx0XHRcdFx0XHRcdFx0XHR1bmljb2RlV2lkZSA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0aWYoIGhleF9jaGFyX2xlbiA8IDIgfHwgKCBzdHJpbmdVbmljb2RlICYmIGhleF9jaGFyX2xlbiA8IDQgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRoZXhfY2hhciAqPSAxNjtcblx0XHRcdFx0XHRcdFx0XHRpZiggY0ludCA+PSA0OC8qJzAnKi8gJiYgY0ludCA8PSA1Ny8qJzknKi8gKSAgICAgIGhleF9jaGFyICs9IGNJbnQgLSAweDMwO1xuXHRcdFx0XHRcdFx0XHRcdGVsc2UgaWYoIGNJbnQgPj0gNjUvKidBJyovICYmIGNJbnQgPD0gNzAvKidGJyovICkgaGV4X2NoYXIgKz0gKCBjSW50IC0gNjUgKSArIDEwO1xuXHRcdFx0XHRcdFx0XHRcdGVsc2UgaWYoIGNJbnQgPj0gOTcvKidhJyovICYmIGNJbnQgPD0gMTAyLyonZicqLyApIGhleF9jaGFyICs9ICggY0ludCAtIDk3ICkgKyAxMDtcblx0XHRcdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIHN0cmluZ1VuaWNvZGU/XCIoZXNjYXBlZCBjaGFyYWN0ZXIsIHBhcnNpbmcgaGV4IG9mIFxcXFx1KVwiOlwiKGVzY2FwZWQgY2hhcmFjdGVyLCBwYXJzaW5nIGhleCBvZiBcXFxceClcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dmFsID0gLTE7XG5cdFx0XHRcdFx0XHRcdFx0XHRzdHJpbmdIZXggPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGhleF9jaGFyX2xlbisrO1xuXHRcdFx0XHRcdFx0XHRcdGlmKCBzdHJpbmdVbmljb2RlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIGhleF9jaGFyX2xlbiA9PSA0ICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IFN0cmluZy5mcm9tQ29kZVBvaW50KCBoZXhfY2hhciApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRzdHJpbmdVbmljb2RlID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRlbHNlIGlmKCBoZXhfY2hhcl9sZW4gPT0gMiApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gU3RyaW5nLmZyb21Db2RlUG9pbnQoIGhleF9jaGFyICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRzdHJpbmdIZXggPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0c3dpdGNoKCBjSW50ICkge1xuXHRcdFx0XHRcdFx0Y2FzZSAxMy8qJ1xccicqLzpcblx0XHRcdFx0XHRcdFx0Y3JfZXNjYXBlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdHBvcy5jb2wgPSAxO1xuXHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdGNhc2UgMHgyMDI4OiAvLyBMUyAoTGluZSBzZXBhcmF0b3IpXG5cdFx0XHRcdFx0XHRjYXNlIDB4MjAyOTogLy8gUFMgKHBhcmFncmFwaCBzZXBhcmF0ZSlcblx0XHRcdFx0XHRcdFx0cG9zLmNvbCA9IDE7XG5cdFx0XHRcdFx0XHRcdC8vIGZhbGxzIHRocm91Z2hcblx0XHRcdFx0XHRcdGNhc2UgMTAvKidcXG4nKi86XG5cdFx0XHRcdFx0XHRcdGlmKCAhY3JfZXNjYXBlZCApIHsgLy8gXFxcXCBcXG5cblx0XHRcdFx0XHRcdFx0XHRwb3MuY29sID0gMTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHsgLy8gXFxcXCBcXHIgXFxuXG5cdFx0XHRcdFx0XHRcdFx0Y3JfZXNjYXBlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHBvcy5saW5lKys7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMTYvKid0JyovOlxuXHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9ICdcXHQnO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgOTgvKidiJyovOlxuXHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9ICdcXGInO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgMTEwLyonbicqLzpcblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSAnXFxuJztcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDExNC8qJ3InKi86XG5cdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gJ1xccic7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMDIvKidmJyovOlxuXHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9ICdcXGYnO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgMTE4LyondicqLzpcblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSAnXFx2Jztcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDQ4LyonMCcqLzogXG5cdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gJ1xcMCc7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMjAvKid4JyovOlxuXHRcdFx0XHRcdFx0XHRzdHJpbmdIZXggPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRoZXhfY2hhcl9sZW4gPSAwO1xuXHRcdFx0XHRcdFx0XHRoZXhfY2hhciA9IDA7XG5cdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMTcvKid1JyovOlxuXHRcdFx0XHRcdFx0XHRzdHJpbmdVbmljb2RlID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0aGV4X2NoYXJfbGVuID0gMDtcblx0XHRcdFx0XHRcdFx0aGV4X2NoYXIgPSAwO1xuXHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdC8vY2FzZSA0Ny8qJy8nKi86XG5cdFx0XHRcdFx0XHQvL2Nhc2UgOTIvKidcXFxcJyovOlxuXHRcdFx0XHRcdFx0Ly9jYXNlIDM0LyonXCInKi86XG5cdFx0XHRcdFx0XHQvL2Nhc2UgMzkvKlwiJ1wiKi86XG5cdFx0XHRcdFx0XHQvL2Nhc2UgOTYvKidgJyovOlxuXHRcdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJvdGhlci4uLlwiICk7XG5cdFx0XHRcdFx0XHRzdHJpbmdFc2NhcGUgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiggY0ludCA9PT0gOTIvKidcXFxcJyovICkge1xuXHRcdFx0XHRcdFx0aWYoIHN0cmluZ0VzY2FwZSApIHtcblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSAnXFxcXCc7XG5cdFx0XHRcdFx0XHRcdHN0cmluZ0VzY2FwZSA9IGZhbHNlXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0c3RyaW5nRXNjYXBlID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0aGV4X2NoYXIgPSAwO1xuXHRcdFx0XHRcdFx0XHRoZXhfY2hhcl9sZW4gPSAwO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHsgLyogYW55IG90aGVyIGNoYXJhY3RlciAqL1xuXHRcdFx0XHRcdFx0aWYoIGNyX2VzY2FwZWQgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFxcXFwgXFxyIDxhbnkgY2hhcj5cblx0XHRcdFx0XHRcdFx0Y3JfZXNjYXBlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRwb3MubGluZSsrO1xuXHRcdFx0XHRcdFx0XHRwb3MuY29sID0gMjsgLy8gdGhpcyBjaGFyYWN0ZXIgaXMgcG9zIDE7IGFuZCBpbmNyZW1lbnQgdG8gYmUgYWZ0ZXIgaXQuXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHJldHZhbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gZ2F0aGVyIGEgbnVtYmVyIGZyb20gdGhlIGlucHV0IHN0cmVhbS5cblx0XHRcdGZ1bmN0aW9uIGNvbGxlY3ROdW1iZXIoKSB7XG5cdFx0XHRcdGxldCBfbjtcblx0XHRcdFx0d2hpbGUoIChfbiA9IG4pIDwgYnVmLmxlbmd0aCApIHtcblx0XHRcdFx0XHRzdHIgPSBidWYuY2hhckF0KF9uKTtcblx0XHRcdFx0XHRsZXQgY0ludCA9IGJ1Zi5jb2RlUG9pbnRBdChuKyspO1xuXHRcdFx0XHRcdGlmKCBjSW50ID49IDI1NiApIHsgXG5cdFx0XHRcdFx0XHRcdHBvcy5jb2wgLT0gbiAtIF9uO1xuXHRcdFx0XHRcdFx0XHRuID0gX247IC8vIHB1dCBjaGFyYWN0ZXIgYmFjayBpbiBxdWV1ZSB0byBwcm9jZXNzLlxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19OVU1CRVJTICAmJiBjb25zb2xlLmxvZyggXCJpbiBnZXR0aW5nIG51bWJlcjpcIiwgbiwgY0ludCwgU3RyaW5nLmZyb21Db2RlUG9pbnQoY0ludCkgKTtcblx0XHRcdFx0XHRcdGlmKCBjSW50ID09IDk1IC8qXyovIClcblx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRwb3MuY29sKys7XG5cdFx0XHRcdFx0XHQvLyBsZWFkaW5nIHplcm9zIHNob3VsZCBiZSBmb3JiaWRkZW4uXG5cdFx0XHRcdFx0XHRpZiggY0ludCA+PSA0OC8qJzAnKi8gJiYgY0ludCA8PSA1Ny8qJzknKi8gKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBleHBvbmVudCApIHtcblx0XHRcdFx0XHRcdFx0XHRleHBvbmVudF9kaWdpdCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoIGNJbnQgPT0gNDUvKictJyovIHx8IGNJbnQgPT0gNDMvKicrJyovICkge1xuXHRcdFx0XHRcdFx0XHRpZiggdmFsLnN0cmluZy5sZW5ndGggPT0gMCB8fCAoIGV4cG9uZW50ICYmICFleHBvbmVudF9zaWduICYmICFleHBvbmVudF9kaWdpdCApICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmKCBjSW50ID09IDQ1LyonLScqLyAmJiAhZXhwb25lbnQgKSBuZWdhdGl2ZSA9ICFuZWdhdGl2ZTtcblx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHRcdFx0XHRleHBvbmVudF9zaWduID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggbmVnYXRpdmUgKSB7IHZhbC5zdHJpbmcgPSAnLScgKyB2YWwuc3RyaW5nOyBuZWdhdGl2ZSA9IGZhbHNlOyB9XG5cdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0ZV9mb3JtYXQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoIGNJbnQgPT0gNzgvKidOJyovICkge1xuXHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19SRVNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHRnYXRoZXJpbmdOdW1iZXIgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfTkFOXzE7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZyBudW1iZXI7XCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoIGNJbnQgPT0gNzMvKidJJyovICkge1xuXHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19SRVNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHRnYXRoZXJpbmdOdW1iZXIgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfSU5GSU5JVFlfMTtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJmYXVsdCB3aGlsZSBwYXJzaW5nIG51bWJlcjtcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggY0ludCA9PSA1OC8qJzonKi8gJiYgZGF0ZV9mb3JtYXQgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBuZWdhdGl2ZSApIHsgdmFsLnN0cmluZyA9ICctJyArIHZhbC5zdHJpbmc7IG5lZ2F0aXZlID0gZmFsc2U7IH1cblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdGRhdGVfZm9ybWF0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggY0ludCA9PSA4NC8qJ1QnKi8gJiYgZGF0ZV9mb3JtYXQgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBuZWdhdGl2ZSApIHsgdmFsLnN0cmluZyA9ICctJyArIHZhbC5zdHJpbmc7IG5lZ2F0aXZlID0gZmFsc2U7IH1cblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdGRhdGVfZm9ybWF0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggY0ludCA9PSA5MC8qJ1onKi8gJiYgZGF0ZV9mb3JtYXQgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBuZWdhdGl2ZSApIHsgdmFsLnN0cmluZyA9ICctJyArIHZhbC5zdHJpbmc7IG5lZ2F0aXZlID0gZmFsc2U7IH1cblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdGRhdGVfZm9ybWF0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggY0ludCA9PSA0Ni8qJy4nKi8gKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCAhZGVjaW1hbCAmJiAhZnJvbUhleCAmJiAhZXhwb25lbnQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdFx0ZGVjaW1hbCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJmYXVsdCB3aGlsZSBwYXJzaW5nIG51bWJlcjtcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoIGNJbnQgPT0gMTEwLyonbicqLyApIHtcblx0XHRcdFx0XHRcdFx0aXNCaWdJbnQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggZnJvbUhleCAmJiAoICggKCBjSW50ID49IDk1LyonYScqLyApICYmICggY0ludCA8PSAxMDIvKidmJyovICkgKSB8fFxuXHRcdFx0XHRcdFx0ICAgICAgICAgICAoICggY0ludCA+PSA2NS8qJ0EnKi8gKSAmJiAoIGNJbnQgPD0gNzAvKidGJyovICkgKSApICkge1xuXHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggY0ludCA9PSAxMjAvKid4JyovIHx8IGNJbnQgPT0gOTgvKidiJyovIHx8IGNJbnQgPT0gMTExLyonbycqL1xuXHRcdFx0XHRcdFx0XHRcdHx8IGNJbnQgPT0gODgvKidYJyovIHx8IGNJbnQgPT0gNjYvKidCJyovIHx8IGNJbnQgPT0gNzkvKidPJyovICkge1xuXHRcdFx0XHRcdFx0XHQvLyBoZXggY29udmVyc2lvbi5cblx0XHRcdFx0XHRcdFx0aWYoICFmcm9tSGV4ICYmIHZhbC5zdHJpbmcgPT0gJzAnICkge1xuXHRcdFx0XHRcdFx0XHRcdGZyb21IZXggPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gc3RyO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1cyA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZyBudW1iZXI7XCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmKCAoIGNJbnQgPT0gMTAxLyonZScqLyApIHx8ICggY0ludCA9PSA2OS8qJ0UnKi8gKSApIHtcblx0XHRcdFx0XHRcdFx0aWYoICFleHBvbmVudCApIHtcblx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHRcdFx0XHRleHBvbmVudCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJmYXVsdCB3aGlsZSBwYXJzaW5nIG51bWJlcjtcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRpZiggY0ludCA9PSAzMi8qJyAnKi8gfHwgY0ludCA9PSAxMyB8fCBjSW50ID09IDEwIHx8IGNJbnQgPT0gOSB8fCBjSW50ID09IDQ3LyonLycqLyB8fCBjSW50ID09ICAzNS8qJyMnKi9cblx0XHRcdFx0XHRcdFx0IHx8IGNJbnQgPT0gNDQvKicsJyovIHx8IGNJbnQgPT0gMTI1LyonfScqLyB8fCBjSW50ID09IDkzLyonXScqL1xuXHRcdFx0XHRcdFx0XHQgfHwgY0ludCA9PSAxMjMvKid7JyovIHx8IGNJbnQgPT0gOTEvKidbJyovIHx8IGNJbnQgPT0gMzQvKidcIicqLyB8fCBjSW50ID09IDM5LyonJycqLyB8fCBjSW50ID09IDk2LyonYCcqL1xuXHRcdFx0XHRcdFx0XHQgfHwgY0ludCA9PSA1OC8qJzonKi8gKSB7XG5cdFx0XHRcdFx0XHRcdFx0cG9zLmNvbCAtPSBuIC0gX247XG5cdFx0XHRcdFx0XHRcdFx0biA9IF9uOyAvLyBwdXQgY2hhcmFjdGVyIGJhY2sgaW4gcXVldWUgdG8gcHJvY2Vzcy5cblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggY29tcGxldGVfYXRfZW5kICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcImZhdWx0IHdoaWxlIHBhcnNpbmcgbnVtYmVyO1wiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCAoIWNvbXBsZXRlX2F0X2VuZCkgJiYgbiA9PSBidWYubGVuZ3RoICkge1xuXHRcdFx0XHRcdGdhdGhlcmluZ051bWJlciA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0Z2F0aGVyaW5nTnVtYmVyID0gZmFsc2U7XG5cdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9OVU1CRVI7XG5cdFx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOICkge1xuXHRcdFx0XHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYmVnaW4gcGFyc2luZyBhbiBvYmplY3QgdHlwZVxuXHRcdFx0ZnVuY3Rpb24gb3Blbk9iamVjdCgpIHtcblx0XHRcdFx0bGV0IG5leHRNb2RlID0gQ09OVEVYVF9PQkpFQ1RfRklFTEQ7XG5cdFx0XHRcdGxldCBjbHMgPSBudWxsO1xuXHRcdFx0XHRsZXQgdG1wb2JqID0ge307XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwib3BlbmluZyBvYmplY3Q6XCIsIHZhbC5zdHJpbmcsIHZhbC52YWx1ZV90eXBlLCB3b3JkLCBwYXJzZV9jb250ZXh0ICk7XG5cdFx0XHRcdGlmKCB3b3JkID4gV09SRF9QT1NfUkVTRVQgJiYgd29yZCA8IFdPUkRfUE9TX0ZJRUxEIClcblx0XHRcdFx0XHRyZWNvdmVySWRlbnQoIDEyMyAvKiAneycgKi8gKTtcblx0XHRcdFx0bGV0IHByb3RvRGVmO1xuXHRcdFx0XHRwcm90b0RlZiA9IGdldFByb3RvKCk7IC8vIGxvb2t1cCBjbGFzc25hbWUgdXNpbmcgdmFsLnN0cmluZyBhbmQgZ2V0IHByb3RvZGVmKGlmIGFueSlcblx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOICkge1xuXHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0ZJRUxEIC8qfHwgd29yZCA9PSBXT1JEX1BPU19BRlRFUl9GSUVMRCovIFxuXHRcdFx0XHRcdCAgIHx8IHdvcmQgPT0gV09SRF9QT1NfRU5EXG5cdFx0XHRcdFx0ICAgICAmJiAoIHByb3RvRGVmIHx8IHZhbC5zdHJpbmcubGVuZ3RoICkgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCBwcm90b0RlZiAmJiBwcm90b0RlZi5wcm90b0RlZiAmJiBwcm90b0RlZi5wcm90b0RlZi5wcm90b0NvbiApIHtcblx0XHRcdFx0XHRcdFx0XHR0bXBvYmogPSBuZXcgcHJvdG9EZWYucHJvdG9EZWYucHJvdG9Db24oKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYoICFwcm90b0RlZiB8fCAhcHJvdG9EZWYucHJvdG9EZWYgJiYgdmFsLnN0cmluZyApIC8vIGNsYXNzIGNyZWF0aW9uIGlzIHJlZHVuZGFudC4uLlxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRjbHMgPSBjbGFzc2VzLmZpbmQoIGNscz0+Y2xzLm5hbWU9PT12YWwuc3RyaW5nICk7XG5cdFx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiUHJvYmFibHkgY3JlYXRpbmcgdGhlIE1hY3JvLVRhZyBoZXJlP1wiLCBjbHMgKVxuXHRcdFx0XHRcdFx0XHRpZiggIWNscyApIHtcblx0XHRcdFx0XHRcdFx0XHQvKiBlc2xpbnQtZGlzYWJsZSBuby1pbm5lci1kZWNsYXJhdGlvbnMgKi9cblx0XHRcdFx0XHRcdFx0XHRmdW5jdGlvbiBwcml2YXRlUHJvdG8oKSB7fSBcblx0XHRcdFx0XHRcdFx0XHQvLyB0aGlzIGp1c3QgdXNlcyB0aGUgdG1wb2JqIHt9IGNvbnRhaW5lciB0byBzdG9yZSB0aGUgdmFsdWVzIGNvbGxlY3RlZCBmb3IgdGhpcyBjbGFzcy4uLlxuXHRcdFx0XHRcdFx0XHRcdC8vIHRoaXMgZG9lcyBub3QgZ2VuZXJhdGUgdGhlIGluc3RhbmNlIG9mIHRoZSBjbGFzcy5cblx0XHRcdFx0XHRcdFx0XHQvLyBpZiB0aGlzIHRhZyB0eXBlIGlzIGFsc28gYSBwcm90b3R5cGUsIHVzZSB0aGF0IHByb3RvdHlwZSwgZWxzZSBjcmVhdGUgYSB1bmlxdWUgcHJvdG9cblx0XHRcdFx0XHRcdFx0XHQvLyBmb3IgdGhpcyB0YWdnZWQgY2xhc3MgdHlwZS5cblx0XHRcdFx0XHRcdFx0XHRjbGFzc2VzLnB1c2goIGNscyA9IHsgbmFtZSA6IHZhbC5zdHJpbmdcblx0XHRcdFx0XHRcdFx0XHQsIHByb3RvQ29uOiAocHJvdG9EZWYgJiYgcHJvdG9EZWYucHJvdG9EZWYgJiYgcHJvdG9EZWYucHJvdG9EZWYucHJvdG9Db24pIHx8IHByaXZhdGVQcm90by5jb25zdHJ1Y3RvclxuXHRcdFx0XHRcdFx0XHRcdCAsIGZpZWxkcyA6IFtdIH0gKTtcblx0XHRcdFx0XHRcdFx0XHQgbmV4dE1vZGUgPSBDT05URVhUX0NMQVNTX0ZJRUxEO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYoIHJlZGVmaW5lQ2xhc3MgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJyZWRlZmluZSBjbGFzcy4uLlwiICk7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gcmVkZWZpbmUgdGhpcyBjbGFzc1xuXHRcdFx0XHRcdFx0XHRcdGNscy5maWVsZHMubGVuZ3RoID0gMDtcblx0XHRcdFx0XHRcdFx0XHRuZXh0TW9kZSA9IENPTlRFWFRfQ0xBU1NfRklFTEQ7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJmb3VuZCBleGlzdGluZyBjbGFzcywgdXNpbmcgaXQuLi4uXCIpO1xuXHRcdFx0XHRcdFx0XHRcdHRtcG9iaiA9IG5ldyBjbHMucHJvdG9Db24oKTtcblx0XHRcdFx0XHRcdFx0XHQvL3RtcG9iaiA9IE9iamVjdC5hc3NpZ24oIHRtcG9iaiwgY2xzLnByb3RvT2JqZWN0ICk7XG5cdFx0XHRcdFx0XHRcdFx0Ly9PYmplY3Quc2V0UHJvdG90eXBlT2YoIHRtcG9iaiwgT2JqZWN0LmdldFByb3RvdHlwZU9mKCBjbHMucHJvdG9PYmplY3QgKSApO1xuXHRcdFx0XHRcdFx0XHRcdG5leHRNb2RlID0gQ09OVEVYVF9DTEFTU19WQUxVRTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZWRlZmluZUNsYXNzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRjdXJyZW50X2NsYXNzID0gY2xzXG5cdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19GSUVMRDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19GSUVMRCAvKnx8IHdvcmQgPT0gV09SRF9QT1NfQUZURVJfRklFTEQqLyBcblx0XHRcdFx0XHRcdHx8IHBhcnNlX2NvbnRleHQgPT09IENPTlRFWFRfSU5fQVJSQVkgXG5cdFx0XHRcdFx0XHR8fCBwYXJzZV9jb250ZXh0ID09PSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRSBcblx0XHRcdFx0XHRcdHx8IHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9DTEFTU19WQUxVRSApIHtcblx0XHRcdFx0XHRpZiggd29yZCAhPSBXT1JEX1BPU19SRVNFVCB8fCB2YWwudmFsdWVfdHlwZSA9PSBWQUxVRV9TVFJJTkcgKSB7XG5cdFx0XHRcdFx0XHRpZiggcHJvdG9EZWYgJiYgcHJvdG9EZWYucHJvdG9EZWYgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIG5lZWQgdG8gY29sbGVjdCB0aGUgb2JqZWN0LFxuXHRcdFx0XHRcdFx0XHR0bXBvYmogPSBuZXcgcHJvdG9EZWYucHJvdG9EZWYucHJvdG9Db24oKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIGxvb2sgZm9yIGEgY2xhc3MgdHlwZSAoc2hvcnRoYW5kKSB0byByZWNvdmVyLlxuXHRcdFx0XHRcdFx0XHRjbHMgPSBjbGFzc2VzLmZpbmQoIGNscz0+Y2xzLm5hbWUgPT09IHZhbC5zdHJpbmcgKTtcblx0XHRcdFx0XHRcdFx0aWYoICFjbHMgKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8taW5uZXItZGVjbGFyYXRpb25zICovXG5cdFx0XHRcdFx0XHRcdCAgIGZ1bmN0aW9uIHByaXZhdGVQcm90bygpe31cblx0XHRcdFx0XHRcdFx0XHQvL3Njb25zb2xlLmxvZyggXCJwcml2YXRlUHJvdG8gaGFzIG5vIHByb3RvP1wiLCBwcml2YXRlUHJvdG8ucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUgKTtcblx0XHRcdFx0XHRcdFx0XHRsb2NhbEZyb21Qcm90b1R5cGVzLnNldCggdmFsLnN0cmluZyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR7IHByb3RvQ29uOnByaXZhdGVQcm90by5wcm90b3R5cGUuY29uc3RydWN0b3Jcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsIGNiOiBudWxsIH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICAgKTtcblx0XHRcdFx0XHRcdFx0XHR0bXBvYmogPSBuZXcgcHJpdmF0ZVByb3RvKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0bmV4dE1vZGUgPSBDT05URVhUX0NMQVNTX1ZBTFVFO1xuXHRcdFx0XHRcdFx0XHRcdHRtcG9iaiA9IHt9O1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQvL25leHRNb2RlID0gQ09OVEVYVF9DTEFTU19WQUxVRTtcblx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX1JFU0VUO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmKCAoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTEQgJiYgd29yZCA9PSBXT1JEX1BPU19SRVNFVCApICkge1xuXHRcdFx0XHRcdHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZzsgZ2V0dGluZyBmaWVsZCBuYW1lIHVuZXhwZWN0ZWQgXCIsIGNJbnQgKTtcblx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBjb21tb24gY29kZSB0byBwdXNoIGludG8gbmV4dCBjb250ZXh0XG5cdFx0XHRcdGxldCBvbGRfY29udGV4dCA9IGdldENvbnRleHQoKTtcblx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJCZWdpbiBhIG5ldyBvYmplY3Q7IHByZXZpb3VzbHkgcHVzaGVkIGludG8gZWxlbWVudHM7IGJ1dCB3YWl0IHVudGlsIHRyYWlsaW5nIGNvbW1hIG9yIGNsb3NlIHByZXZpb3VzbHkgXCIsIHZhbC52YWx1ZV90eXBlLCB2YWwuY2xhc3NOYW1lICk7XG5cblx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9PQkpFQ1Q7XG5cdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09PSBDT05URVhUX1VOS05PV04gKXtcblx0XHRcdFx0XHRlbGVtZW50cyA9IHRtcG9iajtcblx0XHRcdFx0fSBlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfSU5fQVJSQVkgKSB7XG5cdFx0XHRcdFx0aWYoIGFycmF5VHlwZSA9PSAtMSApIHtcblx0XHRcdFx0XHRcdC8vIHRoaXMgaXMgcHVzaGVkIGxhdGVyLi4uIFxuXHRcdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJQVVNISU5HIE9QRU4gT0JKRUNUIElOVE8gRVhJU1RJTkcgQVJSQVkgLSBUSElTIFNIT1VMRCBCRSBSRS1TRVQ/XCIsIEpTT1guc3RyaW5naWZ5KGNvbnRleHRfc3RhY2suZmlyc3Qubm9kZSkgKTtcblx0XHRcdFx0XHRcdC8vZWxlbWVudHMucHVzaCggdG1wb2JqICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHZhbC5uYW1lID0gZWxlbWVudHMubGVuZ3RoO1xuXHRcdFx0XHRcdC8vZWxzZSBpZiggLy9fREVCVUdfUEFSU0lORyAmJiBhcnJheVR5cGUgIT09IC0zIClcblx0XHRcdFx0XHQvL1x0Y29uc29sZS5sb2coIFwiVGhpcyBpcyBhbiBpbnZhbGlkIHBhcnNpbmcgc3RhdGUsIHR5cGVkIGFycmF5IHdpdGggc3ViLW9iamVjdCBlbGVtZW50c1wiICk7XG5cdFx0XHRcdH0gZWxzZSBpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRSB8fCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfQ0xBU1NfVkFMVUUgKSB7XG5cdFx0XHRcdFx0aWYoICF2YWwubmFtZSAmJiBjdXJyZW50X2NsYXNzICl7XG5cdFx0XHRcdFx0XHR2YWwubmFtZSA9IGN1cnJlbnRfY2xhc3MuZmllbGRzW2N1cnJlbnRfY2xhc3NfZmllbGQrK107XG5cdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiQiBTdGVwcGluZyBjdXJyZW50IGNsYXNzIGZpZWxkOlwiLCB2YWwsIGN1cnJlbnRfY2xhc3NfZmllbGQsIHZhbC5uYW1lICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJTZXR0aW5nIGVsZW1lbnQ6XCIsIHZhbC5uYW1lLCB0bXBvYmogKTtcblx0XHRcdFx0XHRlbGVtZW50c1t2YWwubmFtZV0gPSB0bXBvYmo7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRvbGRfY29udGV4dC5jb250ZXh0ID0gcGFyc2VfY29udGV4dDtcblx0XHRcdFx0b2xkX2NvbnRleHQuZWxlbWVudHMgPSBlbGVtZW50cztcblx0XHRcdFx0Ly9vbGRfY29udGV4dC5lbGVtZW50X2FycmF5ID0gZWxlbWVudF9hcnJheTtcblx0XHRcdFx0b2xkX2NvbnRleHQubmFtZSA9IHZhbC5uYW1lO1xuXHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwicHVzaGluZyB2YWwubmFtZTpcIiwgdmFsLm5hbWUsIGFycmF5VHlwZSApO1xuXHRcdFx0XHRvbGRfY29udGV4dC5jdXJyZW50X3Byb3RvID0gY3VycmVudF9wcm90bztcblx0XHRcdFx0b2xkX2NvbnRleHQuY3VycmVudF9jbGFzcyA9IGN1cnJlbnRfY2xhc3M7XG5cdFx0XHRcdG9sZF9jb250ZXh0LmN1cnJlbnRfY2xhc3NfZmllbGQgPSBjdXJyZW50X2NsYXNzX2ZpZWxkO1xuXHRcdFx0XHRvbGRfY29udGV4dC52YWx1ZVR5cGUgPSB2YWwudmFsdWVfdHlwZTtcblx0XHRcdFx0b2xkX2NvbnRleHQuYXJyYXlUeXBlID0gYXJyYXlUeXBlOyAvLyBwb3AgdGhhdCB3ZSBkb24ndCB3YW50IHRvIGhhdmUgdGhpcyB2YWx1ZSByZS1wdXNoZWQuXG5cdFx0XHRcdG9sZF9jb250ZXh0LmNsYXNzTmFtZSA9IHZhbC5jbGFzc05hbWU7XG5cdFx0XHRcdC8vYXJyYXlUeXBlID0gLTM7IC8vIHRoaXMgZG9lc24ndCBtYXR0ZXIsIGl0J3MgYW4gb2JqZWN0IHN0YXRlLCBhbmQgYSBuZXcgYXJyYXkgd2lsbCByZXNldCB0byAtMVxuXHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gbnVsbDtcblx0XHRcdFx0dmFsLm5hbWUgPSBudWxsO1xuXHRcdFx0XHRjdXJyZW50X3Byb3RvID0gcHJvdG9EZWY7XG5cdFx0XHRcdGN1cnJlbnRfY2xhc3MgPSBjbHM7XG5cdFx0XHRcdC8vY29uc29sZS5sb2coIFwiU2V0dGluZyBjdXJyZW50IGNsYXNzOlwiLCBjdXJyZW50X2NsYXNzLm5hbWUgKTtcblx0XHRcdFx0Y3VycmVudF9jbGFzc19maWVsZCA9IDA7XG5cdFx0XHRcdGVsZW1lbnRzID0gdG1wb2JqO1xuXHRcdFx0XHRpZiggIXJvb3RPYmplY3QgKSByb290T2JqZWN0ID0gZWxlbWVudHM7XG5cdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfU1RBQ0sgJiYgY29uc29sZS5sb2coIFwicHVzaCBjb250ZXh0IChvcGVuIG9iamVjdCk6IFwiLCBjb250ZXh0X3N0YWNrLmxlbmd0aCwgXCIgbmV3IG1vZGU6XCIsIG5leHRNb2RlICk7XG5cdFx0XHRcdGNvbnRleHRfc3RhY2sucHVzaCggb2xkX2NvbnRleHQgKTtcblx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIlJFU0VUIE9CSkVDVCBGSUVMRFwiLCBvbGRfY29udGV4dCwgY29udGV4dF9zdGFjayApO1xuXHRcdFx0XHRSRVNFVF9WQUwoKTtcblx0XHRcdFx0cGFyc2VfY29udGV4dCA9IG5leHRNb2RlO1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gb3BlbkFycmF5KCkge1xuXHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwib3BlbkFycmF5KCkuLi5cIiApO1xuXHRcdFx0XHRpZiggd29yZCA+IFdPUkRfUE9TX1JFU0VUICYmIHdvcmQgPCBXT1JEX1BPU19GSUVMRCApXG5cdFx0XHRcdFx0cmVjb3ZlcklkZW50KCA5MSApO1xuXG5cdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0VORCAmJiB2YWwuc3RyaW5nLmxlbmd0aCApIHtcblx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICYmIGNvbnNvbGUubG9nKCBcInJlY292ZXIgYXJyYXlUeXBlOlwiLCBhcnJheVR5cGUsIHZhbC5zdHJpbmcgKTtcblx0XHRcdFx0XHRsZXQgdHlwZUluZGV4ID0ga25vd25BcnJheVR5cGVOYW1lcy5maW5kSW5kZXgoIHR5cGU9Pih0eXBlID09PSB2YWwuc3RyaW5nKSApO1xuXHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRpZiggdHlwZUluZGV4ID49IDAgKSB7XG5cdFx0XHRcdFx0XHRhcnJheVR5cGUgPSB0eXBlSW5kZXg7XG5cdFx0XHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gdmFsLnN0cmluZztcblx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgPSBudWxsO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiggdmFsLnN0cmluZyA9PT0gXCJyZWZcIiApIHtcblx0XHRcdFx0XHRcdFx0dmFsLmNsYXNzTmFtZSA9IG51bGw7XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJUaGlzIHdpbGwgYmUgYSByZWZlcmVuY2UgcmVjb3ZlcnkgZm9yIGtleTpcIiwgdmFsICk7XG5cdFx0XHRcdFx0XHRcdGFycmF5VHlwZSA9IC0yO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0aWYoIGxvY2FsRnJvbVByb3RvVHlwZXMuZ2V0KCB2YWwuc3RyaW5nICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLmNsYXNzTmFtZSA9IHZhbC5zdHJpbmc7XG5cdFx0XHRcdFx0XHRcdH0gXG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIGZyb21Qcm90b1R5cGVzLmdldCggdmFsLnN0cmluZyApICkge1xuXHRcdFx0XHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSB2YWwuc3RyaW5nO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Vcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBgVW5rbm93biB0eXBlICcke3ZhbC5zdHJpbmd9JyBzcGVjaWZpZWQgZm9yIGFycmF5YCwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiICEhISEhQSBTZXQgQ2xhc3NuYW1lOlwiLCB2YWwuY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTEQgfHwgd29yZCA9PSBXT1JEX1BPU19GSUVMRCB8fCB3b3JkID09IFdPUkRfUE9TX0FGVEVSX0ZJRUxEICkge1xuXHRcdFx0XHRcdHRocm93RXJyb3IoIFwiRmF1bHQgd2hpbGUgcGFyc2luZzsgd2hpbGUgZ2V0dGluZyBmaWVsZCBuYW1lIHVuZXhwZWN0ZWRcIiwgY0ludCApO1xuXHRcdFx0XHRcdHN0YXR1cyA9IGZhbHNlO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGV0IG9sZF9jb250ZXh0ID0gZ2V0Q29udGV4dCgpO1xuXHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiQmVnaW4gYSBuZXcgYXJyYXk7IHByZXZpb3VzbHkgcHVzaGVkIGludG8gZWxlbWVudHM7IGJ1dCB3YWl0IHVudGlsIHRyYWlsaW5nIGNvbW1hIG9yIGNsb3NlIHByZXZpb3VzbHkgXCIsIHZhbC52YWx1ZV90eXBlICk7XG5cblx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiT3BlbmluZyBhcnJheTpcIiwgdmFsLCBwYXJzZV9jb250ZXh0ICk7XG5cdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9BUlJBWTtcblx0XHRcdFx0XHRsZXQgdG1wYXJyID0gW107XG5cdFx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOIClcblx0XHRcdFx0XHRcdGVsZW1lbnRzID0gdG1wYXJyO1xuXHRcdFx0XHRcdGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9JTl9BUlJBWSApIHtcblx0XHRcdFx0XHRcdGlmKCBhcnJheVR5cGUgPT0gLTEgKXtcblx0XHRcdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJQdXNoaW5nIG5ldyBvcGVuaW5nIGFycmF5IGludG8gZXhpc3RpbmcgYXJyYXkgYWxyZWFkeSBSRS1TRVRcIiApO1xuXHRcdFx0XHRcdFx0XHRlbGVtZW50cy5wdXNoKCB0bXBhcnIgKTtcblx0XHRcdFx0XHRcdH0gLy9lbHNlIGlmKCAvL19ERUJVR19QQVJTSU5HICYmIGFycmF5VHlwZSAhPT0gLTMgKVxuXHRcdFx0XHRcdFx0dmFsLm5hbWUgPSBlbGVtZW50cy5sZW5ndGg7XG5cdFx0XHRcdFx0XHQvL1x0Y29uc29sZS5sb2coIFwiVGhpcyBpcyBhbiBpbnZhbGlkIHBhcnNpbmcgc3RhdGUsIHR5cGVkIGFycmF5IHdpdGggc3ViLWFycmF5IGVsZW1lbnRzXCIgKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTERfVkFMVUUgKSB7XG5cdFx0XHRcdFx0XHRpZiggIXZhbC5uYW1lICkge1xuXHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyggXCJUaGlzIHNheXMgaXQncyByZXNvbHZlZC4uLi4uLi5cIiApO1xuXHRcdFx0XHRcdFx0XHRhcnJheVR5cGUgPSAtMztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0aWYoIGN1cnJlbnRfcHJvdG8gJiYgY3VycmVudF9wcm90by5wcm90b0RlZiApIHtcblx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIlNPTUVUSElORyBTSE9VTEQgSEFWRSBCRUVOIFJFUExBQ0VEIEhFUkU/P1wiLCBjdXJyZW50X3Byb3RvICk7XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCIobmVlZCB0byBkbyBmcm9tcHJvdG90b3lwZXMgaGVyZSkgb2JqZWN0OlwiLCB2YWwsIHZhbHVlICk7XG5cdFx0XHRcdFx0XHRcdGlmKCBjdXJyZW50X3Byb3RvLnByb3RvRGVmLmNiICl7XG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgbmV3YXJyID0gY3VycmVudF9wcm90by5wcm90b0RlZi5jYi5jYWxsKCBlbGVtZW50cywgdmFsLm5hbWUsIHRtcGFyciApO1xuXHRcdFx0XHRcdFx0XHRcdGlmKCBuZXdhcnIgIT09IHVuZGVmaW5lZCApIHRtcGFyciA9IGVsZW1lbnRzW3ZhbC5uYW1lXSA9IG5ld2Fycjtcblx0XHRcdFx0XHRcdFx0XHQvL2Vsc2UgY29uc29sZS5sb2coIFwiV2FybmluZzogUmVjZWl2ZWQgdW5kZWZpbmVkIGZvciBhbiBhcnJheTsga2VlcGluZyBvcmlnaW5hbCBhcnJheSwgbm90IHNldHRpbmcgZmllbGRcIiApO1xuXHRcdFx0XHRcdFx0XHR9ZWxzZVxuXHRcdFx0XHRcdFx0XHRcdGVsZW1lbnRzW3ZhbC5uYW1lXSA9IHRtcGFycjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHNbdmFsLm5hbWVdID0gdG1wYXJyO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRvbGRfY29udGV4dC5jb250ZXh0ID0gcGFyc2VfY29udGV4dDtcblx0XHRcdFx0XHRvbGRfY29udGV4dC5lbGVtZW50cyA9IGVsZW1lbnRzO1xuXHRcdFx0XHRcdC8vb2xkX2NvbnRleHQuZWxlbWVudF9hcnJheSA9IGVsZW1lbnRfYXJyYXk7XG5cdFx0XHRcdFx0b2xkX2NvbnRleHQubmFtZSA9IHZhbC5uYW1lO1xuXHRcdFx0XHRcdG9sZF9jb250ZXh0LmN1cnJlbnRfcHJvdG8gPSBjdXJyZW50X3Byb3RvO1xuXHRcdFx0XHRcdG9sZF9jb250ZXh0LmN1cnJlbnRfY2xhc3MgPSBjdXJyZW50X2NsYXNzO1xuXHRcdFx0XHRcdG9sZF9jb250ZXh0LmN1cnJlbnRfY2xhc3NfZmllbGQgPSBjdXJyZW50X2NsYXNzX2ZpZWxkO1xuXHRcdFx0XHRcdC8vIGFscmVhZHkgcHVzaGVkP1xuXHRcdFx0XHRcdG9sZF9jb250ZXh0LnZhbHVlVHlwZSA9IHZhbC52YWx1ZV90eXBlO1xuXHRcdFx0XHRcdG9sZF9jb250ZXh0LmFycmF5VHlwZSA9IChhcnJheVR5cGU9PS0xKT8tMzphcnJheVR5cGU7IC8vIHBvcCB0aGF0IHdlIGRvbid0IHdhbnQgdG8gaGF2ZSB0aGlzIHZhbHVlIHJlLXB1c2hlZC5cblx0XHRcdFx0XHRvbGRfY29udGV4dC5jbGFzc05hbWUgPSB2YWwuY2xhc3NOYW1lO1xuXHRcdFx0XHRcdGFycmF5VHlwZSA9IC0xO1xuXHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSBudWxsO1xuXG5cdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIiAhISEhIUIgQ2xlYXIgQ2xhc3NuYW1lOlwiLCBvbGRfY29udGV4dCwgdmFsLmNsYXNzTmFtZSwgb2xkX2NvbnRleHQuY2xhc3NOYW1lLCBvbGRfY29udGV4dC5uYW1lICk7XG5cdFx0XHRcdFx0dmFsLm5hbWUgPSBudWxsO1xuXHRcdFx0XHRcdGN1cnJlbnRfcHJvdG8gPSBudWxsO1xuXHRcdFx0XHRcdGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuXHRcdFx0XHRcdGN1cnJlbnRfY2xhc3NfZmllbGQgPSAwO1xuXHRcdFx0XHRcdC8vZWxlbWVudF9hcnJheSA9IHRtcGFycjtcblx0XHRcdFx0XHRlbGVtZW50cyA9IHRtcGFycjtcblx0XHRcdFx0XHRpZiggIXJvb3RPYmplY3QgKSByb290T2JqZWN0ID0gdG1wYXJyO1xuXHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfU1RBQ0sgJiYgY29uc29sZS5sb2coIFwicHVzaCBjb250ZXh0IChvcGVuIGFycmF5KTogXCIsIGNvbnRleHRfc3RhY2subGVuZ3RoICk7XG5cdFx0XHRcdFx0Y29udGV4dF9zdGFjay5wdXNoKCBvbGRfY29udGV4dCApO1xuXHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJSRVNFVCBBUlJBWSBGSUVMRFwiLCBvbGRfY29udGV4dCwgY29udGV4dF9zdGFjayApO1xuXG5cdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0cGFyc2VfY29udGV4dCA9IENPTlRFWFRfSU5fQVJSQVk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdGZ1bmN0aW9uIGdldFByb3RvKCkge1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSB7cHJvdG9EZWY6bnVsbCxjbHM6bnVsbH07XG5cdFx0XHRcdGlmKCAoIHJlc3VsdC5wcm90b0RlZiA9IGxvY2FsRnJvbVByb3RvVHlwZXMuZ2V0KCB2YWwuc3RyaW5nICkgKSApIHtcblx0XHRcdFx0XHRpZiggIXZhbC5jbGFzc05hbWUgKXtcblx0XHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSB2YWwuc3RyaW5nO1xuXHRcdFx0XHRcdFx0dmFsLnN0cmluZyA9IG51bGw7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vIG5lZWQgdG8gY29sbGVjdCB0aGUgb2JqZWN0LCBcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmKCAoIHJlc3VsdC5wcm90b0RlZiA9IGZyb21Qcm90b1R5cGVzLmdldCggdmFsLnN0cmluZyApICkgKSB7XG5cdFx0XHRcdFx0aWYoICF2YWwuY2xhc3NOYW1lICl7XG5cdFx0XHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gdmFsLnN0cmluZztcblx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgPSBudWxsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBcblx0XHRcdFx0aWYoIHZhbC5zdHJpbmcgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmVzdWx0LmNscyA9IGNsYXNzZXMuZmluZCggY2xzPT5jbHMubmFtZSA9PT0gdmFsLnN0cmluZyApO1xuXHRcdFx0XHRcdGlmKCAhcmVzdWx0LnByb3RvRGVmICYmICFyZXN1bHQuY2xzICkge1xuXHRcdFx0XHRcdCAgICAvLyB0aGlzIHdpbGwgY3JlYWV0IGEgY2xhc3MgZGVmIHdpdGggYSBuZXcgcHJvdG8gdG8gY292ZXIgd2hlbiB3ZSBkb24ndCBLTk9XLlxuXHRcdFx0XHRcdCAgICAvL3Rocm93RXJyb3IoIFwiUmVmZXJlbmNlZCBjbGFzcyBcIiArIHZhbC5zdHJpbmcgKyBcIiBoYXMgbm90IGJlZW4gZGVmaW5lZFwiLCBjSW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiAocmVzdWx0LnByb3RvRGVmfHxyZXN1bHQuY2xzKT9yZXN1bHQ6bnVsbDtcblx0XHRcdH1cblxuXHRcdFx0aWYoICFzdGF0dXMgKVxuXHRcdFx0XHRyZXR1cm4gLTE7XG5cblx0XHRcdGlmKCBtc2cgJiYgbXNnLmxlbmd0aCApIHtcblx0XHRcdFx0aW5wdXQgPSBnZXRCdWZmZXIoKTtcblx0XHRcdFx0aW5wdXQuYnVmID0gbXNnO1xuXHRcdFx0XHRpblF1ZXVlLnB1c2goIGlucHV0ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiggZ2F0aGVyaW5nTnVtYmVyICkge1xuXHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiRm9yY2UgY29tcGxldGVkLlwiKVxuXHRcdFx0XHRcdGdhdGhlcmluZ051bWJlciA9IGZhbHNlO1xuXHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfTlVNQkVSO1xuXHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfVU5LTk9XTiApIHtcblx0XHRcdFx0XHRcdGNvbXBsZXRlZCA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHZhbCA9IDE7ICAvLyBpZiByZXR1cm5pbmcgYnVmZmVycywgdGhlbiBvYnZpb3VzbHkgdGhlcmUncyBtb3JlIGluIHRoaXMgb25lLlxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ICE9PSBDT05URVhUX1VOS05PV04gKVxuXHRcdFx0XHRcdHRocm93RXJyb3IoIFwiVW5jbG9zZWQgb2JqZWN0IGF0IGVuZCBvZiBzdHJlYW0uXCIsIGNJbnQgKTtcblx0XHRcdH1cblxuXHRcdFx0d2hpbGUoIHN0YXR1cyAmJiAoIGlucHV0ID0gaW5RdWV1ZS5zaGlmdCgpICkgKSB7XG5cdFx0XHRcdG4gPSBpbnB1dC5uO1xuXHRcdFx0XHRidWYgPSBpbnB1dC5idWY7XG5cdFx0XHRcdGlmKCBnYXRoZXJpbmdTdHJpbmcgKSB7XG5cdFx0XHRcdFx0bGV0IHN0cmluZ19zdGF0dXMgPSBnYXRoZXJTdHJpbmcoIGdhdGhlcmluZ1N0cmluZ0ZpcnN0Q2hhciApO1xuXHRcdFx0XHRcdGlmKCBzdHJpbmdfc3RhdHVzIDwgMCApXG5cdFx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRlbHNlIGlmKCBzdHJpbmdfc3RhdHVzID4gMCApIHtcblx0XHRcdFx0XHRcdGdhdGhlcmluZ1N0cmluZyA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0aWYoIHN0YXR1cyApIHZhbC52YWx1ZV90eXBlID0gVkFMVUVfU1RSSU5HO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRpZiggZ2F0aGVyaW5nTnVtYmVyICkge1xuXHRcdFx0XHRcdGNvbGxlY3ROdW1iZXIoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHdoaWxlKCAhY29tcGxldGVkICYmIHN0YXR1cyAmJiAoIG4gPCBidWYubGVuZ3RoICkgKSB7XG5cdFx0XHRcdFx0c3RyID0gYnVmLmNoYXJBdChuKTtcblx0XHRcdFx0XHRjSW50ID0gYnVmLmNvZGVQb2ludEF0KG4rKyk7XG5cdFx0XHRcdFx0aWYoIGNJbnQgPj0gMHgxMDAwMCApIHsgc3RyICs9IGJ1Zi5jaGFyQXQobik7IG4rKzsgfVxuXHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwicGFyc2luZyBhdCBcIiwgY0ludCwgc3RyICk7XG5cdFx0XHRcdFx0Ly9fREVCVUdfTEwgJiYgY29uc29sZS5sb2coIFwicHJvY2Vzc2luZzogXCIsIGNJbnQsIG4sIHN0ciwgcG9zLCBjb21tZW50LCBwYXJzZV9jb250ZXh0LCB3b3JkICk7XG5cdFx0XHRcdFx0cG9zLmNvbCsrO1xuXHRcdFx0XHRcdGlmKCBjb21tZW50ICkge1xuXHRcdFx0XHRcdFx0aWYoIGNvbW1lbnQgPT0gMSApIHtcblx0XHRcdFx0XHRcdFx0aWYoIGNJbnQgPT0gNDIvKicqJyovICkgY29tbWVudCA9IDM7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIGNJbnQgIT0gNDcvKicvJyovICkgcmV0dXJuIHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZztcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRlbHNlIGNvbW1lbnQgPSAyO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSBpZiggY29tbWVudCA9PSAyICkge1xuXHRcdFx0XHRcdFx0XHRpZiggY0ludCA9PSAxMC8qJ1xcbicqLyB8fCBjSW50ID09IDEzLyonXFxyJyovICApIGNvbW1lbnQgPSAwO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSBpZiggY29tbWVudCA9PSAzICkge1xuXHRcdFx0XHRcdFx0XHRpZiggY0ludCA9PSA0Mi8qJyonKi8gKSBjb21tZW50ID0gNDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRpZiggY0ludCA9PSA0Ny8qJy8nKi8gKSBjb21tZW50ID0gMDtcblx0XHRcdFx0XHRcdFx0ZWxzZSBjb21tZW50ID0gMztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzd2l0Y2goIGNJbnQgKSB7XG5cdFx0XHRcdFx0Y2FzZSAzNS8qJyMnKi86XG5cdFx0XHRcdFx0XHRjb21tZW50ID0gMjsgLy8gcHJldGVuZCB0aGlzIGlzIHRoZSBzZWNvbmQgc2xhc2guXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIDQ3LyonLycqLzpcblx0XHRcdFx0XHRcdGNvbW1lbnQgPSAxO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAxMjMvKid7JyovOlxuXHRcdFx0XHRcdFx0b3Blbk9iamVjdCgpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSA5MS8qJ1snKi86XG5cdFx0XHRcdFx0XHRvcGVuQXJyYXkoKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0Y2FzZSA1OC8qJzonKi86XG5cdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICYmIGNvbnNvbGUubG9nKCBcImNvbG9uIHJlY2VpdmVkLi4uXCIpXG5cdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX0NMQVNTX1ZBTFVFICkge1xuXHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0XHRcdHZhbC5uYW1lID0gdmFsLnN0cmluZztcblx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1VOU0VUO1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRFxuXHRcdFx0XHRcdFx0XHR8fCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfQ0xBU1NfRklFTEQgICkge1xuXHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX0NMQVNTX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmKCAhT2JqZWN0LmtleXMoIGVsZW1lbnRzKS5sZW5ndGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQgY29uc29sZS5sb2coIFwiVGhpcyBpcyBhIGZ1bGwgb2JqZWN0LCBub3QgYSBjbGFzcyBkZWYuLi5cIiwgdmFsLmNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHByaXZhdGVQcm90byA9ICgpPT57fSBcblx0XHRcdFx0XHRcdFx0XHRsb2NhbEZyb21Qcm90b1R5cGVzLnNldCggY29udGV4dF9zdGFjay5sYXN0Lm5vZGUuY3VycmVudF9jbGFzcy5uYW1lLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHsgcHJvdG9Db246cHJpdmF0ZVByb3RvLnByb3RvdHlwZS5jb25zdHJ1Y3RvclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgY2I6IG51bGwgfVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgICApO1xuXHRcdFx0XHRcdFx0XHRcdGVsZW1lbnRzID0gbmV3IHByaXZhdGVQcm90bygpO1xuXHRcdFx0XHRcdFx0XHRcdHBhcnNlX2NvbnRleHQgPSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRVxuXHRcdFx0XHRcdFx0XHRcdHZhbC5uYW1lID0gdmFsLnN0cmluZztcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyA9ICcnXG5cdFx0XHRcdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9VTlNFVDtcblx0XHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyggXCJkb24ndCBkbyBkZWZhdWx0O3MgZG8gYSByZXZpdmUuLi5cIiApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCAhPSBXT1JEX1BPU19SRVNFVFxuXHRcdFx0XHRcdFx0XHRcdCAgICYmIHdvcmQgIT0gV09SRF9QT1NfRU5EXG5cdFx0XHRcdFx0XHRcdFx0ICAgJiYgd29yZCAhPSBXT1JEX1BPU19GSUVMRFxuXHRcdFx0XHRcdFx0XHRcdCAgICYmIHdvcmQgIT0gV09SRF9QT1NfQUZURVJfRklFTEQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZWNvdmVySWRlbnQoIDMyICk7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBhbGxvdyBzdGFydGluZyBhIG5ldyB3b3JkXG5cdFx0XHRcdFx0XHRcdFx0XHQvL3N0YXR1cyA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly90aHJvd0Vycm9yKCBgZmF1bHQgd2hpbGUgcGFyc2luZzsgdW5xdW90ZWQga2V5d29yZCB1c2VkIGFzIG9iamVjdCBmaWVsZCBuYW1lIChzdGF0ZToke3dvcmR9KWAsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0XHRcdC8vYnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRcdFx0XHR2YWwubmFtZSA9IHZhbC5zdHJpbmc7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdHBhcnNlX2NvbnRleHQgPSAocGFyc2VfY29udGV4dD09PUNPTlRFWFRfT0JKRUNUX0ZJRUxEKT9DT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRTpDT05URVhUX0NMQVNTX0ZJRUxEX1ZBTFVFO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfVU5TRVQ7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOICl7XG5cdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCBcIk92ZXJyaWRlIGNvbG9uIGZvdW5kLCBhbGxvdyBjbGFzcyByZWRlZmluaXRpb25cIiwgcGFyc2VfY29udGV4dCApO1xuXHRcdFx0XHRcdFx0XHRyZWRlZmluZUNsYXNzID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX0lOX0FSUkFZIClcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCAgXCIoaW4gYXJyYXksIGdvdCBjb2xvbiBvdXQgb2Ygc3RyaW5nKTpwYXJzaW5nIGZhdWx0O1wiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTERfVkFMVUUgKXtcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcIlN0cmluZyB1bmV4cGVjdGVkXCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlXG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCIob3V0c2lkZSBhbnkgb2JqZWN0LCBnb3QgY29sb24gb3V0IG9mIHN0cmluZyk6cGFyc2luZyBmYXVsdDtcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgMTI1LyonfScqLzpcblx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiY2xvc2UgYnJhY2tldCBjb250ZXh0OlwiLCB3b3JkLCBwYXJzZV9jb250ZXh0LCB2YWwudmFsdWVfdHlwZSwgdmFsLnN0cmluZyApO1xuXHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfRU5EICkge1xuXHRcdFx0XHRcdFx0XHQvLyBhbGxvdyBzdGFydGluZyBhIG5ldyB3b3JkXG5cdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vIGNvbWluZyBiYWNrIGFmdGVyIHB1c2hpbmcgYW4gYXJyYXkgb3Igc3ViLW9iamVjdCB3aWxsIHJlc2V0IHRoZSBjb250eHQgdG8gRklFTEQsIHNvIGFuIGVuZCB3aXRoIGEgZmllbGQgc2hvdWxkIHN0aWxsIHB1c2ggdmFsdWUuXG5cdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX0NMQVNTX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0XHRpZiggY3VycmVudF9jbGFzcyApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBhbGxvdyBibGFuayBjb21tYSBhdCBlbmQgdG8gbm90IGJlIGEgZmllbGRcblx0XHRcdFx0XHRcdFx0XHRpZih2YWwuc3RyaW5nKSB7IGN1cnJlbnRfY2xhc3MuZmllbGRzLnB1c2goIHZhbC5zdHJpbmcgKTsgfVxuXG5cdFx0XHRcdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0XHRcdFx0bGV0IG9sZF9jb250ZXh0ID0gY29udGV4dF9zdGFjay5wb3AoKTtcblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiY2xvc2Ugb2JqZWN0OlwiLCBvbGRfY29udGV4dCwgY29udGV4dF9zdGFjayApO1xuXHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfU1RBQ0sgJiYgY29uc29sZS5sb2coIFwib2JqZWN0IHBvcCBzdGFjayAoY2xvc2Ugb2JqKVwiLCBjb250ZXh0X3N0YWNrLmxlbmd0aCwgb2xkX2NvbnRleHQgKTtcblx0XHRcdFx0XHRcdFx0XHRwYXJzZV9jb250ZXh0ID0gQ09OVEVYVF9VTktOT1dOOyAvLyB0aGlzIHdpbGwgcmVzdG9yZSBhcyBJTl9BUlJBWSBvciBPQkpFQ1RfRklFTERcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLm5hbWUgPSBvbGRfY29udGV4dC5uYW1lO1xuXHRcdFx0XHRcdFx0XHRcdGVsZW1lbnRzID0gb2xkX2NvbnRleHQuZWxlbWVudHM7XG5cdFx0XHRcdFx0XHRcdFx0Ly9lbGVtZW50X2FycmF5ID0gb2xkX2NvbnRleHQuZWxlbWVudF9hcnJheTtcblx0XHRcdFx0XHRcdFx0XHRjdXJyZW50X2NsYXNzID0gb2xkX2NvbnRleHQuY3VycmVudF9jbGFzcztcblx0XHRcdFx0XHRcdFx0XHRjdXJyZW50X2NsYXNzX2ZpZWxkID0gb2xkX2NvbnRleHQuY3VycmVudF9jbGFzc19maWVsZDtcblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiQSBQb3Agb2xkIGNsYXNzIGZpZWxkIGNvdW50ZXI6XCIsIGN1cnJlbnRfY2xhc3NfZmllbGQsIHZhbC5uYW1lICk7XG5cdFx0XHRcdFx0XHRcdFx0YXJyYXlUeXBlID0gb2xkX2NvbnRleHQuYXJyYXlUeXBlO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gb2xkX2NvbnRleHQudmFsdWVUeXBlO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSBvbGRfY29udGV4dC5jbGFzc05hbWU7XG5cdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIiAhISEhIUMgUG9wIENsYXNzbmFtZTpcIiwgdmFsLmNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdFx0XHRcdHJvb3RPYmplY3QgPSBudWxsO1xuXG5cdFx0XHRcdFx0XHRcdFx0ZHJvcENvbnRleHQoIG9sZF9jb250ZXh0ICk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJTdGF0ZSBlcnJvcjsgZ2F0aGVyaW5nIGNsYXNzIGZpZWxkcywgYW5kIGxvc3QgdGhlIGNsYXNzXCIsIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmKCAoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTEQgKSB8fCAoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9DTEFTU19WQUxVRSApICkge1xuXHRcdFx0XHRcdFx0XHRpZiggdmFsLnZhbHVlX3R5cGUgIT0gVkFMVUVfVU5TRVQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYoIGN1cnJlbnRfY2xhc3MgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiQyBTdGVwcGluZyBjdXJyZW50IGNsYXNzIGZpZWxkOlwiLCBjdXJyZW50X2NsYXNzX2ZpZWxkLCB2YWwubmFtZSwgYXJyYXlUeXBlICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YWwubmFtZSA9IGN1cnJlbnRfY2xhc3MuZmllbGRzW2N1cnJlbnRfY2xhc3NfZmllbGQrK107XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiQ2xvc2luZyBvYmplY3Q7IHNldCB2YWx1ZSBuYW1lLCBhbmQgcHVzaC4uLlwiLCBjdXJyZW50X2NsYXNzX2ZpZWxkLCB2YWwgKTtcblx0XHRcdFx0XHRcdFx0XHRvYmplY3RQdXNoKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJjbG9zZSBvYmplY3Q7IGVtcHR5IG9iamVjdFwiLCB2YWwsIGVsZW1lbnRzICk7XG5cblx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX09CSkVDVDtcblx0XHRcdFx0XHRcdFx0XHRpZiggY3VycmVudF9wcm90byAmJiBjdXJyZW50X3Byb3RvLnByb3RvRGVmICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29uc29sZS5sb2coIFwiU09NRVRISU5HIFNIT1VMRCBBSFZFIEJFRU4gUkVQTEFDRUQgSEVSRT8/XCIsIGN1cnJlbnRfcHJvdG8gKTtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCBcIlRoZSBvdGhlciB2ZXJzaW9uIG9ubHkgcmV2aXZlcyBvbiBpbml0XCIgKTtcblx0XHRcdFx0XHRcdFx0XHRcdGVsZW1lbnRzID0gbmV3IGN1cnJlbnRfcHJvdG8ucHJvdG9EZWYuY2IoIGVsZW1lbnRzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly9lbGVtZW50cyA9IG5ldyBjdXJyZW50X3Byb3RvLnByb3RvQ29uKCBlbGVtZW50cyApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR2YWwuY29udGFpbnMgPSBlbGVtZW50cztcblx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nID0gXCJcIjtcblxuXHRcdFx0XHRcdFx0XHRsZXQgb2xkX2NvbnRleHQgPSBjb250ZXh0X3N0YWNrLnBvcCgpO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX1NUQUNLICYmIGNvbnNvbGUubG9nKCBcIm9iamVjdCBwb3Agc3RhY2sgKGNsb3NlIG9iailcIiwgY29udGV4dF9zdGFjay5sZW5ndGgsIG9sZF9jb250ZXh0ICk7XG5cdFx0XHRcdFx0XHRcdHBhcnNlX2NvbnRleHQgPSBvbGRfY29udGV4dC5jb250ZXh0OyAvLyB0aGlzIHdpbGwgcmVzdG9yZSBhcyBJTl9BUlJBWSBvciBPQkpFQ1RfRklFTERcblx0XHRcdFx0XHRcdFx0dmFsLm5hbWUgPSBvbGRfY29udGV4dC5uYW1lO1xuXHRcdFx0XHRcdFx0XHRlbGVtZW50cyA9IG9sZF9jb250ZXh0LmVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHQvL2VsZW1lbnRfYXJyYXkgPSBvbGRfY29udGV4dC5lbGVtZW50X2FycmF5O1xuXHRcdFx0XHRcdFx0XHRjdXJyZW50X2NsYXNzID0gb2xkX2NvbnRleHQuY3VycmVudF9jbGFzcztcblx0XHRcdFx0XHRcdFx0Y3VycmVudF9wcm90byA9IG9sZF9jb250ZXh0LmN1cnJlbnRfcHJvdG87XG5cdFx0XHRcdFx0XHRcdGN1cnJlbnRfY2xhc3NfZmllbGQgPSBvbGRfY29udGV4dC5jdXJyZW50X2NsYXNzX2ZpZWxkO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiQiBQb3Agb2xkIGNsYXNzIGZpZWxkIGNvdW50ZXI6XCIsIGNvbnRleHRfc3RhY2ssIGN1cnJlbnRfY2xhc3NfZmllbGQsIHZhbC5uYW1lICk7XG5cdFx0XHRcdFx0XHRcdGFycmF5VHlwZSA9IG9sZF9jb250ZXh0LmFycmF5VHlwZTtcblx0XHRcdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBvbGRfY29udGV4dC52YWx1ZVR5cGU7XG5cdFx0XHRcdFx0XHRcdHZhbC5jbGFzc05hbWUgPSBvbGRfY29udGV4dC5jbGFzc05hbWU7XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCIgISEhISFEIFBvcCBDbGFzc25hbWU6XCIsIHZhbC5jbGFzc05hbWUgKTtcblx0XHRcdFx0XHRcdFx0ZHJvcENvbnRleHQoIG9sZF9jb250ZXh0ICk7XG5cblx0XHRcdFx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOICkge1xuXHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2UgaWYoICggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRSApICkge1xuXHRcdFx0XHRcdFx0XHQvLyBmaXJzdCwgYWRkIHRoZSBsYXN0IHZhbHVlXG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiY2xvc2Ugb2JqZWN0OyBwdXNoIGl0ZW0gJyVzJyAlZFwiLCB2YWwubmFtZSwgdmFsLnZhbHVlX3R5cGUgKTtcblx0XHRcdFx0XHRcdFx0aWYoIHZhbC52YWx1ZV90eXBlID09PSBWQUxVRV9VTlNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcIkZhdWx0IHdoaWxlIHBhcnNpbmc7IHVuZXhwZWN0ZWRcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdG9iamVjdFB1c2goKTtcblx0XHRcdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9PQkpFQ1Q7XG5cdFx0XHRcdFx0XHRcdHZhbC5jb250YWlucyA9IGVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cblx0XHRcdFx0XHRcdFx0Ly9sZXQgb2xkX2NvbnRleHQgPSBjb250ZXh0X3N0YWNrLnBvcCgpO1xuXHRcdFx0XHRcdFx0XHRsZXQgb2xkX2NvbnRleHQgPSBjb250ZXh0X3N0YWNrLnBvcCgpO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX1NUQUNLICAmJiBjb25zb2xlLmxvZyggXCJvYmplY3QgcG9wIHN0YWNrIChjbG9zZSBvYmplY3QpXCIsIGNvbnRleHRfc3RhY2subGVuZ3RoLCBvbGRfY29udGV4dCApO1xuXHRcdFx0XHRcdFx0XHRwYXJzZV9jb250ZXh0ID0gb2xkX2NvbnRleHQuY29udGV4dDsgLy8gdGhpcyB3aWxsIHJlc3RvcmUgYXMgSU5fQVJSQVkgb3IgT0JKRUNUX0ZJRUxEXG5cdFx0XHRcdFx0XHRcdHZhbC5uYW1lID0gb2xkX2NvbnRleHQubmFtZTtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHMgPSBvbGRfY29udGV4dC5lbGVtZW50cztcblx0XHRcdFx0XHRcdFx0Y3VycmVudF9wcm90byA9IG9sZF9jb250ZXh0LmN1cnJlbnRfcHJvdG87XG5cdFx0XHRcdFx0XHRcdGN1cnJlbnRfY2xhc3MgPSBvbGRfY29udGV4dC5jdXJyZW50X2NsYXNzO1xuXHRcdFx0XHRcdFx0XHRjdXJyZW50X2NsYXNzX2ZpZWxkID0gb2xkX2NvbnRleHQuY3VycmVudF9jbGFzc19maWVsZDtcblx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIkMgUG9wIG9sZCBjbGFzcyBmaWVsZCBjb3VudGVyOlwiLCBjb250ZXh0X3N0YWNrLCBjdXJyZW50X2NsYXNzX2ZpZWxkLCB2YWwubmFtZSApO1xuXHRcdFx0XHRcdFx0XHRhcnJheVR5cGUgPSBvbGRfY29udGV4dC5hcnJheVR5cGU7XG5cdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gb2xkX2NvbnRleHQudmFsdWVUeXBlO1xuXHRcdFx0XHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gb2xkX2NvbnRleHQuY2xhc3NOYW1lO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiICEhISEhRSBQb3AgQ2xhc3NuYW1lOlwiLCB2YWwuY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0XHRcdC8vZWxlbWVudF9hcnJheSA9IG9sZF9jb250ZXh0LmVsZW1lbnRfYXJyYXk7XG5cdFx0XHRcdFx0XHRcdGRyb3BDb250ZXh0KCBvbGRfY29udGV4dCApO1xuXHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX1VOS05PV04gKSB7XG5cdFx0XHRcdFx0XHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiRmF1bHQgd2hpbGUgcGFyc2luZzsgdW5leHBlY3RlZFwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdHN0YXR1cyA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0bmVnYXRpdmUgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgOTMvKiddJyovOlxuXHRcdFx0XHRcdFx0aWYoIHdvcmQgPj0gV09SRF9QT1NfQUZURVJfRklFTEQgKSB7XG5cdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfSU5fQVJSQVkgKSB7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICAmJiBjb25zb2xlLmxvZyggXCJjbG9zZSBhcnJheSwgcHVzaCBsYXN0IGVsZW1lbnQ6ICVkXCIsIHZhbC52YWx1ZV90eXBlICk7XG5cdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSAhPSBWQUxVRV9VTlNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBuYW1lIGlzIHNldCB3aGVuIHNhdmluZyBhIGNvbnRleHQuXG5cdFx0XHRcdFx0XHRcdFx0Ly8gYSBiZXR0ZXIgc2FuaXR5IGNoZWNrIHdvdWxkIGJlIHZhbC5uYW1lID09PSBlbGVtZW50cy5sZW5ndGg7XG5cdFx0XHRcdFx0XHRcdFx0Ly9pZiggdmFsLm5hbWUgKSBpZiggdmFsLm5hbWUgIT09IGVsZW1lbnRzLmxlbmd0aCApIGNvbnNvbGUubG9nKCBcIllhIHRoaXMgc2hvdWxkIGJsb3cgdXBcIiApO1xuXHRcdFx0XHRcdFx0XHRcdGFycmF5UHVzaCgpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHZhbC5jb250YWlucyA9IGVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0bGV0IG9sZF9jb250ZXh0ID0gY29udGV4dF9zdGFjay5wb3AoKTtcblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX1NUQUNLICAmJiBjb25zb2xlLmxvZyggXCJvYmplY3QgcG9wIHN0YWNrIChjbG9zZSBhcnJheSlcIiwgY29udGV4dF9zdGFjay5sZW5ndGggKTtcblx0XHRcdFx0XHRcdFx0XHR2YWwubmFtZSA9IG9sZF9jb250ZXh0Lm5hbWU7XG5cdFx0XHRcdFx0XHRcdFx0dmFsLmNsYXNzTmFtZSA9IG9sZF9jb250ZXh0LmNsYXNzTmFtZTtcblx0XHRcdFx0XHRcdFx0XHRwYXJzZV9jb250ZXh0ID0gb2xkX2NvbnRleHQuY29udGV4dDtcblx0XHRcdFx0XHRcdFx0XHRlbGVtZW50cyA9IG9sZF9jb250ZXh0LmVsZW1lbnRzO1xuXHRcdFx0XHRcdFx0XHRcdC8vZWxlbWVudF9hcnJheSA9IG9sZF9jb250ZXh0LmVsZW1lbnRfYXJyYXk7XG5cdFx0XHRcdFx0XHRcdFx0Y3VycmVudF9wcm90byA9IG9sZF9jb250ZXh0LmN1cnJlbnRfcHJvdG87XG5cdFx0XHRcdFx0XHRcdFx0Y3VycmVudF9jbGFzcyA9IG9sZF9jb250ZXh0LmN1cnJlbnRfY2xhc3M7XG5cdFx0XHRcdFx0XHRcdFx0Y3VycmVudF9jbGFzc19maWVsZCA9IG9sZF9jb250ZXh0LmN1cnJlbnRfY2xhc3NfZmllbGQ7XG5cdFx0XHRcdFx0XHRcdFx0YXJyYXlUeXBlID0gb2xkX2NvbnRleHQuYXJyYXlUeXBlO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gb2xkX2NvbnRleHQudmFsdWVUeXBlO1xuXHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJjbG9zZSBhcnJheTpcIiwgb2xkX2NvbnRleHQgKTtcblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiRCBQb3Agb2xkIGNsYXNzIGZpZWxkIGNvdW50ZXI6XCIsIGNvbnRleHRfc3RhY2ssIGN1cnJlbnRfY2xhc3NfZmllbGQsIHZhbCApO1xuXHRcdFx0XHRcdFx0XHRcdGRyb3BDb250ZXh0KCBvbGRfY29udGV4dCApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfQVJSQVk7XG5cdFx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfVU5LTk9XTiApIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBgYmFkIGNvbnRleHQgJHtwYXJzZV9jb250ZXh0fTsgZmF1bHQgd2hpbGUgcGFyc2luZ2AsIGNJbnQgKTsvLyBmYXVsdFxuXHRcdFx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG5lZ2F0aXZlID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIDQ0LyonLCcqLzpcblx0XHRcdFx0XHRcdGlmKCB3b3JkIDwgV09SRF9QT1NfQUZURVJfRklFTEQgJiYgd29yZCAhPSBXT1JEX1BPU19SRVNFVCApIHtcblx0XHRcdFx0XHRcdFx0cmVjb3ZlcklkZW50KGNJbnQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfRU5EIHx8IHdvcmQgPT0gV09SRF9QT1NfRklFTEQgKSB3b3JkID0gV09SRF9QT1NfUkVTRVQ7ICAvLyBhbGxvdyBjb2xsZWN0IG5ldyBrZXl3b3JkXG5cdFx0XHRcdFx0XHQvL2lmKC8vX0RFQlVHX1BBUlNJTkcpIFxuXHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcImNvbW1hIGNvbnRleHQ6XCIsIHBhcnNlX2NvbnRleHQsIHZhbCApO1xuXHRcdFx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9DTEFTU19GSUVMRCApIHtcblx0XHRcdFx0XHRcdFx0aWYoIGN1cnJlbnRfY2xhc3MgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJTYXZpbmcgZmllbGQgbmFtZShzZXQgd29yZCB0byBJUyBBIEZJRUxEKTpcIiwgdmFsLnN0cmluZyApO1xuXHRcdFx0XHRcdFx0XHRcdGN1cnJlbnRfY2xhc3MuZmllbGRzLnB1c2goIHZhbC5zdHJpbmcgKTtcblx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nID0gJyc7XG5cdFx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX0ZJRUxEO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiU3RhdGUgZXJyb3I7IGdhdGhlcmluZyBjbGFzcyBmaWVsZHMsIGFuZCBsb3N0IHRoZSBjbGFzc1wiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRCApIHtcblx0XHRcdFx0XHRcdFx0aWYoIGN1cnJlbnRfY2xhc3MgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lOR19ERVRBSUxTICYmIGNvbnNvbGUubG9nKCBcIkQgU3RlcHBpbmcgY3VycmVudCBjbGFzcyBmaWVsZDpcIiwgY3VycmVudF9jbGFzc19maWVsZCwgdmFsLm5hbWUgKTtcblx0XHRcdFx0XHRcdFx0XHR2YWwubmFtZSA9IGN1cnJlbnRfY2xhc3MuZmllbGRzW2N1cnJlbnRfY2xhc3NfZmllbGQrK107XG5cdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJzaG91bGQgaGF2ZSBhIGNvbXBsZXRlZCB2YWx1ZSBhdCBhIGNvbW1hLjpcIiwgY3VycmVudF9jbGFzc19maWVsZCwgdmFsICk7XG5cdFx0XHRcdFx0XHRcdFx0aWYoIHZhbC52YWx1ZV90eXBlICE9IFZBTFVFX1VOU0VUICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAgJiYgY29uc29sZS5sb2coIFwicHVzaGluZyBvYmplY3QgZmllbGQ6XCIsIHZhbCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0b2JqZWN0UHVzaCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdC8vIHRoaXMgaXMgYW4gZW1wdHkgY29tbWEuLi5cblx0XHRcdFx0XHRcdFx0XHRpZiggdmFsLnN0cmluZyB8fCB2YWwudmFsdWVfdHlwZSApXG5cdFx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcIlN0YXRlIGVycm9yOyBjb21tYSBpbiBmaWVsZCBuYW1lIGFuZC9vciBsb3N0IHRoZSBjbGFzc1wiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSBpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX0NMQVNTX1ZBTFVFICkge1xuXHRcdFx0XHRcdFx0XHRpZiggY3VycmVudF9jbGFzcyApIHtcblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwicmV2aXZpbmcgdmFsdWVzIGluIGNsYXNzLi4uXCIsIGFycmF5VHlwZSwgY3VycmVudF9jbGFzcy5maWVsZHNbY3VycmVudF9jbGFzc19maWVsZCBdLCB2YWwgKTtcblx0XHRcdFx0XHRcdFx0XHRpZiggYXJyYXlUeXBlICE9IC0zICYmICF2YWwubmFtZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdC8vIHRoaXMgc2hvdWxkIGhhdmUgc3RpbGwgaGFkIGEgbmFtZS4uLi5cblx0XHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1BBUlNJTkdfREVUQUlMUyAmJiBjb25zb2xlLmxvZyggXCJFIFN0ZXBwaW5nIGN1cnJlbnQgY2xhc3MgZmllbGQ6XCIsIGN1cnJlbnRfY2xhc3NfZmllbGQsIHZhbCwgYXJyYXlUeXBlICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YWwubmFtZSA9IGN1cnJlbnRfY2xhc3MuZmllbGRzW2N1cnJlbnRfY2xhc3NfZmllbGQrK107XG5cdFx0XHRcdFx0XHRcdFx0XHQvL2Vsc2UgdmFsLm5hbWUgPSBjdXJyZW50X2NsYXNzLmZpZWxkc1tjdXJyZW50X2NsYXNzX2ZpZWxkKytdO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICYmIGNvbnNvbGUubG9nKCBcInNob3VsZCBoYXZlIGEgY29tcGxldGVkIHZhbHVlIGF0IGEgY29tbWEuOlwiLCBjdXJyZW50X2NsYXNzX2ZpZWxkLCB2YWwgKTtcblx0XHRcdFx0XHRcdFx0XHRpZiggdmFsLnZhbHVlX3R5cGUgIT0gVkFMVUVfVU5TRVQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiggYXJyYXlUeXBlICE9IC0zIClcblx0XHRcdFx0XHRcdFx0XHRcdFx0b2JqZWN0UHVzaCgpO1xuXHRcdFx0XHRcdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSAhPSBWQUxVRV9VTlNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdG9iamVjdFB1c2goKTtcblx0XHRcdFx0XHRcdFx0XHRcdFJFU0VUX1ZBTCgpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHQvL3Rocm93RXJyb3IoIFwiU3RhdGUgZXJyb3I7IGdhdGhlcmluZyBjbGFzcyB2YWx1ZXMsIGFuZCBsb3N0IHRoZSBjbGFzc1wiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0dmFsLm5hbWUgPSBudWxsO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfSU5fQVJSQVkgKSB7XG5cdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSA9PSBWQUxVRV9VTlNFVCApXG5cdFx0XHRcdFx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9FTVBUWTsgLy8gaW4gYW4gYXJyYXksIGVsZW1lbnRzIGFmdGVyIGEgY29tbWEgc2hvdWxkIGluaXQgYXMgdW5kZWZpbmVkLi4uXG5cblx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAgJiYgY29uc29sZS5sb2coIFwiYmFjayBpbiBhcnJheTsgcHVzaCBpdGVtICVkXCIsIHZhbC52YWx1ZV90eXBlICk7XG5cdFx0XHRcdFx0XHRcdGFycmF5UHVzaCgpO1xuXHRcdFx0XHRcdFx0XHRSRVNFVF9WQUwoKTtcblx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX1JFU0VUO1xuXHRcdFx0XHRcdFx0XHQvLyB1bmRlZmluZWQgYWxsb3dzIFssLCxdIHRvIGJlIDQgdmFsdWVzIGFuZCBbMSwyLDMsXSB0byBiZSA0IHZhbHVlcyB3aXRoIGFuIHVuZGVmaW5lZCBhdCBlbmQuXG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTERfVkFMVUUgJiYgdmFsLnZhbHVlX3R5cGUgIT0gVkFMVUVfVU5TRVQgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIGFmdGVyIGFuIGFycmF5IHZhbHVlLCBpdCB3aWxsIGhhdmUgcmV0dXJuZWQgdG8gT0JKRUNUX0ZJRUxEIGFueXdheVxuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICAmJiBjb25zb2xlLmxvZyggXCJjb21tYSBhZnRlciBmaWVsZCB2YWx1ZSwgcHVzaCBmaWVsZCB0byBvYmplY3Q6ICVzXCIsIHZhbC5uYW1lLCB2YWwudmFsdWVfdHlwZSApO1xuXHRcdFx0XHRcdFx0XHRwYXJzZV9jb250ZXh0ID0gQ09OVEVYVF9PQkpFQ1RfRklFTEQ7XG5cdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSAhPSBWQUxVRV9VTlNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHRvYmplY3RQdXNoKCk7XG5cdFx0XHRcdFx0XHRcdFx0UkVTRVRfVkFMKCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX1JFU0VUO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0c3RhdHVzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiYmFkIGNvbnRleHQ7IGV4Y2Vzc2l2ZSBjb21tYXMgd2hpbGUgcGFyc2luZztcIiwgY0ludCApOy8vIGZhdWx0XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRuZWdhdGl2ZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0c3dpdGNoKCBjSW50ICkge1xuXHRcdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdGlmKCAoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9VTktOT1dOIClcblx0XHRcdFx0XHRcdCAgfHwgKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfT0JKRUNUX0ZJRUxEX1ZBTFVFICYmIHdvcmQgPT0gV09SRF9QT1NfRklFTEQgKVxuXHRcdFx0XHRcdFx0ICB8fCAoICggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRCApIHx8IHdvcmQgPT0gV09SRF9QT1NfRklFTEQgKVxuXHRcdFx0XHRcdFx0ICB8fCAoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9DTEFTU19GSUVMRCApICkge1xuXHRcdFx0XHRcdFx0XHRzd2l0Y2goIGNJbnQgKSB7XG5cdFx0XHRcdFx0XHRcdGNhc2UgOTY6Ly8nYCc6XG5cdFx0XHRcdFx0XHRcdGNhc2UgMzQ6Ly8nXCInOlxuXHRcdFx0XHRcdFx0XHRjYXNlIDM5Oi8vJ1xcJyc6XG5cdFx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgfHwgd29yZCA9PSBXT1JEX1BPU19GSUVMRCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCB2YWwuc3RyaW5nLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Y29uc29sZS5sb2coIFwiSU4gQVJSQVkgQU5EIEZJWElORz9cIiApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuY2xhc3NOYW1lID0gdmFsLnN0cmluZztcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0bGV0IHN0cmluZ19zdGF0dXMgPSBnYXRoZXJTdHJpbmcoY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAmJiBjb25zb2xlLmxvZyggXCJzdHJpbmcgZ2F0aGVyIGZvciBvYmplY3QgZmllbGQgbmFtZSA6XCIsIHZhbC5zdHJpbmcsIHN0cmluZ19zdGF0dXMgKTtcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCBzdHJpbmdfc3RhdHVzICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1NUUklORztcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGdhdGhlcmluZ1N0cmluZ0ZpcnN0Q2hhciA9IGNJbnQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGdhdGhlcmluZ1N0cmluZyA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZzsgcXVvdGUgbm90IGF0IHN0YXJ0IG9mIGZpZWxkIG5hbWVcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRjYXNlIDEwOi8vJ1xcbic6XG5cdFx0XHRcdFx0XHRcdFx0cG9zLmxpbmUrKztcblx0XHRcdFx0XHRcdFx0XHRwb3MuY29sID0gMTtcblx0XHRcdFx0XHRcdFx0XHQvLyBmYWxsIHRocm91Z2ggdG8gbm9ybWFsIHNwYWNlIGhhbmRsaW5nIC0ganVzdCB1cGRhdGVkIGxpbmUvY29sIHBvc2l0aW9uXG5cdFx0XHRcdFx0XHRcdGNhc2UgMTM6Ly8nXFxyJzpcblx0XHRcdFx0XHRcdFx0Y2FzZSAzMjovLycgJzpcblx0XHRcdFx0XHRcdFx0Y2FzZSAweDIwMjg6Ly8nICc6XG5cdFx0XHRcdFx0XHRcdGNhc2UgMHgyMDI5Oi8vJyAnOlxuXHRcdFx0XHRcdFx0XHRjYXNlIDk6Ly8nXFx0Jzpcblx0XHRcdFx0XHRcdFx0Y2FzZSAweEZFRkY6IC8vIFpXTkJTIGlzIFdTIHRob3VnaFxuXHRcdFx0XHRcdFx0XHRcdCAvL19ERUJVR19XSElURVNQQUNFICAmJiBjb25zb2xlLmxvZyggXCJUSElTIFNQQUNFXCIsIHdvcmQsIHBhcnNlX2NvbnRleHQsIHZhbCApO1xuXHRcdFx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09PSBDT05URVhUX1VOS05PV04gJiYgd29yZCA9PT0gV09SRF9QT1NfRU5EICkgeyAvLyBhbGxvdyBjb2xsZWN0IG5ldyBrZXl3b3JkXG5cdFx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PT0gQ09OVEVYVF9VTktOT1dOICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09PSBXT1JEX1BPU19SRVNFVCB8fCB3b3JkID09PSBXT1JEX1BPU19BRlRFUl9GSUVMRCApIHsgLy8gaWdub3JlIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlcHNhY2Vcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfVU5LTk9XTiAmJiB2YWwudmFsdWVfdHlwZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRlbHNlIGlmKCB3b3JkID09PSBXT1JEX1BPU19GSUVMRCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09PSBDT05URVhUX1VOS05PV04gKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiggdmFsLnN0cmluZy5sZW5ndGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyggXCJTVEVQIFRPIE5FWFQgVE9LRU4uXCIgKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX0FGVEVSX0ZJRUxEO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQvL3ZhbC5jbGFzc05hbWUgPSB2YWwuc3RyaW5nOyB2YWwuc3RyaW5nID0gJyc7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0c3RhdHVzID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aHJvd0Vycm9yKCBcImZhdWx0IHdoaWxlIHBhcnNpbmc7IHdoaXRlcHNhY2UgdW5leHBlY3RlZFwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vIHNraXAgd2hpdGVzcGFjZVxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0XHRcdC8vaWYoIC8oKFxcbnxcXHJ8XFx0KXxzfFN8WyBcXHtcXH1cXChcXClcXDxcXD5cXCFcXCstXFwqXFwvXFwuXFw6XFwsIF0pLy5cblx0XHRcdFx0XHRcdFx0XHRpZiggdGVzdE5vbklkZW50aWZpZXJDaGFyYWN0ZXJzICkge1xuXHRcdFx0XHRcdFx0XHRcdGxldCBpZGVudFJvdyA9IG5vbklkZW50LmZpbmQoIHJvdz0+KHJvdy5maXJzdENoYXIgPj0gY0ludCApJiYgKHJvdy5sYXN0Q2hhciA+IGNJbnQpIClcblx0XHRcdFx0XHRcdFx0XHRpZiggaWRlbnRSb3cgJiYgKCBpZGVudFJvdy5iaXRzWyhjSW50IC0gaWRlbnRSb3cuZmlyc3RDaGFyKSAvIDI0XVxuXHRcdFx0XHRcdFx0XHRcdCAgICAmICgxIDw8ICgoY0ludCAtIGlkZW50Um93LmZpcnN0Q2hhcikgJSAyNCkpKSkge1xuXHRcdFx0XHRcdFx0XHRcdC8vaWYoIG5vbklkZW50WyhjSW50LygyNCoxNikpfDBdICYmIG5vbklkZW50WyhjSW50LygyNCoxNikpfDBdWygoIGNJbnQgJSAoMjQqMTYpICkvMjQpfDBdICYgKCAxIDw8IChjSW50JTI0KSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBpbnZhbGlkIHN0YXJ0L2NvbnRpbnVlXG5cdFx0XHRcdFx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIGBmYXVsdCB3aGlsZSBwYXJzaW5nIG9iamVjdCBmaWVsZCBuYW1lOyBcXFxcdSR7Y0ludH1gLCBjSW50ICk7XHQvLyBmYXVsdFxuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIlRJQ0tcIiApO1xuXHRcdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX1JFU0VUICYmICggKCBjSW50ID49IDQ4LyonMCcqLyAmJiBjSW50IDw9IDU3LyonOScqLyApIHx8ICggY0ludCA9PSA0My8qJysnKi8gKSB8fCAoIGNJbnQgPT0gNDYvKicuJyovICkgfHwgKCBjSW50ID09IDQ1LyonLScqLyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRmcm9tSGV4ID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHRleHBvbmVudCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0ZV9mb3JtYXQgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdGlzQmlnSW50ID0gZmFsc2U7XG5cblx0XHRcdFx0XHRcdFx0XHRcdGV4cG9uZW50X3NpZ24gPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdGV4cG9uZW50X2RpZ2l0ID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHRkZWNpbWFsID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nID0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0aW5wdXQubiA9IG47XG5cdFx0XHRcdFx0XHRcdFx0XHRjb2xsZWN0TnVtYmVyKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PT0gV09SRF9QT1NfQUZURVJfRklFTEQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRzdGF0dXMgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiZmF1bHQgd2hpbGUgcGFyc2luZzsgY2hhcmFjdGVyIHVuZXhwZWN0ZWRcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PT0gV09SRF9QT1NfUkVTRVQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfRklFTEQ7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1NUUklORztcblx0XHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly9fREVCVUdfUEFSU0lORyAgJiYgY29uc29sZS5sb2coIFwiU1RBUlQvQ09OVElOVUUgSURFTlRJRkVSXCIgKTtcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0XHRcdFx0fSAgICAgXG5cdFx0XHRcdFx0XHRcdFx0aWYoIHZhbC52YWx1ZV90eXBlID09IFZBTFVFX1VOU0VUICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgIT09IFdPUkRfUE9TX1JFU0VUICYmIHdvcmQgIT09IFdPUkRfUE9TX0VORCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJlY292ZXJJZGVudCggY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PT0gV09SRF9QT1NfRU5EIHx8IHdvcmQgPT09IFdPUkRfUE9TX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBmaW5hbCB3b3JkIG9mIHRoZSBsaW5lLi4uIFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyB3aGlzcGFjZSBjaGFuZ2VzIHRoZSAnd29yZCcgc3RhdGUgdG8gbm90ICdlbmQnXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIHVudGlsIHRoZSBuZXh0IGNoYXJhY3Rlciwgd2hpY2ggbWF5IHJlc3RvcmUgaXQgdG9cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gJ2VuZCcgYW5kIHRoaXMgd2lsbCByZXN1bWUgY29sbGVjdGluZyB0aGUgc2FtZSBzdHJpbmcuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfT0JKRUNUX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19GSUVMRCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nKz1zdHI7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJNdWx0aXBsZSB2YWx1ZXMgZm91bmQgaW4gZmllbGQgbmFtZVwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJTdHJpbmcgdW5leHBlY3RlZFwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrOyAvLyBkZWZhdWx0XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHR9ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX1JFU0VUICYmICggKCBjSW50ID49IDQ4LyonMCcqLyAmJiBjSW50IDw9IDU3LyonOScqLyApIHx8ICggY0ludCA9PSA0My8qJysnKi8gKSB8fCAoIGNJbnQgPT0gNDYvKicuJyovICkgfHwgKCBjSW50ID09IDQ1LyonLScqLyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0ZnJvbUhleCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdGV4cG9uZW50ID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0ZV9mb3JtYXQgPSBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRpc0JpZ0ludCA9IGZhbHNlO1xuXG5cdFx0XHRcdFx0XHRcdFx0ZXhwb25lbnRfc2lnbiA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdGV4cG9uZW50X2RpZ2l0ID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0ZGVjaW1hbCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgPSBzdHI7XG5cdFx0XHRcdFx0XHRcdFx0aW5wdXQubiA9IG47XG5cdFx0XHRcdFx0XHRcdFx0Y29sbGVjdE51bWJlcigpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiVElDS1wiKVxuXHRcdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSA9PSBWQUxVRV9VTlNFVCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCB3b3JkICE9IFdPUkRfUE9TX1JFU0VUICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZWNvdmVySWRlbnQoIGNJbnQgKTtcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19FTkQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1NUUklORztcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIHBhcnNlX2NvbnRleHQgPT0gQ09OVEVYVF9PQkpFQ1RfRklFTEQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiTXVsdGlwbGUgdmFsdWVzIGZvdW5kIGluIGZpZWxkIG5hbWVcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX09CSkVDVF9GSUVMRF9WQUxVRSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiggdmFsLnZhbHVlX3R5cGUgIT0gVkFMVUVfU1RSSU5HICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCB2YWwudmFsdWVfdHlwZSA9PSBWQUxVRV9PQkpFQ1QgfHwgdmFsLnZhbHVlX3R5cGUgPT0gVkFMVUVfQVJSQVkgKXtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiU3RyaW5nIHVuZXhwZWN0ZWRcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZWNvdmVySWRlbnQoY0ludCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfQUZURVJfRklFTEQgKXtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjb25zdCAgcHJvdG9EZWYgPSBnZXRQcm90bygpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCBwcm90b0RlZil7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR3b3JkID09IFdPUkRfUE9TX0VORDsgLy8gbGFzdCBzdHJpbmcuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nID0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRlbHNlIFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhyb3dFcnJvciggXCJTdHJpbmcgdW5leHBlY3RlZFwiLCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfRU5EICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dmFsLnN0cmluZyArPSBzdHI7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fWVsc2Vcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHRocm93RXJyb3IoIFwiU3RyaW5nIHVuZXhwZWN0ZWRcIiwgY0ludCApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfSU5fQVJSQVkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0FGVEVSX0ZJRUxEICl7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoICF2YWwuY2xhc3NOYW1lICl7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL1x0Z2V0UHJvdG8oKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dmFsLmNsYXNzTmFtZSA9IHZhbC5zdHJpbmc7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nID0gJyc7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHZhbC5zdHJpbmcgKz0gc3RyO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0VORCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR2YWwuc3RyaW5nICs9IHN0cjtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0XHRcdC8vcmVjb3ZlcklkZW50KGNJbnQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGJyZWFrOyAvLyBkZWZhdWx0XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgOTY6Ly8nYCc6XG5cdFx0XHRcdFx0XHRjYXNlIDM0Oi8vJ1wiJzpcblx0XHRcdFx0XHRcdGNhc2UgMzk6Ly8nXFwnJzpcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0aWYoIHZhbC5zdHJpbmcgKSB2YWwuY2xhc3NOYW1lID0gdmFsLnN0cmluZzsgdmFsLnN0cmluZyA9ICcnO1xuXHRcdFx0XHRcdFx0XHRsZXQgc3RyaW5nX3N0YXR1cyA9IGdhdGhlclN0cmluZyggY0ludCApO1xuXHRcdFx0XHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICYmIGNvbnNvbGUubG9nKCBcInN0cmluZyBnYXRoZXIgZm9yIG9iamVjdCBmaWVsZCB2YWx1ZSA6XCIsIHZhbC5zdHJpbmcsIHN0cmluZ19zdGF0dXMsIGNvbXBsZXRlZCwgaW5wdXQubiwgYnVmLmxlbmd0aCApO1xuXHRcdFx0XHRcdFx0XHRpZiggc3RyaW5nX3N0YXR1cyApIHtcblx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX1NUUklORztcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfRU5EO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGdhdGhlcmluZ1N0cmluZ0ZpcnN0Q2hhciA9IGNJbnQ7XG5cdFx0XHRcdFx0XHRcdFx0Z2F0aGVyaW5nU3RyaW5nID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGNhc2UgMTA6Ly8nXFxuJzpcblx0XHRcdFx0XHRcdFx0cG9zLmxpbmUrKztcblx0XHRcdFx0XHRcdFx0cG9zLmNvbCA9IDE7XG5cdFx0XHRcdFx0XHRcdC8vZmFsbHMgdGhyb3VnaFxuXHRcdFx0XHRcdFx0Y2FzZSAzMjovLycgJzpcblx0XHRcdFx0XHRcdGNhc2UgOTovLydcXHQnOlxuXHRcdFx0XHRcdFx0Y2FzZSAxMzovLydcXHInOlxuXHRcdFx0XHRcdFx0Y2FzZSAweDIwMjg6IC8vIExTIChMaW5lIHNlcGFyYXRvcilcblx0XHRcdFx0XHRcdGNhc2UgMHgyMDI5OiAvLyBQUyAocGFyYWdyYXBoIHNlcGFyYXRlKVxuXHRcdFx0XHRcdFx0Y2FzZSAweEZFRkY6Ly8nXFx1RkVGRic6XG5cdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1dISVRFU1BBQ0UgJiYgY29uc29sZS5sb2coIFwiV2hpdGVzcGFjZS4uLlwiLCB3b3JkLCBwYXJzZV9jb250ZXh0ICk7XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0VORCApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX1VOS05PV04gKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfT0JKRUNUX0ZJRUxEX1ZBTFVFICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX0FGVEVSX0ZJRUxEX1ZBTFVFO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfT0JKRUNUX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0d29yZCA9IFdPUkRfUE9TX0FGVEVSX0ZJRUxEO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmKCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfSU5fQVJSQVkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfQUZURVJfRklFTEQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgfHwgKCB3b3JkID09IFdPUkRfUE9TX0FGVEVSX0ZJRUxEICkpXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfRklFTEQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYoIHZhbC5zdHJpbmcubGVuZ3RoIClcblx0XHRcdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19BRlRFUl9GSUVMRDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggd29yZCA8IFdPUkRfUE9TX0VORCApIFxuXHRcdFx0XHRcdFx0XHRcdFx0cmVjb3ZlcklkZW50KCBjSW50ICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdFx0XHRcdFx0Ly8gIGNhdGNoIGNoYXJhY3RlcnMgZm9yIHRydWUvZmFsc2UvbnVsbC91bmRlZmluZWQgd2hpY2ggYXJlIHZhbHVlcyBvdXRzaWRlIG9mIHF1b3Rlc1xuXHRcdFx0XHRcdFx0Y2FzZSAxMTY6Ly8ndCc6XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX1JFU0VUICkgd29yZCA9IFdPUkRfUE9TX1RSVUVfMTtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19JTkZJTklUWV82ICkgd29yZCA9IFdPUkRfUE9TX0lORklOSVRZXzc7XG5cdFx0XHRcdFx0XHRcdGVsc2UgeyByZWNvdmVySWRlbnQoY0ludCk7IH0vLyBmYXVsdFxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgMTE0Oi8vJ3InOlxuXHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19UUlVFXzEgKSB3b3JkID0gV09SRF9QT1NfVFJVRV8yO1xuXHRcdFx0XHRcdFx0XHRlbHNlIHsgcmVjb3ZlcklkZW50KGNJbnQpOyB9Ly8gZmF1bHRcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDExNzovLyd1Jzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfVFJVRV8yICkgd29yZCA9IFdPUkRfUE9TX1RSVUVfMztcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19OVUxMXzEgKSB3b3JkID0gV09SRF9QT1NfTlVMTF8yO1xuXHRcdFx0XHRcdFx0XHRlbHNlIGlmKCB3b3JkID09IFdPUkRfUE9TX1JFU0VUICkgd29yZCA9IFdPUkRfUE9TX1VOREVGSU5FRF8xO1xuXHRcdFx0XHRcdFx0XHRlbHNlIHsgcmVjb3ZlcklkZW50KGNJbnQpOyB9Ly8gZmF1bHRcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDEwMTovLydlJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfVFJVRV8zICkge1xuXHRcdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfVFJVRTtcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfRU5EO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfRkFMU0VfNCApIHtcblx0XHRcdFx0XHRcdFx0XHR2YWwudmFsdWVfdHlwZSA9IFZBTFVFX0ZBTFNFO1xuXHRcdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19FTkQ7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19VTkRFRklORURfMyApIHdvcmQgPSBXT1JEX1BPU19VTkRFRklORURfNDtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19VTkRFRklORURfNyApIHdvcmQgPSBXT1JEX1BPU19VTkRFRklORURfODtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMTA6Ly8nbic6XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX1JFU0VUICkgd29yZCA9IFdPUkRfUE9TX05VTExfMTtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19VTkRFRklORURfMSApIHdvcmQgPSBXT1JEX1BPU19VTkRFRklORURfMjtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19VTkRFRklORURfNiApIHdvcmQgPSBXT1JEX1BPU19VTkRFRklORURfNztcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19JTkZJTklUWV8xICkgd29yZCA9IFdPUkRfUE9TX0lORklOSVRZXzI7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfSU5GSU5JVFlfNCApIHdvcmQgPSBXT1JEX1BPU19JTkZJTklUWV81O1xuXHRcdFx0XHRcdFx0XHRlbHNlIHsgcmVjb3ZlcklkZW50KGNJbnQpOyB9Ly8gZmF1bHRcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDEwMDovLydkJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfVU5ERUZJTkVEXzIgKSB3b3JkID0gV09SRF9QT1NfVU5ERUZJTkVEXzM7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfVU5ERUZJTkVEXzggKSB7IHZhbC52YWx1ZV90eXBlPVZBTFVFX1VOREVGSU5FRDsgd29yZCA9IFdPUkRfUE9TX0VORDsgfVxuXHRcdFx0XHRcdFx0XHRlbHNlIHsgcmVjb3ZlcklkZW50KGNJbnQpOyB9Ly8gZmF1bHRcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDEwNTovLydpJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfVU5ERUZJTkVEXzUgKSB3b3JkID0gV09SRF9QT1NfVU5ERUZJTkVEXzY7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfSU5GSU5JVFlfMyApIHdvcmQgPSBXT1JEX1BPU19JTkZJTklUWV80O1xuXHRcdFx0XHRcdFx0XHRlbHNlIGlmKCB3b3JkID09IFdPUkRfUE9TX0lORklOSVRZXzUgKSB3b3JkID0gV09SRF9QT1NfSU5GSU5JVFlfNjtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMDg6Ly8nbCc6XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX05VTExfMiApIHdvcmQgPSBXT1JEX1BPU19OVUxMXzM7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfTlVMTF8zICkge1xuXHRcdFx0XHRcdFx0XHRcdHZhbC52YWx1ZV90eXBlID0gVkFMVUVfTlVMTDtcblx0XHRcdFx0XHRcdFx0XHR3b3JkID0gV09SRF9QT1NfRU5EO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfRkFMU0VfMiApIHdvcmQgPSBXT1JEX1BPU19GQUxTRV8zO1xuXHRcdFx0XHRcdFx0XHRlbHNlIHsgcmVjb3ZlcklkZW50KGNJbnQpOyB9Ly8gZmF1bHRcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlIDEwMjovLydmJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgKSB3b3JkID0gV09SRF9QT1NfRkFMU0VfMTtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19VTkRFRklORURfNCApIHdvcmQgPSBXT1JEX1BPU19VTkRFRklORURfNTtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19JTkZJTklUWV8yICkgd29yZCA9IFdPUkRfUE9TX0lORklOSVRZXzM7XG5cdFx0XHRcdFx0XHRcdGVsc2UgeyByZWNvdmVySWRlbnQoY0ludCk7IH0vLyBmYXVsdFxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgOTc6Ly8nYSc6XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0ZBTFNFXzEgKSB3b3JkID0gV09SRF9QT1NfRkFMU0VfMjtcblx0XHRcdFx0XHRcdFx0ZWxzZSBpZiggd29yZCA9PSBXT1JEX1BPU19OQU5fMSApIHdvcmQgPSBXT1JEX1BPU19OQU5fMjtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAxMTU6Ly8ncyc6XG5cdFx0XHRcdFx0XHRcdGlmKCB3b3JkID09IFdPUkRfUE9TX0ZBTFNFXzMgKSB3b3JkID0gV09SRF9QT1NfRkFMU0VfNDtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSA3MzovLydJJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgKSB3b3JkID0gV09SRF9QT1NfSU5GSU5JVFlfMTtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSA3ODovLydOJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgKSB3b3JkID0gV09SRF9QT1NfTkFOXzE7XG5cdFx0XHRcdFx0XHRcdGVsc2UgaWYoIHdvcmQgPT0gV09SRF9QT1NfTkFOXzIgKSB7IHZhbC52YWx1ZV90eXBlID0gbmVnYXRpdmUgPyBWQUxVRV9ORUdfTkFOIDogVkFMVUVfTkFOOyBuZWdhdGl2ZSA9IGZhbHNlOyB3b3JkID0gV09SRF9QT1NfRU5EOyB9XG5cdFx0XHRcdFx0XHRcdGVsc2UgeyByZWNvdmVySWRlbnQoY0ludCk7IH0vLyBmYXVsdFxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgMTIxOi8vJ3knOlxuXHRcdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19JTkZJTklUWV83ICkgeyB2YWwudmFsdWVfdHlwZSA9IG5lZ2F0aXZlID8gVkFMVUVfTkVHX0lORklOSVRZIDogVkFMVUVfSU5GSU5JVFk7IG5lZ2F0aXZlID0gZmFsc2U7IHdvcmQgPSBXT1JEX1BPU19FTkQ7IH1cblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSA0NTovLyctJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgPT0gV09SRF9QT1NfUkVTRVQgKSBuZWdhdGl2ZSA9ICFuZWdhdGl2ZTtcblx0XHRcdFx0XHRcdFx0ZWxzZSB7IHJlY292ZXJJZGVudChjSW50KTsgfS8vIGZhdWx0XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSA0MzovLycrJzpcblx0XHRcdFx0XHRcdFx0aWYoIHdvcmQgIT09IFdPUkRfUE9TX1JFU0VUICkgeyByZWNvdmVySWRlbnQoY0ludCk7IH1cblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhazsgLy8gZGVmYXVsdCBvZiBoaWdoIGxldmVsIHN3aXRjaFxuXHRcdFx0XHRcdC8vXG5cdFx0XHRcdFx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdFx0XHRpZiggd29yZCA9PSBXT1JEX1BPU19FTkQgKSB7XG5cdFx0XHRcdFx0XHRcdHdvcmQgPSBXT1JEX1BPU19SRVNFVDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmKCBuID09IGJ1Zi5sZW5ndGggKSB7XG5cdFx0XHRcdFx0ZHJvcEJ1ZmZlciggaW5wdXQgKTtcblx0XHRcdFx0XHRpZiggZ2F0aGVyaW5nU3RyaW5nIHx8IGdhdGhlcmluZ051bWJlciB8fCBwYXJzZV9jb250ZXh0ID09IENPTlRFWFRfT0JKRUNUX0ZJRUxEICkge1xuXHRcdFx0XHRcdFx0cmV0dmFsID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiggcGFyc2VfY29udGV4dCA9PSBDT05URVhUX1VOS05PV04gJiYgKCB2YWwudmFsdWVfdHlwZSAhPSBWQUxVRV9VTlNFVCB8fCByZXN1bHQgKSApIHtcblx0XHRcdFx0XHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0cmV0dmFsID0gMTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0Ly8gcHV0IHRoZXNlIGJhY2sgaW50byB0aGUgc3RhY2suXG5cdFx0XHRcdFx0aW5wdXQubiA9IG47XG5cdFx0XHRcdFx0aW5RdWV1ZS51bnNoaWZ0KCBpbnB1dCApO1xuXHRcdFx0XHRcdHJldHZhbCA9IDI7ICAvLyBpZiByZXR1cm5pbmcgYnVmZmVycywgdGhlbiBvYnZpb3VzbHkgdGhlcmUncyBtb3JlIGluIHRoaXMgb25lLlxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdFx0cm9vdE9iamVjdCA9IG51bGw7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYoICFzdGF0dXMgKSByZXR1cm4gLTE7XG5cdFx0XHRpZiggY29tcGxldGVkICYmIHZhbC52YWx1ZV90eXBlICE9IFZBTFVFX1VOU0VUICkge1xuXHRcdFx0XHR3b3JkID0gV09SRF9QT1NfUkVTRVQ7XG5cdFx0XHRcdHJlc3VsdCA9IGNvbnZlcnRWYWx1ZSgpO1xuXHRcdFx0XHQvL19ERUJVR19QQVJTSU5HICYmIGNvbnNvbGUubG9nKCBcIlJlc3VsdCgzKTpcIiwgcmVzdWx0ICk7XG5cdFx0XHRcdG5lZ2F0aXZlID0gZmFsc2U7XG5cdFx0XHRcdHZhbC5zdHJpbmcgPSAnJztcblx0XHRcdFx0dmFsLnZhbHVlX3R5cGUgPSBWQUxVRV9VTlNFVDtcblx0XHRcdH1cblx0XHRcdGNvbXBsZXRlZCA9IGZhbHNlO1xuXHRcdFx0cmV0dXJuIHJldHZhbDtcblx0XHR9XG5cdH1cbn1cblxuXG5cbmNvbnN0IF9wYXJzZXIgPSBbT2JqZWN0LmZyZWV6ZSggSlNPWC5iZWdpbigpICldO1xubGV0IF9wYXJzZV9sZXZlbCA9IDA7XG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgXG4gKiBAcGFyYW0geyh0aGlzOiB1bmtub3duLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pID0+IGFueX0gW3Jldml2ZXJdIFxuICogQHJldHVybnMge3Vua25vd259XG4gKi9cbkpTT1gucGFyc2UgPSBmdW5jdGlvbiggbXNnLCByZXZpdmVyICkge1xuXHRsZXQgcGFyc2VfbGV2ZWwgPSBfcGFyc2VfbGV2ZWwrKztcblx0bGV0IHBhcnNlcjtcblx0aWYoIF9wYXJzZXIubGVuZ3RoIDw9IHBhcnNlX2xldmVsIClcblx0XHRfcGFyc2VyLnB1c2goIE9iamVjdC5mcmVlemUoIEpTT1guYmVnaW4oKSApICk7XG5cdHBhcnNlciA9IF9wYXJzZXJbcGFyc2VfbGV2ZWxdO1xuXHRpZiAodHlwZW9mIG1zZyAhPT0gXCJzdHJpbmdcIikgbXNnID0gU3RyaW5nKG1zZyk7XG5cdHBhcnNlci5yZXNldCgpO1xuXHRjb25zdCB3cml0ZVJlc3VsdCA9IHBhcnNlci5fd3JpdGUoIG1zZywgdHJ1ZSApO1xuXHRpZiggd3JpdGVSZXN1bHQgPiAwICkge1xuXHRcdGlmKCB3cml0ZVJlc3VsdCA+IDEgKXtcblx0XHRcdC8vIHByb2JhYmx5IGEgY2FycmlhZ2UgcmV0dXJuLlxuXHRcdFx0Ly9jb25zb2xlLmxvZyggXCJFeHRyYSBkYXRhIGF0IGVuZCBvZiBtZXNzYWdlXCIpO1xuXHRcdH1cblx0XHRsZXQgcmVzdWx0ID0gcGFyc2VyLnZhbHVlKCk7XG5cdFx0aWYoICggXCJ1bmRlZmluZWRcIiA9PT0gdHlwZW9mIHJlc3VsdCApICYmIHdyaXRlUmVzdWx0ID4gMSApe1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIlBlbmRpbmcgdmFsdWUgY291bGQgbm90IGNvbXBsZXRlXCIpO1xuXHRcdH1cblxuXHRcdHJlc3VsdCA9IHR5cGVvZiByZXZpdmVyID09PSAnZnVuY3Rpb24nID8gKGZ1bmN0aW9uIHdhbGsoaG9sZGVyLCBrZXkpIHtcblx0XHRcdGxldCBrLCB2LCB2YWx1ZSA9IGhvbGRlcltrZXldO1xuXHRcdFx0aWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdFx0Zm9yIChrIGluIHZhbHVlKSB7XG5cdFx0XHRcdFx0aWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgaykpIHtcblx0XHRcdFx0XHRcdHYgPSB3YWxrKHZhbHVlLCBrKTtcblx0XHRcdFx0XHRcdGlmICh2ICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0dmFsdWVba10gPSB2O1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIHZhbHVlW2tdO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJldml2ZXIuY2FsbChob2xkZXIsIGtleSwgdmFsdWUpO1xuXHRcdH0oeycnOiByZXN1bHR9LCAnJykpIDogcmVzdWx0O1xuXHRcdF9wYXJzZV9sZXZlbC0tO1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblx0cGFyc2VyLmZpbmFsRXJyb3IoKTtcblx0cmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuXG5mdW5jdGlvbiB0aGlzX3ZhbHVlKCkgey8qLy9fREVCVUdfU1RSSU5HSUZZJiZjb25zb2xlLmxvZyggXCJ0aGlzOlwiLCB0aGlzLCBcInZhbHVlb2Y6XCIsIHRoaXMmJnRoaXMudmFsdWVPZigpICk7Ki8gXG5cdHJldHVybiB0aGlzJiZ0aGlzLnZhbHVlT2YoKTtcbn1cblxuLyoqXG4gKiBEZWZpbmUgYSBjbGFzcyB0byBiZSB1c2VkIGZvciBzZXJpYWxpemF0aW9uOyB0aGUgY2xhc3MgYWxsb3dzIGVtaXR0aW5nIHRoZSBjbGFzcyBmaWVsZHMgYWhlYWQgb2YgdGltZSwgYW5kIGp1c3QgcHJvdmlkZSB2YWx1ZXMgbGF0ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmogXG4gKi9cbkpTT1guZGVmaW5lQ2xhc3MgPSBmdW5jdGlvbiggbmFtZSwgb2JqICkge1xuXHRsZXQgY2xzO1xuXHRsZXQgZGVub3JtS2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG5cdGZvciggbGV0IGkgPSAxOyBpIDwgZGVub3JtS2V5cy5sZW5ndGg7IGkrKyApIHtcblx0XHRsZXQgYSwgYjtcblx0XHRpZiggKCBhID0gZGVub3JtS2V5c1tpLTFdICkgPiAoIGIgPSBkZW5vcm1LZXlzW2ldICkgKSB7XG5cdFx0XHRkZW5vcm1LZXlzW2ktMV0gPSBiO1xuXHRcdFx0ZGVub3JtS2V5c1tpXSA9IGE7XG5cdFx0XHRpZiggaSApIGktPTI7IC8vIGdvIGJhY2sgMiwgdGhpcyBtaWdodCBuZWVkIHRvIGdvIGZ1cnRoZXIgcGFjay5cblx0XHRcdGVsc2UgaS0tOyAvLyBvbmx5IDEgdG8gY2hlY2suXG5cdFx0fVxuXHR9XG5cdC8vY29uc29sZS5sb2coIFwibm9ybWFsaXplZDpcIiwgZGVub3JtS2V5cyApO1xuXHRjb21tb25DbGFzc2VzLnB1c2goIGNscyA9IHsgbmFtZSA6IG5hbWVcblx0XHQgICAsIHRhZzpkZW5vcm1LZXlzLnRvU3RyaW5nKClcblx0XHQgICAsIHByb3RvIDogT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iailcblx0XHQgICAsIGZpZWxkcyA6IE9iamVjdC5rZXlzKG9iaikgfSApO1xuXHRmb3IobGV0IG4gPSAxOyBuIDwgY2xzLmZpZWxkcy5sZW5ndGg7IG4rKykge1xuXHRcdGlmKCBjbHMuZmllbGRzW25dIDwgY2xzLmZpZWxkc1tuLTFdICkge1xuXHRcdFx0bGV0IHRtcCA9IGNscy5maWVsZHNbbi0xXTtcblx0XHRcdGNscy5maWVsZHNbbi0xXSA9IGNscy5maWVsZHNbbl07XG5cdFx0XHRjbHMuZmllbGRzW25dID0gdG1wO1xuXHRcdFx0aWYoIG4gPiAxIClcblx0XHRcdFx0bi09Mjtcblx0XHR9XG5cdH1cblx0aWYoIGNscy5wcm90byA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKCB7fSApICkgY2xzLnByb3RvID0gbnVsbDtcbn1cblxuLyoqXG4gKiBkZWZpbmUgYSBjbGFzcyB0byBiZSB1c2VkIGZvciBzZXJpYWxpemF0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZWRcbiAqIEBwYXJhbSB7Y2xhc3N9IHB0eXBlXG4gKiBAcGFyYW0geyhhbnkpPT5hbnl9IGZcbiAqL1xuSlNPWC50b0pTT1ggPVxuSlNPWC5yZWdpc3RlclRvSlNPWCA9IGZ1bmN0aW9uKCBuYW1lLCBwdHlwZSwgZiApIHtcblx0Ly9jb25zb2xlLmxvZyggXCJTRVQgT0JKRUNUIFRZUEU6XCIsIHB0eXBlLCBwdHlwZS5wcm90b3R5cGUsIE9iamVjdC5wcm90b3R5cGUsIHB0eXBlLmNvbnN0cnVjdG9yICk7XG5cdGlmKCAhcHR5cGUucHJvdG90eXBlIHx8IHB0eXBlLnByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSApIHtcblx0XHRpZiggdG9Qcm90b1R5cGVzLmdldChwdHlwZS5wcm90b3R5cGUpICkgdGhyb3cgbmV3IEVycm9yKCBcIkV4aXN0aW5nIHRvSlNPWCBoYXMgYmVlbiByZWdpc3RlcmVkIGZvciBwcm90b3R5cGVcIiApO1xuXHRcdC8vX0RFQlVHX1BBUlNJTkcgJiYgY29uc29sZS5sb2coIFwiUFVTSCBQUk9UT1RZUEVcIiApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIHB0eXBlLnByb3RvdHlwZSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOm5hbWV8fGYuY29uc3RydWN0b3IubmFtZSwgY2I6ZiB9ICk7XG5cdH0gZWxzZSB7XG5cdFx0bGV0IGtleSA9IE9iamVjdC5rZXlzKCBwdHlwZSApLnRvU3RyaW5nKCk7XG5cdFx0aWYoIHRvT2JqZWN0VHlwZXMuZ2V0KGtleSkgKSB0aHJvdyBuZXcgRXJyb3IoIFwiRXhpc3RpbmcgdG9KU09YIGhhcyBiZWVuIHJlZ2lzdGVyZWQgZm9yIG9iamVjdCB0eXBlXCIgKTtcblx0XHQvL2NvbnNvbGUubG9nKCBcIlRFU1QgU0VUIE9CSkVDVCBUWVBFOlwiLCBrZXkgKTtcblx0XHR0b09iamVjdFR5cGVzLnNldCgga2V5LCB7IGV4dGVybmFsOnRydWUsIG5hbWU6bmFtZSwgY2I6ZiB9ICk7XG5cdH1cbn1cbi8qKlxuICogZGVmaW5lIGEgY2xhc3MgdG8gYmUgdXNlZCBmb3IgZGVzZXJpYWxpemF0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvdG90eXBlTmFtZSBcbiAqIEBwYXJhbSB7Y2xhc3N9IG8gXG4gKiBAcGFyYW0geyhhbnkpPT5hbnl9IGYgXG4gKi9cbkpTT1guZnJvbUpTT1ggPSBmdW5jdGlvbiggcHJvdG90eXBlTmFtZSwgbywgZiApIHtcblx0ZnVuY3Rpb24gcHJpdmF0ZVByb3RvKCkgeyB9XG5cdFx0aWYoICFvICkgbyA9IHByaXZhdGVQcm90by5wcm90b3R5cGU7XG5cdFx0aWYoIGZyb21Qcm90b1R5cGVzLmdldChwcm90b3R5cGVOYW1lKSApIHRocm93IG5ldyBFcnJvciggXCJFeGlzdGluZyBmcm9tSlNPWCBoYXMgYmVlbiByZWdpc3RlcmVkIGZvciBwcm90b3R5cGVcIiApO1xuXHRcdGlmKCBvICYmICEoXCJjb25zdHJ1Y3RvclwiIGluIG8gKSl7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiUGxlYXNlIHBhc3MgYSBwcm90b3R5cGUgbGlrZSB0aGluZy4uLlwiKTtcblx0fVxuXHRmcm9tUHJvdG9UeXBlcy5zZXQoIHByb3RvdHlwZU5hbWUsIHtwcm90b0Nvbjogby5wcm90b3R5cGUuY29uc3RydWN0b3IsIGNiOmYgfSApO1xuXG59XG5KU09YLnJlZ2lzdGVyRnJvbUpTT1ggPSBmdW5jdGlvbiggcHJvdG90eXBlTmFtZSwgbyAvKiwgZiovICkge1xuXHR0aHJvdyBuZXcgRXJyb3IoIFwiZGVwcmVjYXRlZDsgcGxlYXNlIGFkanVzdCBjb2RlIHRvIHVzZSBmcm9tSlNPWDpcIiArIHByb3RvdHlwZU5hbWUgKyBvLnRvU3RyaW5nKCkgKTtcbn1cbkpTT1guYWRkVHlwZSA9IGZ1bmN0aW9uKCBwcm90b3R5cGVOYW1lLCBwcm90b3R5cGUsIHRvLCBmcm9tICkge1xuXHRKU09YLnRvSlNPWCggcHJvdG90eXBlTmFtZSwgcHJvdG90eXBlLCB0byApO1xuXHRKU09YLmZyb21KU09YKCBwcm90b3R5cGVOYW1lLCBwcm90b3R5cGUsIGZyb20gKTtcbn1cblxuSlNPWC5yZWdpc3RlclRvRnJvbSA9IGZ1bmN0aW9uKCBwcm90b3R5cGVOYW1lLCBwcm90b3R5cGUvKiwgdG8sIGZyb20qLyApIHtcblx0dGhyb3cgbmV3IEVycm9yKCBcInJlZ2lzdGVyVG9Gcm9tIGRlcHJlY2F0ZWQ7IHBsZWFzZSB1c2UgYWRkVHlwZTpcIiArIHByb3RvdHlwZU5hbWUgKyBwcm90b3R5cGUudG9TdHJpbmcoKSApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHN0cmluZ2lmaWVyIHRvIGNvbnZlcnQgb2JqZWN0cyB0byBKU09YIHRleHQuICBBbGxvd3MgZGVmaW5pbmcgY3VzdG9tIHNlcmlhbGl6YXRpb24gZm9yIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7U3RyaW5naWZpZXJ9XG4gKi9cbkpTT1guc3RyaW5naWZpZXIgPSBmdW5jdGlvbigpIHtcblx0bGV0IGNsYXNzZXMgPSBbXTtcblx0bGV0IHVzZVF1b3RlID0gJ1wiJztcblxuXHRsZXQgZmllbGRNYXAgPSBuZXcgV2Vha01hcCgpO1xuXHRjb25zdCBwYXRoID0gW107XG5cdGxldCBlbmNvZGluZyA9IFtdO1xuXHRjb25zdCBsb2NhbFRvUHJvdG9UeXBlcyA9IG5ldyBXZWFrTWFwKCk7XG5cdGNvbnN0IGxvY2FsVG9PYmplY3RUeXBlcyA9IG5ldyBNYXAoKTtcblx0bGV0IG9iamVjdFRvSlNPWCA9IG51bGw7XG5cdGNvbnN0IHN0cmluZ2lmeWluZyA9IFtdOyAvLyB0aGluZ3MgdGhhdCBoYXZlIGJlZW4gc3RyaW5naWZpZWQgdGhyb3VnaCBleHRlcm5hbCB0b0pTT1g7IGFsbG93cyBzZWNvbmQgcGFzcyB0byBza2lwIHRoaXMgdG9KU09YIHBhc3MgYW5kIGVuY29kZSAnbm9ybWFsbHknXG5cdGxldCBpZ25vcmVOb25FbnVtZXJhYmxlID0gZmFsc2U7XG5cdGZ1bmN0aW9uIGdldElkZW50aWZpZXIocykge1xuXHRcblx0XHRpZiggKCBcInN0cmluZ1wiID09PSB0eXBlb2YgcyApICYmIHMgPT09ICcnICkgcmV0dXJuICdcIlwiJztcblx0XHRpZiggKCBcIm51bWJlclwiID09PSB0eXBlb2YgcyApICYmICFpc05hTiggcyApICkge1xuXHRcdFx0cmV0dXJuIFtcIidcIixzLnRvU3RyaW5nKCksXCInXCJdLmpvaW4oJycpO1xuXHRcdH1cblx0XHQvLyBzaG91bGQgY2hlY2sgYWxzbyBmb3IgaWYgYW55IG5vbiBpZGVudCBpbiBzdHJpbmcuLi5cblx0XHRpZiggcy5pbmNsdWRlcyggXCJcXHV7RkVGRn1cIiApICkgcmV0dXJuICh1c2VRdW90ZSArIEpTT1guZXNjYXBlKHMpICt1c2VRdW90ZSk7XG5cdFx0cmV0dXJuICggKCBzIGluIGtleXdvcmRzIC8qIFsgXCJ0cnVlXCIsXCJmYWxzZVwiLFwibnVsbFwiLFwiTmFOXCIsXCJJbmZpbml0eVwiLFwidW5kZWZpbmVkXCJdLmZpbmQoIGtleXdvcmQ9PmtleXdvcmQ9PT1zICkqL1xuXHRcdFx0fHwgL1swLTlcXC1dLy50ZXN0KHNbMF0pXG5cdFx0XHR8fCAvW1xcblxcclxcdCAjXFxbXFxde30oKTw+XFx+ISsqLy46LFxcLVwiJ2BdLy50ZXN0KCBzICkgKT8odXNlUXVvdGUgKyBKU09YLmVzY2FwZShzKSArdXNlUXVvdGUpOnMgKVxuXHR9XG5cblxuXHQvKiBpbml0IHByb3RvdHlwZXMgKi9cblx0aWYoICF0b1Byb3RvVHlwZXMuZ2V0KCBPYmplY3QucHJvdG90eXBlICkgKVxuXHR7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggT2JqZWN0LnByb3RvdHlwZSwgeyBleHRlcm5hbDpmYWxzZSwgbmFtZTpPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUsIGNiOm51bGwgfSApO1xuXHQgICBcblx0XHQvLyBmdW5jdGlvbiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTc0MTU2NzcvNDYxOTI2N1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIERhdGUucHJvdG90eXBlLCB7IGV4dGVybmFsOmZhbHNlLFxuXHRcdFx0bmFtZSA6IFwiRGF0ZVwiLFxuXHRcdFx0Y2IgOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0aWYoIHRoaXMuZ2V0VGltZSgpPT09IC02MjE2NzIxOTIwMDAwMCkgXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cmV0dXJuIFwiMDAwMC0wMS0wMVQwMDowMDowMC4wMDBaXCI7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGxldCB0em8gPSAtdGhpcy5nZXRUaW1lem9uZU9mZnNldCgpLFxuXHRcdFx0XHRcdGRpZiA9IHR6byA+PSAwID8gJysnIDogJy0nLFxuXHRcdFx0XHRcdHBhZCA9IGZ1bmN0aW9uKG51bSkge1xuXHRcdFx0XHRcdFx0bGV0IG5vcm0gPSBNYXRoLmZsb29yKE1hdGguYWJzKG51bSkpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIChub3JtIDwgMTAgPyAnMCcgOiAnJykgKyBub3JtO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0cGFkMyA9IGZ1bmN0aW9uKG51bSkge1xuXHRcdFx0XHRcdFx0bGV0IG5vcm0gPSBNYXRoLmZsb29yKE1hdGguYWJzKG51bSkpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIChub3JtIDwgMTAwID8gJzAnIDogJycpICsgKG5vcm0gPCAxMCA/ICcwJyA6ICcnKSArIG5vcm07XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0cmV0dXJuIFt0aGlzLmdldEZ1bGxZZWFyKCkgLFxuXHRcdFx0XHRcdCctJyAsIHBhZCh0aGlzLmdldE1vbnRoKCkgKyAxKSAsXG5cdFx0XHRcdFx0Jy0nICwgcGFkKHRoaXMuZ2V0RGF0ZSgpKSAsXG5cdFx0XHRcdFx0J1QnICwgcGFkKHRoaXMuZ2V0SG91cnMoKSkgLFxuXHRcdFx0XHRcdCc6JyAsIHBhZCh0aGlzLmdldE1pbnV0ZXMoKSkgLFxuXHRcdFx0XHRcdCc6JyAsIHBhZCh0aGlzLmdldFNlY29uZHMoKSkgLFxuXHRcdFx0XHRcdCcuJyArIHBhZDModGhpcy5nZXRNaWxsaXNlY29uZHMoKSkgK1xuXHRcdFx0XHRcdGRpZiAsIHBhZCh0em8gLyA2MCkgLFxuXHRcdFx0XHRcdCc6JyAsIHBhZCh0em8gJSA2MCldLmpvaW4oXCJcIik7XG5cdFx0XHR9IFxuXHRcdH0gKTtcblx0XHR0b1Byb3RvVHlwZXMuc2V0KCBEYXRlTlMucHJvdG90eXBlLCB7IGV4dGVybmFsOmZhbHNlLFxuXHRcdFx0bmFtZSA6IFwiRGF0ZU5TXCIsXG5cdFx0XHRjYiA6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0bGV0IHR6byA9IC10aGlzLmdldFRpbWV6b25lT2Zmc2V0KCksXG5cdFx0XHRcdFx0ZGlmID0gdHpvID49IDAgPyAnKycgOiAnLScsXG5cdFx0XHRcdFx0cGFkID0gZnVuY3Rpb24obnVtKSB7XG5cdFx0XHRcdFx0XHRsZXQgbm9ybSA9IE1hdGguZmxvb3IoTWF0aC5hYnMobnVtKSk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gKG5vcm0gPCAxMCA/ICcwJyA6ICcnKSArIG5vcm07XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRwYWQzID0gZnVuY3Rpb24obnVtKSB7XG5cdFx0XHRcdFx0XHRsZXQgbm9ybSA9IE1hdGguZmxvb3IoTWF0aC5hYnMobnVtKSk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gKG5vcm0gPCAxMDAgPyAnMCcgOiAnJykgKyAobm9ybSA8IDEwID8gJzAnIDogJycpICsgbm9ybTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHBhZDYgPSBmdW5jdGlvbihudW0pIHtcblx0XHRcdFx0XHRcdGxldCBub3JtID0gTWF0aC5mbG9vcihNYXRoLmFicyhudW0pKTtcblx0XHRcdFx0XHRcdHJldHVybiAobm9ybSA8IDEwMDAwMCA/ICcwJyA6ICcnKSArIChub3JtIDwgMTAwMDAgPyAnMCcgOiAnJykgKyAobm9ybSA8IDEwMDAgPyAnMCcgOiAnJykgKyAobm9ybSA8IDEwMCA/ICcwJyA6ICcnKSArIChub3JtIDwgMTAgPyAnMCcgOiAnJykgKyBub3JtO1xuXHRcdFx0XHRcdH07XG5cdFx0XHRcdHJldHVybiBbdGhpcy5nZXRGdWxsWWVhcigpICxcblx0XHRcdFx0XHQnLScgLCBwYWQodGhpcy5nZXRNb250aCgpICsgMSkgLFxuXHRcdFx0XHRcdCctJyAsIHBhZCh0aGlzLmdldERhdGUoKSkgLFxuXHRcdFx0XHRcdCdUJyAsIHBhZCh0aGlzLmdldEhvdXJzKCkpICxcblx0XHRcdFx0XHQnOicgLCBwYWQodGhpcy5nZXRNaW51dGVzKCkpICxcblx0XHRcdFx0XHQnOicgLCBwYWQodGhpcy5nZXRTZWNvbmRzKCkpICxcblx0XHRcdFx0XHQnLicgKyBwYWQzKHRoaXMuZ2V0TWlsbGlzZWNvbmRzKCkpICsgcGFkNih0aGlzLm5zKSArXG5cdFx0XHRcdFx0ZGlmICwgcGFkKHR6byAvIDYwKSAsXG5cdFx0XHRcdFx0JzonICwgcGFkKHR6byAlIDYwKV0uam9pbihcIlwiKTtcblx0XHRcdH0gXG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIEJvb2xlYW4ucHJvdG90eXBlLCB7IGV4dGVybmFsOmZhbHNlLCBuYW1lOlwiQm9vbGVhblwiLCBjYjp0aGlzX3ZhbHVlICB9ICk7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggTnVtYmVyLnByb3RvdHlwZSwgeyBleHRlcm5hbDpmYWxzZSwgbmFtZTpcIk51bWJlclwiXG5cdFx0ICAgICwgY2I6ZnVuY3Rpb24oKXsgXG5cdFx0XHRcdGlmKCBpc05hTih0aGlzKSApICByZXR1cm4gXCJOYU5cIjtcblx0XHRcdFx0cmV0dXJuIChpc0Zpbml0ZSh0aGlzKSlcblx0XHRcdFx0XHQ/IFN0cmluZyh0aGlzKVxuXHRcdFx0XHRcdDogKHRoaXM8MCk/XCItSW5maW5pdHlcIjpcIkluZmluaXR5XCI7XG5cdFx0ICAgIH1cblx0XHR9ICk7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggU3RyaW5nLnByb3RvdHlwZSwgeyBleHRlcm5hbDpmYWxzZVxuXHRcdCAgICAsIG5hbWUgOiBcIlN0cmluZ1wiXG5cdFx0ICAgICwgY2I6ZnVuY3Rpb24oKXsgcmV0dXJuICdcIicgKyBKU09YLmVzY2FwZSh0aGlzX3ZhbHVlLmFwcGx5KHRoaXMpKSArICdcIicgfSB9ICk7XG5cdFx0aWYoIHR5cGVvZiBCaWdJbnQgPT09IFwiZnVuY3Rpb25cIiApXG5cdFx0XHR0b1Byb3RvVHlwZXMuc2V0KCBCaWdJbnQucHJvdG90eXBlXG5cdFx0XHQgICAgICwgeyBleHRlcm5hbDpmYWxzZSwgbmFtZTpcIkJpZ0ludFwiLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMgKyAnbicgfSB9ICk7XG5cdCAgIFxuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIEFycmF5QnVmZmVyLnByb3RvdHlwZSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOlwiYWJcIlxuXHRcdCAgICAsIGNiOmZ1bmN0aW9uKCkgeyByZXR1cm4gXCJbXCIrZ2V0SWRlbnRpZmllcihiYXNlNjRBcnJheUJ1ZmZlcih0aGlzKSkrXCJdXCIgfVxuXHRcdH0gKTtcblx0ICAgXG5cdFx0dG9Qcm90b1R5cGVzLnNldCggVWludDhBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcInU4XCJcblx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIFVpbnQ4Q2xhbXBlZEFycmF5LnByb3RvdHlwZSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOlwidWM4XCJcblx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIEludDhBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcInM4XCJcblx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIFVpbnQxNkFycmF5LnByb3RvdHlwZSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOlwidTE2XCJcblx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIEludDE2QXJyYXkucHJvdG90eXBlLCB7IGV4dGVybmFsOnRydWUsIG5hbWU6XCJzMTZcIlxuXHRcdCAgICAsIGNiOmZ1bmN0aW9uKCkgeyByZXR1cm4gXCJbXCIrZ2V0SWRlbnRpZmllcihiYXNlNjRBcnJheUJ1ZmZlcih0aGlzLmJ1ZmZlcikpK1wiXVwiIH1cblx0XHR9ICk7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggVWludDMyQXJyYXkucHJvdG90eXBlLCB7IGV4dGVybmFsOnRydWUsIG5hbWU6XCJ1MzJcIlxuXHRcdCAgICAsIGNiOmZ1bmN0aW9uKCkgeyByZXR1cm4gXCJbXCIrZ2V0SWRlbnRpZmllcihiYXNlNjRBcnJheUJ1ZmZlcih0aGlzLmJ1ZmZlcikpK1wiXVwiIH1cblx0XHR9ICk7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggSW50MzJBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcInMzMlwiXG5cdFx0ICAgICwgY2I6ZnVuY3Rpb24oKSB7IHJldHVybiBcIltcIitnZXRJZGVudGlmaWVyKGJhc2U2NEFycmF5QnVmZmVyKHRoaXMuYnVmZmVyKSkrXCJdXCIgfVxuXHRcdH0gKTtcblx0XHQvKlxuXHRcdGlmKCB0eXBlb2YgVWludDY0QXJyYXkgIT0gXCJ1bmRlZmluZWRcIiApXG5cdFx0XHR0b1Byb3RvVHlwZXMuc2V0KCBVaW50NjRBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcInU2NFwiXG5cdFx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0XHR9ICk7XG5cdFx0aWYoIHR5cGVvZiBJbnQ2NEFycmF5ICE9IFwidW5kZWZpbmVkXCIgKVxuXHRcdFx0dG9Qcm90b1R5cGVzLnNldCggSW50NjRBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcInM2NFwiXG5cdFx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0XHR9ICk7XG5cdFx0Ki9cblx0XHR0b1Byb3RvVHlwZXMuc2V0KCBGbG9hdDMyQXJyYXkucHJvdG90eXBlLCB7IGV4dGVybmFsOnRydWUsIG5hbWU6XCJmMzJcIlxuXHRcdCAgICAsIGNiOmZ1bmN0aW9uKCkgeyByZXR1cm4gXCJbXCIrZ2V0SWRlbnRpZmllcihiYXNlNjRBcnJheUJ1ZmZlcih0aGlzLmJ1ZmZlcikpK1wiXVwiIH1cblx0XHR9ICk7XG5cdFx0dG9Qcm90b1R5cGVzLnNldCggRmxvYXQ2NEFycmF5LnByb3RvdHlwZSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOlwiZjY0XCJcblx0XHQgICAgLCBjYjpmdW5jdGlvbigpIHsgcmV0dXJuIFwiW1wiK2dldElkZW50aWZpZXIoYmFzZTY0QXJyYXlCdWZmZXIodGhpcy5idWZmZXIpKStcIl1cIiB9XG5cdFx0fSApO1xuXHRcdHRvUHJvdG9UeXBlcy5zZXQoIEZsb2F0NjRBcnJheS5wcm90b3R5cGUsIHsgZXh0ZXJuYWw6dHJ1ZSwgbmFtZTpcImY2NFwiXG5cdFx0ICAgICwgY2I6ZnVuY3Rpb24oKSB7IHJldHVybiBcIltcIitnZXRJZGVudGlmaWVyKGJhc2U2NEFycmF5QnVmZmVyKHRoaXMuYnVmZmVyKSkrXCJdXCIgfVxuXHRcdH0gKTtcblx0ICAgXG5cdFx0dG9Qcm90b1R5cGVzLnNldCggUmVnRXhwLnByb3RvdHlwZSwgbWFwVG9KU09YID0geyBleHRlcm5hbDp0cnVlLCBuYW1lOlwicmVnZXhcIlxuXHRcdCAgICAsIGNiOmZ1bmN0aW9uKG8sc3RyaW5naWZpZXIpe1xuXHRcdFx0XHRyZXR1cm4gXCInXCIrZXNjYXBlKHRoaXMuc291cmNlKStcIidcIjtcblx0XHRcdH1cblx0XHR9ICk7XG5cdFx0ZnJvbVByb3RvVHlwZXMuc2V0KCBcInJlZ2V4XCIsIHsgcHJvdG9Db246UmVnRXhwLCBjYjpmdW5jdGlvbiAoZmllbGQsdmFsKXtcblx0XHRcdHJldHVybiBuZXcgUmVnRXhwKCB0aGlzICk7XG5cdFx0fSB9ICk7XG5cblx0XHR0b1Byb3RvVHlwZXMuc2V0KCBNYXAucHJvdG90eXBlLCBtYXBUb0pTT1ggPSB7IGV4dGVybmFsOnRydWUsIG5hbWU6XCJtYXBcIlxuXHRcdCAgICAsIGNiOm51bGxcblx0XHR9ICk7XG5cdFx0ZnJvbVByb3RvVHlwZXMuc2V0KCBcIm1hcFwiLCB7IHByb3RvQ29uOk1hcCwgY2I6ZnVuY3Rpb24gKGZpZWxkLHZhbCl7XG5cdFx0XHRpZiggZmllbGQgKSB7XG5cdFx0XHRcdHRoaXMuc2V0KCBmaWVsZCwgdmFsICk7XG5cdFx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9IH0gKTtcblx0ICAgXG5cdFx0dG9Qcm90b1R5cGVzLnNldCggQXJyYXkucHJvdG90eXBlLCBhcnJheVRvSlNPWCA9IHsgZXh0ZXJuYWw6ZmFsc2UsIG5hbWU6QXJyYXkucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWVcblx0XHQgICAgLCBjYjogbnVsbFx0XHQgICAgXG5cdFx0fSApO1xuXG5cdH1cblxuXHRjb25zdCBzdHJpbmdpZmllciA9IHtcblx0XHRkZWZpbmVDbGFzcyhuYW1lLG9iaikgeyBcblx0XHRcdGxldCBjbHM7IFxuXHRcdFx0bGV0IGRlbm9ybUtleXMgPSBPYmplY3Qua2V5cyhvYmopO1xuXHRcdFx0Zm9yKCBsZXQgaSA9IDE7IGkgPCBkZW5vcm1LZXlzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHQvLyBub3JtYWxpemUgY2xhc3Mga2V5IG9yZGVyXG5cdFx0XHRcdGxldCBhLCBiO1xuXHRcdFx0XHRpZiggKCBhID0gZGVub3JtS2V5c1tpLTFdICkgPiAoIGIgPSBkZW5vcm1LZXlzW2ldICkgKSB7XG5cdFx0XHRcdFx0ZGVub3JtS2V5c1tpLTFdID0gYjtcblx0XHRcdFx0XHRkZW5vcm1LZXlzW2ldID0gYTtcblx0XHRcdFx0XHRpZiggaSApIGktPTI7IC8vIGdvIGJhY2sgMiwgdGhpcyBtaWdodCBuZWVkIHRvIGdvIGZ1cnRoZXIgcGFjay5cblx0XHRcdFx0XHRlbHNlIGktLTsgLy8gb25seSAxIHRvIGNoZWNrLlxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRjbGFzc2VzLnB1c2goIGNscyA9IHsgbmFtZSA6IG5hbWVcblx0XHRcdCAgICAgICAsIHRhZzpkZW5vcm1LZXlzLnRvU3RyaW5nKClcblx0XHRcdCAgICAgICAsIHByb3RvIDogT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iailcblx0XHRcdCAgICAgICAsIGZpZWxkcyA6IE9iamVjdC5rZXlzKG9iaikgfSApO1xuXG5cdFx0XHRmb3IobGV0IG4gPSAxOyBuIDwgY2xzLmZpZWxkcy5sZW5ndGg7IG4rKykge1xuXHRcdFx0XHRpZiggY2xzLmZpZWxkc1tuXSA8IGNscy5maWVsZHNbbi0xXSApIHtcblx0XHRcdFx0XHRsZXQgdG1wID0gY2xzLmZpZWxkc1tuLTFdO1xuXHRcdFx0XHRcdGNscy5maWVsZHNbbi0xXSA9IGNscy5maWVsZHNbbl07XG5cdFx0XHRcdFx0Y2xzLmZpZWxkc1tuXSA9IHRtcDtcblx0XHRcdFx0XHRpZiggbiA+IDEgKVxuXHRcdFx0XHRcdFx0bi09Mjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYoIGNscy5wcm90byA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKCB7fSApICkgY2xzLnByb3RvID0gbnVsbDtcblx0XHR9LFxuXHRcdHNldERlZmF1bHRPYmplY3RUb0pTT1goIGNiICkgeyBvYmplY3RUb0pTT1ggPSBjYiB9LFxuXHRcdGlzRW5jb2Rpbmcobykge1xuXHRcdFx0Ly9jb25zb2xlLmxvZyggXCJpcyBvYmplY3QgZW5jb2Rpbmc/XCIsIGVuY29kaW5nLmxlbmd0aCwgbywgZW5jb2RpbmcgKTtcblx0XHRcdHJldHVybiAhIWVuY29kaW5nLmZpbmQoIChlbyxpKT0+ZW89PT1vICYmIGkgPCAoZW5jb2RpbmcubGVuZ3RoLTEpIClcblx0XHR9LFxuXHRcdGVuY29kZU9iamVjdChvKSB7XG5cdFx0XHRpZiggb2JqZWN0VG9KU09YICkgXG5cdFx0XHRcdHJldHVybiBvYmplY3RUb0pTT1guYXBwbHkobywgW3RoaXNdKTtcblx0XHRcdHJldHVybiBvO1xuXHRcdH0sXG5cdFx0c3RyaW5naWZ5KG8scixzKSB7IHJldHVybiBzdHJpbmdpZnkobyxyLHMpIH0sXG5cdFx0c2V0UXVvdGUocSkgeyB1c2VRdW90ZSA9IHE7IH0sXG5cdFx0cmVnaXN0ZXJUb0pTT1gobixwLGYpIHsgcmV0dXJuIHRoaXMudG9KU09YKCBuLHAsZiApIH0sXG5cdFx0dG9KU09YKCBuYW1lLCBwdHlwZSwgZiApIHtcblx0XHRcdGlmKCBwdHlwZS5wcm90b3R5cGUgJiYgcHR5cGUucHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICkge1xuXHRcdFx0XHRpZiggbG9jYWxUb1Byb3RvVHlwZXMuZ2V0KHB0eXBlLnByb3RvdHlwZSkgKSB0aHJvdyBuZXcgRXJyb3IoIFwiRXhpc3RpbmcgdG9KU09YIGhhcyBiZWVuIHJlZ2lzdGVyZWQgZm9yIHByb3RvdHlwZVwiICk7XG5cdFx0XHRcdGxvY2FsVG9Qcm90b1R5cGVzLnNldCggcHR5cGUucHJvdG90eXBlLCB7IGV4dGVybmFsOnRydWUsIG5hbWU6bmFtZXx8Zi5jb25zdHJ1Y3Rvci5uYW1lLCBjYjpmIH0gKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxldCBrZXkgPSBPYmplY3Qua2V5cyggcHR5cGUgKS50b1N0cmluZygpO1xuXHRcdFx0XHRpZiggbG9jYWxUb09iamVjdFR5cGVzLmdldChrZXkpICkgdGhyb3cgbmV3IEVycm9yKCBcIkV4aXN0aW5nIHRvSlNPWCBoYXMgYmVlbiByZWdpc3RlcmVkIGZvciBvYmplY3QgdHlwZVwiICk7XG5cdFx0XHRcdGxvY2FsVG9PYmplY3RUeXBlcy5zZXQoIGtleSwgeyBleHRlcm5hbDp0cnVlLCBuYW1lOm5hbWUsIGNiOmYgfSApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Z2V0IGlnbm9yZU5vbkVudW1lcmFibGUoKSB7IHJldHVybiBpZ25vcmVOb25FbnVtZXJhYmxlOyB9LFxuXHRcdHNldCBpZ25vcmVOb25FbnVtZXJhYmxlKHZhbCkgeyBpZ25vcmVOb25FbnVtZXJhYmxlID0gdmFsOyB9LFxuXHR9XG5cdHJldHVybiBzdHJpbmdpZmllcjtcblxuXHQvKipcblx0ICogZ2V0IGEgcmVmZXJlbmNlIHRvIGEgcHJldmlvdXNseSBzZWVuIG9iamVjdFxuXHQgKiBAcGFyYW0ge2FueX0gaGVyZSBcblx0ICogQHJldHVybnMgcmVmZXJlbmNlIHRvIGV4aXN0aW5nIG9iamVjdCwgb3IgdW5kZWZpbmVkIGlmIG5vdCBmb3VuZC5cblx0ICovXG5cdGZ1bmN0aW9uIGdldFJlZmVyZW5jZSggaGVyZSApIHtcblx0XHRpZiggaGVyZSA9PT0gbnVsbCApIHJldHVybiB1bmRlZmluZWQ7XG5cdFx0bGV0IGZpZWxkID0gZmllbGRNYXAuZ2V0KCBoZXJlICk7XG5cdFx0Ly9fREVCVUdfU1RSSU5HSUZZICYmIGNvbnNvbGUubG9nKCBcInBhdGg6XCIsIF9KU09OLnN0cmluZ2lmeShwYXRoKSwgZmllbGQgKTtcblx0XHRpZiggIWZpZWxkICkge1xuXHRcdFx0ZmllbGRNYXAuc2V0KCBoZXJlLCBfSlNPTi5zdHJpbmdpZnkocGF0aCkgKTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdHJldHVybiBcInJlZlwiK2ZpZWxkO1xuXHR9XG5cblxuXHQvKipcblx0ICogZmluZCB0aGUgcHJvdG90eXBlIGRlZmluaXRpb24gZm9yIGEgY2xhc3Ncblx0ICogQHBhcmFtIHtvYmplY3R9IG8gXG5cdCAqIEBwYXJhbSB7bWFwfSB1c2VLIFxuXHQgKiBAcmV0dXJucyBvYmplY3Rcblx0ICovXG5cdGZ1bmN0aW9uIG1hdGNoT2JqZWN0KG8sdXNlSykge1xuXHRcdGxldCBrO1xuXHRcdGxldCBjbHM7XG5cdFx0bGV0IHBydCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvKTtcblx0XHRjbHMgPSBjbGFzc2VzLmZpbmQoIGNscz0+e1xuXHRcdFx0aWYoIGNscy5wcm90byAmJiBjbHMucHJvdG8gPT09IHBydCApIHJldHVybiB0cnVlO1xuXHRcdH0gKTtcblx0XHRpZiggY2xzICkgcmV0dXJuIGNscztcblxuXHRcdGlmKCBjbGFzc2VzLmxlbmd0aCB8fCBjb21tb25DbGFzc2VzLmxlbmd0aCApIHtcblx0XHRcdGlmKCB1c2VLICkgIHtcblx0XHRcdFx0dXNlSyA9IHVzZUsubWFwKCB2PT57IGlmKCB0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIiApIHJldHVybiB2OyBlbHNlIHJldHVybiB1bmRlZmluZWQ7IH0gKTtcblx0XHRcdFx0ayA9IHVzZUsudG9TdHJpbmcoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxldCBkZW5vcm1LZXlzID0gT2JqZWN0LmtleXMobyk7XG5cdFx0XHRcdGZvciggbGV0IGkgPSAxOyBpIDwgZGVub3JtS2V5cy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0XHRsZXQgYSwgYjtcblx0XHRcdFx0XHRpZiggKCBhID0gZGVub3JtS2V5c1tpLTFdICkgPiAoIGIgPSBkZW5vcm1LZXlzW2ldICkgKSB7XG5cdFx0XHRcdFx0XHRkZW5vcm1LZXlzW2ktMV0gPSBiO1xuXHRcdFx0XHRcdFx0ZGVub3JtS2V5c1tpXSA9IGE7XG5cdFx0XHRcdFx0XHRpZiggaSApIGktPTI7IC8vIGdvIGJhY2sgMiwgdGhpcyBtaWdodCBuZWVkIHRvIGdvIGZ1cnRoZXIgcGFjay5cblx0XHRcdFx0XHRcdGVsc2UgaS0tOyAvLyBvbmx5IDEgdG8gY2hlY2suXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGsgPSBkZW5vcm1LZXlzLnRvU3RyaW5nKCk7XG5cdFx0XHR9XG5cdFx0XHRjbHMgPSBjbGFzc2VzLmZpbmQoIGNscz0+e1xuXHRcdFx0XHRpZiggY2xzLnRhZyA9PT0gayApIHJldHVybiB0cnVlO1xuXHRcdFx0fSApO1xuXHRcdFx0aWYoICFjbHMgKVxuXHRcdFx0XHRjbHMgPSBjb21tb25DbGFzc2VzLmZpbmQoIGNscz0+e1xuXHRcdFx0XHRcdGlmKCBjbHMudGFnID09PSBrICkgcmV0dXJuIHRydWU7XG5cdFx0XHRcdH0gKTtcblx0XHR9XG5cdFx0cmV0dXJuIGNscztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXJpYWxpemUgYW4gb2JqZWN0IHRvIEpTT1ggdGV4dC5cblx0ICogQHBhcmFtIHthbnl9IG9iamVjdCBcblx0ICogQHBhcmFtIHsoa2V5OnN0cmluZyx2YWx1ZTphbnkpPT5zdHJpbmd9IHJlcGxhY2VyIFxuXHQgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHNwYWNlIFxuXHQgKiBAcmV0dXJucyBcblx0ICovXG5cdGZ1bmN0aW9uIHN0cmluZ2lmeSggb2JqZWN0LCByZXBsYWNlciwgc3BhY2UgKSB7XG5cdFx0aWYoIG9iamVjdCA9PT0gdW5kZWZpbmVkICkgcmV0dXJuIFwidW5kZWZpbmVkXCI7XG5cdFx0aWYoIG9iamVjdCA9PT0gbnVsbCApIHJldHVybjtcblx0XHRsZXQgZ2FwO1xuXHRcdGxldCBpbmRlbnQ7XG5cdFx0bGV0IHJlcDtcblxuXHRcdGxldCBpO1xuXHRcdGNvbnN0IHNwYWNlVHlwZSA9IHR5cGVvZiBzcGFjZTtcblx0XHRjb25zdCByZXBUeXBlID0gdHlwZW9mIHJlcGxhY2VyO1xuXHRcdGdhcCA9IFwiXCI7XG5cdFx0aW5kZW50ID0gXCJcIjtcblxuXHRcdC8vIElmIHRoZSBzcGFjZSBwYXJhbWV0ZXIgaXMgYSBudW1iZXIsIG1ha2UgYW4gaW5kZW50IHN0cmluZyBjb250YWluaW5nIHRoYXRcblx0XHQvLyBtYW55IHNwYWNlcy5cblxuXHRcdGlmIChzcGFjZVR5cGUgPT09IFwibnVtYmVyXCIpIHtcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBzcGFjZTsgaSArPSAxKSB7XG5cdFx0XHRcdGluZGVudCArPSBcIiBcIjtcblx0XHRcdH1cblxuXHRcdC8vIElmIHRoZSBzcGFjZSBwYXJhbWV0ZXIgaXMgYSBzdHJpbmcsIGl0IHdpbGwgYmUgdXNlZCBhcyB0aGUgaW5kZW50IHN0cmluZy5cblx0XHR9IGVsc2UgaWYgKHNwYWNlVHlwZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0aW5kZW50ID0gc3BhY2U7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlcmUgaXMgYSByZXBsYWNlciwgaXQgbXVzdCBiZSBhIGZ1bmN0aW9uIG9yIGFuIGFycmF5LlxuXHRcdC8vIE90aGVyd2lzZSwgdGhyb3cgYW4gZXJyb3IuXG5cblx0XHRyZXAgPSByZXBsYWNlcjtcblx0XHRpZiggcmVwbGFjZXIgJiYgcmVwVHlwZSAhPT0gXCJmdW5jdGlvblwiXG5cdFx0ICAgICYmICggcmVwVHlwZSAhPT0gXCJvYmplY3RcIlxuXHRcdCAgICAgICB8fCB0eXBlb2YgcmVwbGFjZXIubGVuZ3RoICE9PSBcIm51bWJlclwiXG5cdFx0ICAgKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiSlNPWC5zdHJpbmdpZnlcIik7XG5cdFx0fVxuXG5cdFx0cGF0aC5sZW5ndGggPSAwO1xuXHRcdGZpZWxkTWFwID0gbmV3IFdlYWtNYXAoKTtcblxuXHRcdGNvbnN0IGZpbmFsUmVzdWx0ID0gc3RyKCBcIlwiLCB7XCJcIjpvYmplY3R9ICk7XG5cdFx0Y29tbW9uQ2xhc3Nlcy5sZW5ndGggPSAwO1xuXHRcdHJldHVybiBmaW5hbFJlc3VsdDtcblxuXHRcdC8vIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2RvdWdsYXNjcm9ja2ZvcmQvSlNPTi1qcy9ibG9iL21hc3Rlci9qc29uMi5qcyNMMTgxXG5cdFx0ZnVuY3Rpb24gc3RyKGtleSwgaG9sZGVyKSB7XG5cdFx0XHR2YXIgbWluZCA9IGdhcDtcblx0XHRcdGNvbnN0IGRvQXJyYXlUb0pTT1hfID0gYXJyYXlUb0pTT1guY2I7XG5cdFx0XHRjb25zdCBtYXBUb09iamVjdF8gPSBtYXBUb0pTT1guY2I7XHRcdCBcblx0XHRcdGFycmF5VG9KU09YLmNiID0gZG9BcnJheVRvSlNPWDtcblx0XHRcdG1hcFRvSlNPWC5jYiA9IG1hcFRvT2JqZWN0O1xuXHRcdFx0Y29uc3QgdiA9IHN0cl8oa2V5LGhvbGRlcik7XG5cdFx0XHRhcnJheVRvSlNPWC5jYiA9IGRvQXJyYXlUb0pTT1hfO1xuXHRcdFx0bWFwVG9KU09YLmNiID0gbWFwVG9PYmplY3RfO1xuXHRcdFx0cmV0dXJuIHY7XG5cblx0XHRcdGZ1bmN0aW9uIGRvQXJyYXlUb0pTT1goKSB7XG5cdFx0XHRcdGxldCB2O1xuXHRcdFx0XHRsZXQgcGFydGlhbCA9IFtdO1xuXHRcdFx0XHRsZXQgdGhpc05vZGVOYW1lSW5kZXggPSBwYXRoLmxlbmd0aDtcblxuXHRcdFx0XHQvLyBUaGUgdmFsdWUgaXMgYW4gYXJyYXkuIFN0cmluZ2lmeSBldmVyeSBlbGVtZW50LiBVc2UgbnVsbCBhcyBhIHBsYWNlaG9sZGVyXG5cdFx0XHRcdC8vIGZvciBub24tSlNPWCB2YWx1ZXMuXG5cdFx0XHRcblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSArPSAxKSB7XG5cdFx0XHRcdFx0cGF0aFt0aGlzTm9kZU5hbWVJbmRleF0gPSBpO1xuXHRcdFx0XHRcdHBhcnRpYWxbaV0gPSBzdHIoaSwgdGhpcykgfHwgXCJudWxsXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0cGF0aC5sZW5ndGggPSB0aGlzTm9kZU5hbWVJbmRleDtcblx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJyZW1vdmUgZW5jb2RpbmcgaXRlbVwiLCB0aGlzTm9kZU5hbWVJbmRleCwgZW5jb2RpbmcubGVuZ3RoKTtcblx0XHRcdFx0ZW5jb2RpbmcubGVuZ3RoID0gdGhpc05vZGVOYW1lSW5kZXg7XG5cdFx0XHRcblx0XHRcdFx0Ly8gSm9pbiBhbGwgb2YgdGhlIGVsZW1lbnRzIHRvZ2V0aGVyLCBzZXBhcmF0ZWQgd2l0aCBjb21tYXMsIGFuZCB3cmFwIHRoZW0gaW5cblx0XHRcdFx0Ly8gYnJhY2tldHMuXG5cdFx0XHRcdHYgPSAoIHBhcnRpYWwubGVuZ3RoID09PSAwXG5cdFx0XHRcdFx0PyBcIltdXCJcblx0XHRcdFx0XHQ6IGdhcFxuXHRcdFx0XHRcdFx0PyBbXG5cdFx0XHRcdFx0XHRcdFwiW1xcblwiXG5cdFx0XHRcdFx0XHRcdCwgZ2FwXG5cdFx0XHRcdFx0XHRcdCwgcGFydGlhbC5qb2luKFwiLFxcblwiICsgZ2FwKVxuXHRcdFx0XHRcdFx0XHQsIFwiXFxuXCJcblx0XHRcdFx0XHRcdFx0LCBtaW5kXG5cdFx0XHRcdFx0XHRcdCwgXCJdXCJcblx0XHRcdFx0XHRcdF0uam9pbihcIlwiKVxuXHRcdFx0XHRcdFx0OiBcIltcIiArIHBhcnRpYWwuam9pbihcIixcIikgKyBcIl1cIiApO1xuXHRcdFx0XHRyZXR1cm4gdjtcblx0XHRcdH0gXG5cdFx0XHRmdW5jdGlvbiBtYXBUb09iamVjdCgpe1xuXHRcdFx0XHQvL19ERUJVR19QQVJTSU5HX0RFVEFJTFMgJiYgY29uc29sZS5sb2coIFwiLS0tLS0tLS0tLSBORVcgTUFQIC0tLS0tLS0tLS0tLS1cIiApO1xuXHRcdFx0XHRsZXQgdG1wID0ge3RtcDpudWxsfTtcblx0XHRcdFx0bGV0IG91dCA9ICd7J1xuXHRcdFx0XHRsZXQgZmlyc3QgPSB0cnVlO1xuXHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIkNPTlZFUlQ6XCIsIG1hcCk7XG5cdFx0XHRcdGZvciAobGV0IFtrZXksIHZhbHVlXSBvZiB0aGlzKSB7XG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJlci4uLlwiLCBrZXksIHZhbHVlIClcblx0XHRcdFx0XHR0bXAudG1wID0gdmFsdWU7XG5cdFx0XHRcdFx0bGV0IHRoaXNOb2RlTmFtZUluZGV4ID0gcGF0aC5sZW5ndGg7XG5cdFx0XHRcdFx0cGF0aFt0aGlzTm9kZU5hbWVJbmRleF0gPSBrZXk7XG5cdFx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdG91dCArPSAoZmlyc3Q/XCJcIjpcIixcIikgKyBnZXRJZGVudGlmaWVyKGtleSkgKyc6JyArIHN0cihcInRtcFwiLCB0bXApO1xuXHRcdFx0XHRcdHBhdGgubGVuZ3RoID0gdGhpc05vZGVOYW1lSW5kZXg7XG5cdFx0XHRcdFx0Zmlyc3QgPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRvdXQgKz0gJ30nO1xuXHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIm91dCBpczpcIiwgb3V0ICk7XG5cdFx0XHRcdHJldHVybiBvdXQ7XG5cdFx0XHR9XG5cblx0XHQvLyBQcm9kdWNlIGEgc3RyaW5nIGZyb20gaG9sZGVyW2tleV0uXG5cdFx0ZnVuY3Rpb24gc3RyXyhrZXksIGhvbGRlcikge1xuXG5cdFx0XHRsZXQgaTsgICAgICAgICAgLy8gVGhlIGxvb3AgY291bnRlci5cblx0XHRcdGxldCBrOyAgICAgICAgICAvLyBUaGUgbWVtYmVyIGtleS5cblx0XHRcdGxldCB2OyAgICAgICAgICAvLyBUaGUgbWVtYmVyIHZhbHVlLlxuXHRcdFx0bGV0IGxlbmd0aDtcblx0XHRcdGxldCBwYXJ0aWFsQ2xhc3M7XG5cdFx0XHRsZXQgcGFydGlhbDtcblx0XHRcdGxldCB0aGlzTm9kZU5hbWVJbmRleCA9IHBhdGgubGVuZ3RoO1xuXHRcdFx0bGV0IGlzVmFsdWUgPSB0cnVlO1xuXHRcdFx0bGV0IHZhbHVlID0gaG9sZGVyW2tleV07XG5cdFx0XHRsZXQgaXNPYmplY3QgPSAodHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiKTtcblx0XHRcdGxldCBjO1xuXG5cdFx0XHRpZiggaXNPYmplY3QgJiYgKCB2YWx1ZSAhPT0gbnVsbCApICkge1xuXHRcdFx0XHRpZiggb2JqZWN0VG9KU09YICl7XG5cdFx0XHRcdFx0aWYoICFzdHJpbmdpZnlpbmcuZmluZCggdmFsPT52YWw9PT12YWx1ZSApICkge1xuXHRcdFx0XHRcdFx0c3RyaW5naWZ5aW5nLnB1c2goIHZhbHVlICk7XG5cdFx0XHRcdFx0XHRlbmNvZGluZ1t0aGlzTm9kZU5hbWVJbmRleF0gPSB2YWx1ZTtcblx0XHRcdFx0XHRcdGlzVmFsdWUgPSBmYWxzZTtcblx0XHRcdFx0XHRcdHZhbHVlID0gb2JqZWN0VG9KU09YLmFwcGx5KHZhbHVlLCBbc3RyaW5naWZpZXJdKTtcblx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coIFwiQ29udmVydGVkIGJ5IG9iamVjdCBsb29rdXAgLWl0J3Mgbm93IGEgZGlmZmVyZW50IHR5cGVcIlxuXHRcdFx0XHRcdFx0Ly9cdCwgcHJvdG9Db252ZXJ0ZXIsIG9iamVjdENvbnZlcnRlciApO1xuXHRcdFx0XHRcdFx0aXNPYmplY3QgPSAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiApO1xuXHRcdFx0XHRcdFx0c3RyaW5naWZ5aW5nLnBvcCgpO1xuXHRcdFx0XHRcdFx0ZW5jb2RpbmcubGVuZ3RoID0gdGhpc05vZGVOYW1lSW5kZXg7XG5cdFx0XHRcdFx0XHRpc09iamVjdCA9ICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIlZhbHVlIGNvbnZlcmV0ZWQgdG86XCIsIGtleSwgdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgb2JqVHlwZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoIHZhbHVlICk7XG5cdFx0XHRcblx0XHRcdGxldCBwcm90b0NvbnZlcnRlciA9IG9ialR5cGVcblx0XHRcdFx0JiYgKCBsb2NhbFRvUHJvdG9UeXBlcy5nZXQoIG9ialR5cGUgKSBcblx0XHRcdFx0fHwgdG9Qcm90b1R5cGVzLmdldCggb2JqVHlwZSApIFxuXHRcdFx0XHR8fCBudWxsIClcblx0XHRcdGxldCBvYmplY3RDb252ZXJ0ZXIgPSAhcHJvdG9Db252ZXJ0ZXIgJiYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwpIFxuXHRcdFx0XHQmJiAoIGxvY2FsVG9PYmplY3RUeXBlcy5nZXQoIE9iamVjdC5rZXlzKCB2YWx1ZSApLnRvU3RyaW5nKCkgKSBcblx0XHRcdFx0fHwgdG9PYmplY3RUeXBlcy5nZXQoIE9iamVjdC5rZXlzKCB2YWx1ZSApLnRvU3RyaW5nKCkgKSBcblx0XHRcdFx0fHwgbnVsbCApXG5cblx0XHRcdC8vIElmIHdlIHdlcmUgY2FsbGVkIHdpdGggYSByZXBsYWNlciBmdW5jdGlvbiwgdGhlbiBjYWxsIHRoZSByZXBsYWNlciB0b1xuXHRcdFx0Ly8gb2J0YWluIGEgcmVwbGFjZW1lbnQgdmFsdWUuXG5cblx0XHRcdGlmICh0eXBlb2YgcmVwID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0aXNWYWx1ZSA9IGZhbHNlO1xuXHRcdFx0XHR2YWx1ZSA9IHJlcC5jYWxsKGhvbGRlciwga2V5LCB2YWx1ZSk7XG5cdFx0XHR9XG5cdFx0XHRcdC8vY29uc29sZS5sb2coIFwiUFJPVE9UWVBFOlwiLCBPYmplY3QuZ2V0UHJvdG90eXBlT2YoIHZhbHVlICkgKVxuXHRcdFx0XHQvL2NvbnNvbGUubG9nKCBcIlBST1RPVFlQRTpcIiwgdG9Qcm90b1R5cGVzLmdldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoIHZhbHVlICkpIClcblx0XHRcdFx0Ly9pZiggcHJvdG9Db252ZXJ0ZXIgKVxuXHRcdFx0Ly9fREVCVUdfU1RSSU5HSUZZICYmIGNvbnNvbGUubG9nKCBcIlRFU1QoKVwiLCB2YWx1ZSwgcHJvdG9Db252ZXJ0ZXIsIG9iamVjdENvbnZlcnRlciApO1xuXG5cdFx0XHRsZXQgdG9KU09YID0gKCBwcm90b0NvbnZlcnRlciAmJiBwcm90b0NvbnZlcnRlci5jYiApIFxuXHRcdFx0ICAgICAgICAgIHx8ICggb2JqZWN0Q29udmVydGVyICYmIG9iamVjdENvbnZlcnRlci5jYiApO1xuXHRcdFx0Ly8gSWYgdGhlIHZhbHVlIGhhcyBhIHRvSlNPWCBtZXRob2QsIGNhbGwgaXQgdG8gb2J0YWluIGEgcmVwbGFjZW1lbnQgdmFsdWUuXG5cdFx0XHQvL19ERUJVR19TVFJJTkdJRlkgJiYgY29uc29sZS5sb2coIFwidHlwZTpcIiwgdHlwZW9mIHZhbHVlLCBwcm90b0NvbnZlcnRlciwgISF0b0pTT1gsIHBhdGggKTtcblxuXHRcdFx0aWYoIHZhbHVlICE9PSB1bmRlZmluZWRcblx0XHRcdCAgICAmJiB2YWx1ZSAhPT0gbnVsbFxuXHRcdFx0XHQmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCJcblx0XHRcdCAgICAmJiB0eXBlb2YgdG9KU09YID09PSBcImZ1bmN0aW9uXCJcblx0XHRcdCkge1xuXHRcdFx0XHRpZiggIXN0cmluZ2lmeWluZy5maW5kKCB2YWw9PnZhbD09PXZhbHVlICkgKSB7XG5cdFx0XHRcdFx0aWYoIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdFx0XHRcdHYgPSBnZXRSZWZlcmVuY2UoIHZhbHVlICk7XG5cdFx0XHRcdFx0XHRpZiggdiApXHRyZXR1cm4gdjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzdHJpbmdpZnlpbmcucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0XHRlbmNvZGluZ1t0aGlzTm9kZU5hbWVJbmRleF0gPSB2YWx1ZTtcblx0XHRcdFx0XHR2YWx1ZSA9IHRvSlNPWC5jYWxsKHZhbHVlLCBzdHJpbmdpZmllcik7XG5cdFx0XHRcdFx0aXNWYWx1ZSA9IGZhbHNlO1xuXHRcdFx0XHRcdHN0cmluZ2lmeWluZy5wb3AoKTtcblx0XHRcdFx0XHRpZiggcHJvdG9Db252ZXJ0ZXIgJiYgcHJvdG9Db252ZXJ0ZXIubmFtZSApIHtcblx0XHRcdFx0XHRcdC8vIHN0cmluZ2lmeSBtYXkgcmV0dXJuIGEgdW5xdW90ZWQgc3RyaW5nXG5cdFx0XHRcdFx0XHQvLyB3aGljaCBuZWVkcyBhbiBleHRyYSBzcGFjZSBiZXR3ZW4gaXRzIHRhZyBhbmQgdmFsdWUuXG5cdFx0XHRcdFx0XHRpZiggXCJzdHJpbmdcIiA9PT0gdHlwZW9mIHZhbHVlIFxuXHRcdFx0XHRcdFx0XHQmJiB2YWx1ZVswXSAhPT0gJy0nXG5cdFx0XHRcdFx0XHRcdCYmICh2YWx1ZVswXSA8ICcwJyB8fCB2YWx1ZVswXSA+ICc5JyApXG5cdFx0XHRcdFx0XHRcdCYmIHZhbHVlWzBdICE9PSAnXCInXG5cdFx0XHRcdFx0XHRcdCYmIHZhbHVlWzBdICE9PSAnXFwnJyBcblx0XHRcdFx0XHRcdFx0JiYgdmFsdWVbMF0gIT09ICdgJyBcblx0XHRcdFx0XHRcdFx0JiYgdmFsdWVbMF0gIT09ICdbJyBcblx0XHRcdFx0XHRcdFx0JiYgdmFsdWVbMF0gIT09ICd7JyBcblx0XHRcdFx0XHRcdFx0KXtcblx0XHRcdFx0XHRcdFx0dmFsdWUgPSAnICcgKyB2YWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggXCJWYWx1ZSBjb252ZXJ0ZWQ6XCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0ZW5jb2RpbmcubGVuZ3RoID0gdGhpc05vZGVOYW1lSW5kZXg7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0diA9IGdldFJlZmVyZW5jZSggdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdH0gZWxzZSBcblx0XHRcdFx0aWYoIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdFx0XHR2ID0gZ2V0UmVmZXJlbmNlKCB2YWx1ZSApO1xuXHRcdFx0XHRcdGlmKCB2ICkgcmV0dXJuIHY7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gV2hhdCBoYXBwZW5zIG5leHQgZGVwZW5kcyBvbiB0aGUgdmFsdWUncyB0eXBlLlxuXHRcdFx0c3dpdGNoICh0eXBlb2YgdmFsdWUpIHtcblx0XHRcdGNhc2UgXCJiaWdpbnRcIjpcblx0XHRcdFx0cmV0dXJuIHZhbHVlICsgJ24nO1xuXHRcdFx0Y2FzZSBcInN0cmluZ1wiOlxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZyggYFZhbHVlIHdhcyBjb252ZXJ0ZWQgYmVmb3JlPyAgWyR7dmFsdWV9XWApO1xuXHRcdFx0XHRcdHZhbHVlID0gaXNWYWx1ZT9nZXRJZGVudGlmaWVyKHZhbHVlKTp2YWx1ZTtcblx0XHRcdFx0XHRsZXQgYyA9ICcnO1xuXHRcdFx0XHRcdGlmKCBrZXk9PT1cIlwiIClcblx0XHRcdFx0XHRcdGMgPSBjbGFzc2VzLm1hcCggY2xzPT4gY2xzLm5hbWUrXCJ7XCIrY2xzLmZpZWxkcy5qb2luKFwiLFwiKStcIn1cIiApLmpvaW4oZ2FwP1wiXFxuXCI6XCJcIikrXG5cdFx0XHRcdFx0XHQgICAgY29tbW9uQ2xhc3Nlcy5tYXAoIGNscz0+IGNscy5uYW1lK1wie1wiK2Nscy5maWVsZHMuam9pbihcIixcIikrXCJ9XCIgKS5qb2luKGdhcD9cIlxcblwiOlwiXCIpXG5cdFx0XHRcdFx0XHRcdFx0KyhnYXA/XCJcXG5cIjpcIlwiKTtcblx0XHRcdFx0XHRpZiggcHJvdG9Db252ZXJ0ZXIgJiYgcHJvdG9Db252ZXJ0ZXIuZXh0ZXJuYWwgKSBcblx0XHRcdFx0XHRcdHJldHVybiBjICsgcHJvdG9Db252ZXJ0ZXIubmFtZSArIHZhbHVlO1xuXHRcdFx0XHRcdGlmKCBvYmplY3RDb252ZXJ0ZXIgJiYgb2JqZWN0Q29udmVydGVyLmV4dGVybmFsICkgXG5cdFx0XHRcdFx0XHRyZXR1cm4gYyArIG9iamVjdENvbnZlcnRlci5uYW1lICsgdmFsdWU7XG5cdFx0XHRcdFx0cmV0dXJuIGMgKyB2YWx1ZTsvL3VzZVF1b3RlK0pTT1guZXNjYXBlKCB2YWx1ZSApK3VzZVF1b3RlO1xuXHRcdFx0XHR9XG5cdFx0XHRjYXNlIFwibnVtYmVyXCI6XG5cdFx0XHRjYXNlIFwiYm9vbGVhblwiOlxuXHRcdFx0Y2FzZSBcIm51bGxcIjpcblxuXHRcdFx0XHQvLyBJZiB0aGUgdmFsdWUgaXMgYSBib29sZWFuIG9yIG51bGwsIGNvbnZlcnQgaXQgdG8gYSBzdHJpbmcuIE5vdGU6XG5cdFx0XHRcdC8vIHR5cGVvZiBudWxsIGRvZXMgbm90IHByb2R1Y2UgXCJudWxsXCIuIFRoZSBjYXNlIGlzIGluY2x1ZGVkIGhlcmUgaW5cblx0XHRcdFx0Ly8gdGhlIHJlbW90ZSBjaGFuY2UgdGhhdCB0aGlzIGdldHMgZml4ZWQgc29tZWRheS5cblxuXHRcdFx0XHRyZXR1cm4gU3RyaW5nKHZhbHVlKTtcblxuXHRcdFx0XHQvLyBJZiB0aGUgdHlwZSBpcyBcIm9iamVjdFwiLCB3ZSBtaWdodCBiZSBkZWFsaW5nIHdpdGggYW4gb2JqZWN0IG9yIGFuIGFycmF5IG9yXG5cdFx0XHRcdC8vIG51bGwuXG5cblx0XHRcdGNhc2UgXCJvYmplY3RcIjpcblx0XHRcdFx0Ly9fREVCVUdfU1RSSU5HSUZZICYmIGNvbnNvbGUubG9nKCBcIkVOVEVSSU5UIE9CSkVDVCBFTUlTU0lPTiBXSVRIOlwiLCB2ICk7XG5cdFx0XHRcdGlmKCB2ICkgcmV0dXJuIFwicmVmXCIrdjtcblxuXHRcdFx0XHQvLyBEdWUgdG8gYSBzcGVjaWZpY2F0aW9uIGJsdW5kZXIgaW4gRUNNQVNjcmlwdCwgdHlwZW9mIG51bGwgaXMgXCJvYmplY3RcIixcblx0XHRcdFx0Ly8gc28gd2F0Y2ggb3V0IGZvciB0aGF0IGNhc2UuXG5cdFx0XHRcdGlmICghdmFsdWUpIHtcblx0XHRcdFx0XHRyZXR1cm4gXCJudWxsXCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBNYWtlIGFuIGFycmF5IHRvIGhvbGQgdGhlIHBhcnRpYWwgcmVzdWx0cyBvZiBzdHJpbmdpZnlpbmcgdGhpcyBvYmplY3QgdmFsdWUuXG5cdFx0XHRcdGdhcCArPSBpbmRlbnQ7XG5cdFx0XHRcdHBhcnRpYWxDbGFzcyA9IG51bGw7XG5cdFx0XHRcdHBhcnRpYWwgPSBbXTtcblxuXHRcdFx0XHQvLyBJZiB0aGUgcmVwbGFjZXIgaXMgYW4gYXJyYXksIHVzZSBpdCB0byBzZWxlY3QgdGhlIG1lbWJlcnMgdG8gYmUgc3RyaW5naWZpZWQuXG5cdFx0XHRcdGlmIChyZXAgJiYgdHlwZW9mIHJlcCA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0XHRcdGxlbmd0aCA9IHJlcC5sZW5ndGg7XG5cdFx0XHRcdFx0cGFydGlhbENsYXNzID0gbWF0Y2hPYmplY3QoIHZhbHVlLCByZXAgKTtcblx0XHRcdFx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcblx0XHRcdFx0XHRcdGlmICh0eXBlb2YgcmVwW2ldID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdFx0XHRcdGsgPSByZXBbaV07XG5cdFx0XHRcdFx0XHRcdHBhdGhbdGhpc05vZGVOYW1lSW5kZXhdID0gaztcblx0XHRcdFx0XHRcdFx0diA9IHN0cihrLCB2YWx1ZSk7XG5cblx0XHRcdFx0XHRcdFx0aWYgKHYgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiggcGFydGlhbENsYXNzICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cGFydGlhbC5wdXNoKHYpO1xuXHRcdFx0XHRcdFx0XHRcdH0gZWxzZVxuXHRcdFx0XHRcdFx0XHRcdFx0cGFydGlhbC5wdXNoKCBnZXRJZGVudGlmaWVyKGspIFxuXHRcdFx0XHRcdFx0XHRcdFx0KyAoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdChnYXApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PyBcIjogXCJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ6IFwiOlwiXG5cdFx0XHRcdFx0XHRcdFx0XHQpICsgdik7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cGF0aC5zcGxpY2UoIHRoaXNOb2RlTmFtZUluZGV4LCAxICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHQvLyBPdGhlcndpc2UsIGl0ZXJhdGUgdGhyb3VnaCBhbGwgb2YgdGhlIGtleXMgaW4gdGhlIG9iamVjdC5cblx0XHRcdFx0XHRwYXJ0aWFsQ2xhc3MgPSBtYXRjaE9iamVjdCggdmFsdWUgKTtcblx0XHRcdFx0XHRsZXQga2V5cyA9IFtdO1xuXHRcdFx0XHRcdGZvciAoayBpbiB2YWx1ZSkge1xuXHRcdFx0XHRcdFx0aWYoIGlnbm9yZU5vbkVudW1lcmFibGUgKVxuXHRcdFx0XHRcdFx0XHRpZiggIU9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCggdmFsdWUsIGsgKSApe1xuXHRcdFx0XHRcdFx0XHRcdC8vX0RFQlVHX1NUUklOR0lGWSAmJiBjb25zb2xlLmxvZyggXCJza2lwcGluZyBub24tZW51ZXJhYmxlP1wiLCBrICk7XG5cdFx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIGspKSB7XG5cdFx0XHRcdFx0XHRcdGxldCBuO1xuXHRcdFx0XHRcdFx0XHRmb3IoIG4gPSAwOyBuIDwga2V5cy5sZW5ndGg7IG4rKyApIFxuXHRcdFx0XHRcdFx0XHRcdGlmKCBrZXlzW25dID4gayApIHtcdFxuXHRcdFx0XHRcdFx0XHRcdFx0a2V5cy5zcGxpY2UobiwwLGsgKTtcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0aWYoIG4gPT0ga2V5cy5sZW5ndGggKVxuXHRcdFx0XHRcdFx0XHRcdGtleXMucHVzaChrKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Zm9yKGxldCBuID0gMDsgbiA8IGtleXMubGVuZ3RoOyBuKyspIHtcblx0XHRcdFx0XHRcdGsgPSBrZXlzW25dO1xuXHRcdFx0XHRcdFx0aWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgaykpIHtcblx0XHRcdFx0XHRcdFx0cGF0aFt0aGlzTm9kZU5hbWVJbmRleF0gPSBrO1xuXHRcdFx0XHRcdFx0XHR2ID0gc3RyKGssIHZhbHVlKTtcblxuXHRcdFx0XHRcdFx0XHRpZiAodiAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmKCBwYXJ0aWFsQ2xhc3MgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRwYXJ0aWFsLnB1c2godik7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlXG5cdFx0XHRcdFx0XHRcdFx0XHRwYXJ0aWFsLnB1c2goZ2V0SWRlbnRpZmllcihrKSArIChcblx0XHRcdFx0XHRcdFx0XHRcdFx0KGdhcClcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ/IFwiOiBcIlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDogXCI6XCJcblx0XHRcdFx0XHRcdFx0XHRcdCkgKyB2KTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwYXRoLnNwbGljZSggdGhpc05vZGVOYW1lSW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEpvaW4gYWxsIG9mIHRoZSBtZW1iZXIgdGV4dHMgdG9nZXRoZXIsIHNlcGFyYXRlZCB3aXRoIGNvbW1hcyxcblx0XHRcdFx0Ly8gYW5kIHdyYXAgdGhlbSBpbiBicmFjZXMuXG5cdFx0XHRcdC8vX0RFQlVHX1NUUklOR0lGWSAmJiBjb25zb2xlLmxvZyggXCJwYXJ0aWFsOlwiLCBwYXJ0aWFsIClcblxuXHRcdFx0XHQvL2xldCBjO1xuXHRcdFx0XHRpZigga2V5PT09XCJcIiApXG5cdFx0XHRcdFx0YyA9ICggY2xhc3Nlcy5tYXAoIGNscz0+IGNscy5uYW1lK1wie1wiK2Nscy5maWVsZHMuam9pbihcIixcIikrXCJ9XCIgKS5qb2luKGdhcD9cIlxcblwiOlwiXCIpXG5cdFx0XHRcdFx0XHR8fCBjb21tb25DbGFzc2VzLm1hcCggY2xzPT4gY2xzLm5hbWUrXCJ7XCIrY2xzLmZpZWxkcy5qb2luKFwiLFwiKStcIn1cIiApLmpvaW4oZ2FwP1wiXFxuXCI6XCJcIikpKyhnYXA/XCJcXG5cIjpcIlwiKTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdGMgPSAnJztcblxuXHRcdFx0XHRpZiggcHJvdG9Db252ZXJ0ZXIgJiYgcHJvdG9Db252ZXJ0ZXIuZXh0ZXJuYWwgKSBcblx0XHRcdFx0XHRjID0gYyArIGdldElkZW50aWZpZXIocHJvdG9Db252ZXJ0ZXIubmFtZSk7XG5cblx0XHRcdFx0Ly9fREVCVUdfU1RSSU5HSUZZICYmIGNvbnNvbGUubG9nKCBcIlBSRUZJWCBGT1IgVEhJUyBGSUVMRDpcIiwgYyApO1xuXHRcdFx0XHRsZXQgaWRlbnQgPSBudWxsO1xuXHRcdFx0XHRpZiggcGFydGlhbENsYXNzIClcblx0XHRcdFx0XHRpZGVudCA9IGdldElkZW50aWZpZXIoIHBhcnRpYWxDbGFzcy5uYW1lICkgO1xuXHRcdFx0XHR2ID0gYyArXG5cdFx0XHRcdFx0KCBwYXJ0aWFsLmxlbmd0aCA9PT0gMFxuXHRcdFx0XHRcdD8gXCJ7fVwiXG5cdFx0XHRcdFx0OiBnYXBcblx0XHRcdFx0XHRcdFx0PyAocGFydGlhbENsYXNzP2lkZW50OlwiXCIpK1wie1xcblwiICsgZ2FwICsgcGFydGlhbC5qb2luKFwiLFxcblwiICsgZ2FwKSArIFwiXFxuXCIgKyBtaW5kICsgXCJ9XCJcblx0XHRcdFx0XHRcdFx0OiAocGFydGlhbENsYXNzP2lkZW50OlwiXCIpK1wie1wiICsgcGFydGlhbC5qb2luKFwiLFwiKSArIFwifVwiXG5cdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRnYXAgPSBtaW5kO1xuXHRcdFx0XHRyZXR1cm4gdjtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHR9XG59XG5cblx0Ly8gQ29udmVydHMgYW4gQXJyYXlCdWZmZXIgZGlyZWN0bHkgdG8gYmFzZTY0LCB3aXRob3V0IGFueSBpbnRlcm1lZGlhdGUgJ2NvbnZlcnQgdG8gc3RyaW5nIHRoZW5cblx0Ly8gdXNlIHdpbmRvdy5idG9hJyBzdGVwLiBBY2NvcmRpbmcgdG8gbXkgdGVzdHMsIHRoaXMgYXBwZWFycyB0byBiZSBhIGZhc3RlciBhcHByb2FjaDpcblx0Ly8gaHR0cDovL2pzcGVyZi5jb20vZW5jb2RpbmcteGhyLWltYWdlLWRhdGEvNVxuXHQvLyBkb2Vzbid0IGhhdmUgdG8gYmUgcmV2ZXJzYWJsZS4uLi5cblx0Y29uc3QgZW5jb2RpbmdzID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5JF8nXG5cdGNvbnN0IGRlY29kaW5ncyA9IHsgJ34nOi0xXG5cdFx0LCc9JzotMVxuXHRcdCwnJCc6NjJcblx0XHQsJ18nOjYzXG5cdFx0LCcrJzo2MlxuXHRcdCwnLSc6NjJcblx0XHQsJy4nOjYyXG5cdFx0LCcvJzo2M1xuXHRcdCwnLCc6NjNcblx0fTtcblx0XG5cdGZvciggbGV0IHggPSAwOyB4IDwgZW5jb2RpbmdzLmxlbmd0aDsgeCsrICkge1xuXHRcdGRlY29kaW5nc1tlbmNvZGluZ3NbeF1dID0geDtcblx0fVxuXHRPYmplY3QuZnJlZXplKCBkZWNvZGluZ3MgKTtcblx0XG5cdGZ1bmN0aW9uIGJhc2U2NEFycmF5QnVmZmVyKGFycmF5QnVmZmVyKSB7XG5cdFx0bGV0IGJhc2U2NCAgICA9ICcnXG5cdFxuXHRcdGxldCBieXRlcyAgICAgICAgID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpXG5cdFx0bGV0IGJ5dGVMZW5ndGggICAgPSBieXRlcy5ieXRlTGVuZ3RoXG5cdFx0bGV0IGJ5dGVSZW1haW5kZXIgPSBieXRlTGVuZ3RoICUgM1xuXHRcdGxldCBtYWluTGVuZ3RoICAgID0gYnl0ZUxlbmd0aCAtIGJ5dGVSZW1haW5kZXJcblx0XG5cdFx0bGV0IGEsIGIsIGMsIGRcblx0XHRsZXQgY2h1bmtcblx0XHQvL3Rocm93IFwid2hvJ3MgdXNpbmcgdGhpcz9cIlxuXHRcdC8vY29uc29sZS5sb2coIFwiYnVmZmVyLi5cIiwgYXJyYXlCdWZmZXIgKVxuXHRcdC8vIE1haW4gbG9vcCBkZWFscyB3aXRoIGJ5dGVzIGluIGNodW5rcyBvZiAzXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBtYWluTGVuZ3RoOyBpID0gaSArIDMpIHtcblx0XHRcdC8vIENvbWJpbmUgdGhlIHRocmVlIGJ5dGVzIGludG8gYSBzaW5nbGUgaW50ZWdlclxuXHRcdFx0Y2h1bmsgPSAoYnl0ZXNbaV0gPDwgMTYpIHwgKGJ5dGVzW2kgKyAxXSA8PCA4KSB8IGJ5dGVzW2kgKyAyXVxuXG5cdFx0XHQvLyBVc2UgYml0bWFza3MgdG8gZXh0cmFjdCA2LWJpdCBzZWdtZW50cyBmcm9tIHRoZSB0cmlwbGV0XG5cdFx0XHRhID0gKGNodW5rICYgMTY1MTUwNzIpID4+IDE4IC8vIDE2NTE1MDcyID0gKDJeNiAtIDEpIDw8IDE4XG5cdFx0XHRiID0gKGNodW5rICYgMjU4MDQ4KSAgID4+IDEyIC8vIDI1ODA0OCAgID0gKDJeNiAtIDEpIDw8IDEyXG5cdFx0XHRjID0gKGNodW5rICYgNDAzMikgICAgID4+ICA2IC8vIDQwMzIgICAgID0gKDJeNiAtIDEpIDw8IDZcblx0XHRcdGQgPSBjaHVuayAmIDYzICAgICAgICAgICAgICAgLy8gNjMgICAgICAgPSAyXjYgLSAxXG5cdFxuXHRcdFx0Ly8gQ29udmVydCB0aGUgcmF3IGJpbmFyeSBzZWdtZW50cyB0byB0aGUgYXBwcm9wcmlhdGUgQVNDSUkgZW5jb2Rpbmdcblx0XHRcdGJhc2U2NCArPSBlbmNvZGluZ3NbYV0gKyBlbmNvZGluZ3NbYl0gKyBlbmNvZGluZ3NbY10gKyBlbmNvZGluZ3NbZF1cblx0XHR9XG5cdFxuXHQvLyBEZWFsIHdpdGggdGhlIHJlbWFpbmluZyBieXRlcyBhbmQgcGFkZGluZ1xuXHRcdGlmIChieXRlUmVtYWluZGVyID09IDEpIHtcblx0XHRcdGNodW5rID0gYnl0ZXNbbWFpbkxlbmd0aF1cblx0XHRcdGEgPSAoY2h1bmsgJiAyNTIpID4+IDIgLy8gMjUyID0gKDJeNiAtIDEpIDw8IDJcblx0XHRcdC8vIFNldCB0aGUgNCBsZWFzdCBzaWduaWZpY2FudCBiaXRzIHRvIHplcm9cblx0XHRcdGIgPSAoY2h1bmsgJiAzKSAgIDw8IDQgLy8gMyAgID0gMl4yIC0gMVxuXHRcdFx0YmFzZTY0ICs9IGVuY29kaW5nc1thXSArIGVuY29kaW5nc1tiXSArICc9PSdcblx0XHR9IGVsc2UgaWYgKGJ5dGVSZW1haW5kZXIgPT0gMikge1xuXHRcdFx0Y2h1bmsgPSAoYnl0ZXNbbWFpbkxlbmd0aF0gPDwgOCkgfCBieXRlc1ttYWluTGVuZ3RoICsgMV1cblx0XHRcdGEgPSAoY2h1bmsgJiA2NDUxMikgPj4gMTAgLy8gNjQ1MTIgPSAoMl42IC0gMSkgPDwgMTBcblx0XHRcdGIgPSAoY2h1bmsgJiAxMDA4KSAgPj4gIDQgLy8gMTAwOCAgPSAoMl42IC0gMSkgPDwgNFxuXHRcdFx0Ly8gU2V0IHRoZSAyIGxlYXN0IHNpZ25pZmljYW50IGJpdHMgdG8gemVyb1xuXHRcdFx0YyA9IChjaHVuayAmIDE1KSAgICA8PCAgMiAvLyAxNSAgICA9IDJeNCAtIDFcblx0XHRcdGJhc2U2NCArPSBlbmNvZGluZ3NbYV0gKyBlbmNvZGluZ3NbYl0gKyBlbmNvZGluZ3NbY10gKyAnPSdcblx0XHR9XG5cdFx0Ly9jb25zb2xlLmxvZyggXCJkdXA/XCIsIGJhc2U2NClcblx0XHRyZXR1cm4gYmFzZTY0XG5cdH1cblx0XG5cdFxuXHRmdW5jdGlvbiBEZWNvZGVCYXNlNjQoIGJ1ZiApIHtcdFxuXHRcdGxldCBvdXRzaXplO1xuXHRcdGlmKCBidWYubGVuZ3RoICUgNCA9PSAxIClcblx0XHRcdG91dHNpemUgPSAoKCgoYnVmLmxlbmd0aCArIDMpIC8gNCl8MCkgKiAzKSAtIDM7XG5cdFx0ZWxzZSBpZiggYnVmLmxlbmd0aCAlIDQgPT0gMiApXG5cdFx0XHRvdXRzaXplID0gKCgoKGJ1Zi5sZW5ndGggKyAzKSAvIDQpfDApICogMykgLSAyO1xuXHRcdGVsc2UgaWYoIGJ1Zi5sZW5ndGggJSA0ID09IDMgKVxuXHRcdFx0b3V0c2l6ZSA9ICgoKChidWYubGVuZ3RoICsgMykgLyA0KXwwKSAqIDMpIC0gMTtcblx0XHRlbHNlIGlmKCBkZWNvZGluZ3NbYnVmW2J1Zi5sZW5ndGggLSAzXV0gPT0gLTEgKVxuXHRcdFx0b3V0c2l6ZSA9ICgoKChidWYubGVuZ3RoICsgMykgLyA0KXwwKSAqIDMpIC0gMztcblx0XHRlbHNlIGlmKCBkZWNvZGluZ3NbYnVmW2J1Zi5sZW5ndGggLSAyXV0gPT0gLTEgKSBcblx0XHRcdG91dHNpemUgPSAoKCgoYnVmLmxlbmd0aCArIDMpIC8gNCl8MCkgKiAzKSAtIDI7XG5cdFx0ZWxzZSBpZiggZGVjb2RpbmdzW2J1ZltidWYubGVuZ3RoIC0gMV1dID09IC0xICkgXG5cdFx0XHRvdXRzaXplID0gKCgoKGJ1Zi5sZW5ndGggKyAzKSAvIDQpfDApICogMykgLSAxO1xuXHRcdGVsc2Vcblx0XHRcdG91dHNpemUgPSAoKCgoYnVmLmxlbmd0aCArIDMpIC8gNCl8MCkgKiAzKTtcblx0XHRsZXQgYWIgPSBuZXcgQXJyYXlCdWZmZXIoIG91dHNpemUgKTtcblx0XHRsZXQgb3V0ID0gbmV3IFVpbnQ4QXJyYXkoYWIpO1xuXG5cdFx0bGV0IG47XG5cdFx0bGV0IGwgPSAoYnVmLmxlbmd0aCszKT4+Mjtcblx0XHRmb3IoIG4gPSAwOyBuIDwgbDsgbisrICkge1xuXHRcdFx0bGV0IGluZGV4MCA9IGRlY29kaW5nc1tidWZbbio0XV07XG5cdFx0XHRsZXQgaW5kZXgxID0gKG4qNCsxKTxidWYubGVuZ3RoP2RlY29kaW5nc1tidWZbbio0KzFdXTotMTtcblx0XHRcdGxldCBpbmRleDIgPSAoaW5kZXgxPj0wKSAmJiAobio0KzIpPGJ1Zi5sZW5ndGg/ZGVjb2RpbmdzW2J1ZltuKjQrMl1dOi0xIHx8IC0xO1xuXHRcdFx0bGV0IGluZGV4MyA9IChpbmRleDI+PTApICYmIChuKjQrMyk8YnVmLmxlbmd0aD9kZWNvZGluZ3NbYnVmW24qNCszXV06LTEgfHwgLTE7XG5cdFx0XHRpZiggaW5kZXgxID49IDAgKVxuXHRcdFx0XHRvdXRbbiozKzBdID0gKCggaW5kZXgwICkgPDwgMiB8ICggaW5kZXgxICkgPj4gNCk7XG5cdFx0XHRpZiggaW5kZXgyID49IDAgKVxuXHRcdFx0XHRvdXRbbiozKzFdID0gKCggaW5kZXgxICkgPDwgNCB8ICggKCAoIGluZGV4MiApID4+IDIgKSAmIDB4MGYgKSk7XG5cdFx0XHRpZiggaW5kZXgzID49IDAgKVxuXHRcdFx0XHRvdXRbbiozKzJdID0gKCggaW5kZXgyICkgPDwgNiB8ICggKCBpbmRleDMgKSAmIDB4M0YgKSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFiO1xuXHR9XG5cdFxuLyoqXG4gKiBAcGFyYW0ge3Vua25vd259IG9iamVjdCBcbiAqIEBwYXJhbSB7KHRoaXM6IHVua25vd24sIGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bil9IFtyZXBsYWNlcl0gXG4gKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gW3NwYWNlXSBcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cdFxuSlNPWC5zdHJpbmdpZnkgPSBmdW5jdGlvbiggb2JqZWN0LCByZXBsYWNlciwgc3BhY2UgKSB7XG5cdGxldCBzdHJpbmdpZmllciA9IEpTT1guc3RyaW5naWZpZXIoKTtcblx0cmV0dXJuIHN0cmluZ2lmaWVyLnN0cmluZ2lmeSggb2JqZWN0LCByZXBsYWNlciwgc3BhY2UgKTtcbn1cblxuY29uc3Qgbm9uSWRlbnQgPSBcblsgWyAwLDI1NixbIDB4ZmZkOWZmLDB4ZmY2YWZmLDB4MWZjMDAsMHgzODAwMDAsMHgwLDB4ZmZmZmY4LDB4ZmZmZmZmLDB4N2ZmZmZmXSBdXG5dLm1hcCggcm93PT57IHJldHVybnsgZmlyc3RDaGFyIDogcm93WzBdLCBsYXN0Q2hhcjogcm93WzFdLCBiaXRzIDogcm93WzJdIH07IH0gKTtcblxuLy99IHByaXZhdGVpemVFdmVyeXRoaW5nKCk7XG5leHBvcnQge0pTT1h9XG5cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(rsc)/./node_modules/.pnpm/jsox@1.2.121/node_modules/jsox/lib/jsox.mjs\n");
|
|
|
|
/***/ })
|
|
|
|
};
|
|
; |