@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
201 lines • 21.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const string_fragments_1 = require("../string-fragments");
const token_1 = require("../token");
// Details for encoding and decoding Tokens into native types; should not be exported
exports.BEGIN_STRING_TOKEN_MARKER = '${Token[';
exports.BEGIN_LIST_TOKEN_MARKER = '#{Token[';
exports.END_TOKEN_MARKER = ']}';
exports.VALID_KEY_CHARS = 'a-zA-Z0-9:._-';
const QUOTED_BEGIN_STRING_TOKEN_MARKER = regexQuote(exports.BEGIN_STRING_TOKEN_MARKER);
const QUOTED_BEGIN_LIST_TOKEN_MARKER = regexQuote(exports.BEGIN_LIST_TOKEN_MARKER);
const QUOTED_END_TOKEN_MARKER = regexQuote(exports.END_TOKEN_MARKER);
const STRING_TOKEN_REGEX = new RegExp(`${QUOTED_BEGIN_STRING_TOKEN_MARKER}([${exports.VALID_KEY_CHARS}]+)${QUOTED_END_TOKEN_MARKER}`, 'g');
const LIST_TOKEN_REGEX = new RegExp(`${QUOTED_BEGIN_LIST_TOKEN_MARKER}([${exports.VALID_KEY_CHARS}]+)${QUOTED_END_TOKEN_MARKER}`, 'g');
/**
* A string with markers in it that can be resolved to external values
*/
class TokenString {
constructor(str, re) {
this.str = str;
this.re = re;
}
/**
* Returns a `TokenString` for this string.
*/
static forString(s) {
return new TokenString(s, STRING_TOKEN_REGEX);
}
/**
* Returns a `TokenString` for this string (must be the first string element of the list)
*/
static forListToken(s) {
return new TokenString(s, LIST_TOKEN_REGEX);
}
/**
* Split string on markers, substituting markers with Tokens
*/
split(lookup) {
const ret = new string_fragments_1.TokenizedStringFragments();
let rest = 0;
this.re.lastIndex = 0; // Reset
let m = this.re.exec(this.str);
while (m) {
if (m.index > rest) {
ret.addLiteral(this.str.substring(rest, m.index));
}
ret.addToken(lookup(m[1]));
rest = this.re.lastIndex;
m = this.re.exec(this.str);
}
if (rest < this.str.length) {
ret.addLiteral(this.str.substring(rest));
}
return ret;
}
/**
* Indicates if this string includes tokens.
*/
test() {
this.re.lastIndex = 0; // Reset
return this.re.test(this.str);
}
}
exports.TokenString = TokenString;
/**
* Quote a string for use in a regex
*/
function regexQuote(s) {
return s.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
}
exports.regexQuote = regexQuote;
/**
* Concatenator that disregards the input
*
* Can be used when traversing the tokens is important, but the
* result isn't.
*/
class NullConcat {
join(_left, _right) {
return undefined;
}
}
exports.NullConcat = NullConcat;
function containsListTokenElement(xs) {
return xs.some(x => typeof (x) === 'string' && TokenString.forListToken(x).test());
}
exports.containsListTokenElement = containsListTokenElement;
/**
* Returns true if obj is a token (i.e. has the resolve() method or is a string
* that includes token markers), or it's a listifictaion of a Token string.
*
* @param obj The object to test.
*/
function unresolved(obj) {
if (typeof (obj) === 'string') {
return TokenString.forString(obj).test();
}
else if (typeof obj === 'number') {
return extractTokenDouble(obj) !== undefined;
}
else if (Array.isArray(obj) && obj.length === 1) {
return typeof (obj[0]) === 'string' && TokenString.forListToken(obj[0]).test();
}
else {
return token_1.isResolvableObject(obj);
}
}
exports.unresolved = unresolved;
/**
* Bit pattern in the top 16 bits of a double to indicate a Token
*
* An IEEE double in LE memory order looks like this (grouped
* into octets, then grouped into 32-bit words):
*
* mmmmmmmm.mmmmmmmm.mmmmmmmm.mmmmmmmm | mmmmmmmm.mmmmmmmm.EEEEmmmm.sEEEEEEE
*
* - m: mantissa (52 bits)
* - E: exponent (11 bits)
* - s: sign (1 bit)
*
* We put the following marker into the top 16 bits (exponent and sign), and
* use the mantissa part to encode the token index. To save some bit twiddling
* we use all top 16 bits for the tag. That loses us 4 mantissa bits to store
* information in but we still have 48, which is going to be plenty for any
* number of tokens to be created during the lifetime of any CDK application.
*
* Can't have all bits set because that makes a NaN, so unset the least
* significant exponent bit.
*
* Currently not supporting BE architectures.
*/
// tslint:disable-next-line:no-bitwise
const DOUBLE_TOKEN_MARKER_BITS = 0xFBFF << 16;
/**
* Highest encodable number
*/
const MAX_ENCODABLE_INTEGER = Math.pow(2, 48) - 1;
/**
* Get 2^32 as a number, so we can do multiplication and div instead of bit shifting
*
* Necessary because in JavaScript, bit operations implicitly convert
* to int32 and we need them to work on "int64"s.
*
* So instead of x >> 32, we do Math.floor(x / 2^32), and vice versa.
*/
const BITS32 = Math.pow(2, 32);
/**
* Return a special Double value that encodes the given nonnegative integer
*
* We use this to encode Token ordinals.
*/
function createTokenDouble(x) {
if (Math.floor(x) !== x || x < 0) {
throw new Error('Can only encode positive integers');
}
if (x > MAX_ENCODABLE_INTEGER) {
throw new Error(`Got an index too large to encode: ${x}`);
}
const buf = new ArrayBuffer(8);
const ints = new Uint32Array(buf);
// tslint:disable:no-bitwise
ints[0] = x & 0x0000FFFFFFFF; // Bottom 32 bits of number
// This needs an "x >> 32" but that will make it a 32-bit number instead
// of a 64-bit number.
ints[1] = (shr32(x) & 0xFFFF) | DOUBLE_TOKEN_MARKER_BITS; // Top 16 bits of number and the mask
// tslint:enable:no-bitwise
return (new Float64Array(buf))[0];
}
exports.createTokenDouble = createTokenDouble;
/**
* Shift a 64-bit int right 32 bits
*/
function shr32(x) {
return Math.floor(x / BITS32);
}
/**
* Shift a 64-bit left 32 bits
*/
function shl32(x) {
return x * BITS32;
}
/**
* Extract the encoded integer out of the special Double value
*
* Returns undefined if the float is a not an encoded token.
*/
function extractTokenDouble(encoded) {
const buf = new ArrayBuffer(8);
(new Float64Array(buf))[0] = encoded;
const ints = new Uint32Array(buf);
// tslint:disable:no-bitwise
if ((ints[1] & 0xFFFF0000) !== DOUBLE_TOKEN_MARKER_BITS) {
return undefined;
}
// Must use + instead of | here (bitwise operations
// will force 32-bits integer arithmetic, + will not).
return ints[0] + shl32(ints[1] & 0xFFFF);
// tslint:enable:no-bitwise
}
exports.extractTokenDouble = extractTokenDouble;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5jb2RpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJlbmNvZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUNBLDBEQUErRDtBQUMvRCxvQ0FBOEM7QUFFOUMscUZBQXFGO0FBRXhFLFFBQUEseUJBQXlCLEdBQUcsVUFBVSxDQUFDO0FBQ3ZDLFFBQUEsdUJBQXVCLEdBQUcsVUFBVSxDQUFDO0FBQ3JDLFFBQUEsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBRXhCLFFBQUEsZUFBZSxHQUFHLGVBQWUsQ0FBQztBQUUvQyxNQUFNLGdDQUFnQyxHQUFHLFVBQVUsQ0FBQyxpQ0FBeUIsQ0FBQyxDQUFDO0FBQy9FLE1BQU0sOEJBQThCLEdBQUcsVUFBVSxDQUFDLCtCQUF1QixDQUFDLENBQUM7QUFDM0UsTUFBTSx1QkFBdUIsR0FBRyxVQUFVLENBQUMsd0JBQWdCLENBQUMsQ0FBQztBQUU3RCxNQUFNLGtCQUFrQixHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsZ0NBQWdDLEtBQUssdUJBQWUsTUFBTSx1QkFBdUIsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ25JLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyw4QkFBOEIsS0FBSyx1QkFBZSxNQUFNLHVCQUF1QixFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFFL0g7O0dBRUc7QUFDSCxNQUFhLFdBQVc7SUFldEIsWUFBNkIsR0FBVyxFQUFtQixFQUFVO1FBQXhDLFFBQUcsR0FBSCxHQUFHLENBQVE7UUFBbUIsT0FBRSxHQUFGLEVBQUUsQ0FBUTtJQUNyRSxDQUFDO0lBZkQ7O09BRUc7SUFDSSxNQUFNLENBQUMsU0FBUyxDQUFDLENBQVM7UUFDL0IsT0FBTyxJQUFJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsWUFBWSxDQUFDLENBQVM7UUFDbEMsT0FBTyxJQUFJLFdBQVcs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d0JBQXdCLENBQUMsQ0FBQyxxQ0FBcUM7SUFDL0YsMkJBQTJCO0lBRTNCLE9BQU8sQ0FBQyxJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BDLENBQUM7QUFwQkQsOENBb0JDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLEtBQUssQ0FBQyxDQUFTO0lBQ3RCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDaEMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxLQUFLLENBQUMsQ0FBUztJQUN0QixPQUFPLENBQUMsR0FBRyxNQUFNLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxPQUFlO0lBQ2hELE1BQU0sR0FBRyxHQUFHLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLENBQUMsSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUM7SUFFckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFbEMsNEJBQTRCO0lBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLEtBQUssd0JBQXdCLEVBQUU7UUFDdkQsT0FBTyxTQUFTLENBQUM7S0FDbEI7SUFFRCxtREFBbUQ7SUFDbkQsc0RBQXNEO0lBQ3RELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDekMsMkJBQTJCO0FBQzdCLENBQUM7QUFmRCxnREFlQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElGcmFnbWVudENvbmNhdGVuYXRvciwgSVJlc29sdmFibGUgfSBmcm9tIFwiLi4vcmVzb2x2YWJsZVwiO1xuaW1wb3J0IHsgVG9rZW5pemVkU3RyaW5nRnJhZ21lbnRzIH0gZnJvbSBcIi4uL3N0cmluZy1mcmFnbWVudHNcIjtcbmltcG9ydCB7IGlzUmVzb2x2YWJsZU9iamVjdCB9IGZyb20gXCIuLi90b2tlblwiO1xuXG4vLyBEZXRhaWxzIGZvciBlbmNvZGluZyBhbmQgZGVjb2RpbmcgVG9rZW5zIGludG8gbmF0aXZlIHR5cGVzOyBzaG91bGQgbm90IGJlIGV4cG9ydGVkXG5cbmV4cG9ydCBjb25zdCBCRUdJTl9TVFJJTkdfVE9LRU5fTUFSS0VSID0gJyR7VG9rZW5bJztcbmV4cG9ydCBjb25zdCBCRUdJTl9MSVNUX1RPS0VOX01BUktFUiA9ICcje1Rva2VuWyc7XG5leHBvcnQgY29uc3QgRU5EX1RPS0VOX01BUktFUiA9ICddfSc7XG5cbmV4cG9ydCBjb25zdCBWQUxJRF9LRVlfQ0hBUlMgPSAnYS16QS1aMC05Oi5fLSc7XG5cbmNvbnN0IFFVT1RFRF9CRUdJTl9TVFJJTkdfVE9LRU5fTUFSS0VSID0gcmVnZXhRdW90ZShCRUdJTl9TVFJJTkdfVE9LRU5fTUFSS0VSKTtcbmNvbnN0IFFVT1RFRF9CRUdJTl9MSVNUX1RPS0VOX01BUktFUiA9IHJlZ2V4UXVvdGUoQkVHSU5fTElTVF9UT0tFTl9NQVJLRVIpO1xuY29uc3QgUVVPVEVEX0VORF9UT0tFTl9NQVJLRVIgPSByZWdleFF1b3RlKEVORF9UT0tFTl9NQVJLRVIpO1xuXG5jb25zdCBTVFJJTkdfVE9LRU5fUkVHRVggPSBuZXcgUmVnRXhwKGAke1FVT1RFRF9CRUdJTl9TVFJJTkdfVE9LRU5fTUFSS0VSfShbJHtWQUxJRF9LRVlfQ0hBUlN9XSspJHtRVU9URURfRU5EX1RPS0VOX01BUktFUn1gLCAnZycpO1xuY29uc3QgTElTVF9UT0tFTl9SRUdFWCA9IG5ldyBSZWdFeHAoYCR7UVVPVEVEX0JFR0lOX0xJU1RfVE9LRU5fTUFSS0VSfShbJHtWQUxJRF9LRVlfQ0hBUlN9XSspJHtRVU9URURfRU5EX1RPS0VOX01BUktFUn1gLCAnZycpO1xuXG4vKipcbiAqIEEgc3RyaW5nIHdpdGggbWFya2VycyBpbiBpdCB0aGF0IGNhbiBiZSByZXNvbHZlZCB0byBleHRlcm5hbCB2YWx1ZXNcbiAqL1xuZXhwb3J0IGNsYXNzIFRva2VuU3RyaW5nIHtcbiAgLyoqXG4gICAqIFJldHVybnMgYSBgVG9rZW5TdHJpbmdgIGZvciB0aGlzIHN0cmluZy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZm9yU3RyaW5nKHM6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgVG9rZW5TdHJpbmcocywgU1RSSU5HX1RPS0VOX1JFR0VYKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgYFRva2VuU3RyaW5nYCBmb3IgdGhpcyBzdHJpbmcgKG11c3QgYmUgdGhlIGZpcnN0IHN0cmluZyBlbGVtZW50IG9mIHRoZSBsaXN0KVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmb3JMaXN0VG9rZW4oczogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBUb2tlblN0cmluZyhzLCBMSVNUX1RPS0VOX1JFR0VYKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgc3RyOiBzdHJpbmcsIHByaXZhdGUgcmVhZG9ubHkgcmU6IFJlZ0V4cCkge1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0IHN0cmluZyBvbiBtYXJrZXJzLCBzdWJzdGl0dXRpbmcgbWFya2VycyB3aXRoIFRva2Vuc1xuICAgKi9cbiAgcHVibGljIHNwbGl0KGxvb2t1cDogKGlkOiBzdHJpbmcpID0+IElSZXNvbHZhYmxlKTogVG9rZW5pemVkU3RyaW5nRnJhZ21lbnRzIHtcbiAgICBjb25zdCByZXQgPSBuZXcgVG9rZW5pemVkU3RyaW5nRnJhZ21lbnRzKCk7XG5cbiAgICBsZXQgcmVzdCA9IDA7XG4gICAgdGhpcy5yZS5sYXN0SW5kZXggPSAwOyAvLyBSZXNldFxuICAgIGxldCBtID0gdGhpcy5yZS5leGVjKHRoaXMuc3RyKTtcbiAgICB3aGlsZSAobSkge1xuICAgICAgaWYgKG0uaW5kZXggPiByZXN0KSB7XG4gICAgICAgIHJldC5hZGRMaXRlcmFsKHRoaXMuc3RyLnN1YnN0cmluZyhyZXN0LCBtLmluZGV4KSk7XG4gICAgICB9XG5cbiAgICAgIHJldC5hZGRUb2tlbihsb29rdXAobVsxXSkpO1xuXG4gICAgICByZXN0ID0gdGhpcy5yZS5sYXN0SW5kZXg7XG4gICAgICBtID0gdGhpcy5yZS5leGVjKHRoaXMuc3RyKTtcbiAgICB9XG5cbiAgICBpZiAocmVzdCA8IHRoaXMuc3RyLmxlbmd0aCkge1xuICAgICAgcmV0LmFkZExpdGVyYWwodGhpcy5zdHIuc3Vic3RyaW5nKHJlc3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiB0aGlzIHN0cmluZyBpbmNsdWRlcyB0b2tlbnMuXG4gICAqL1xuICBwdWJsaWMgdGVzdCgpOiBib29sZWFuIHtcbiAgICB0aGlzLnJlLmxhc3RJbmRleCA9IDA7IC8vIFJlc2V0XG4gICAgcmV0dXJuIHRoaXMucmUudGVzdCh0aGlzLnN0cik7XG4gIH1cbn1cblxuLyoqXG4gKiBRdW90ZSBhIHN0cmluZyBmb3IgdXNlIGluIGEgcmVnZXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2V4UXVvdGUoczogc3RyaW5nKSB7XG4gIHJldHVybiBzLnJlcGxhY2UoL1suPyorXiRbXFxdXFxcXCgpe318LV0vZywgXCJcXFxcJCZcIik7XG59XG5cbi8qKlxuICogQ29uY2F0ZW5hdG9yIHRoYXQgZGlzcmVnYXJkcyB0aGUgaW5wdXRcbiAqXG4gKiBDYW4gYmUgdXNlZCB3aGVuIHRyYXZlcnNpbmcgdGhlIHRva2VucyBpcyBpbXBvcnRhbnQsIGJ1dCB0aGVcbiAqIHJlc3VsdCBpc24ndC5cbiAqL1xuZXhwb3J0IGNsYXNzIE51bGxDb25jYXQgaW1wbGVtZW50cyBJRnJhZ21lbnRDb25jYXRlbmF0b3Ige1xuICBwdWJsaWMgam9pbihfbGVmdDogYW55IHwgdW5kZWZpbmVkLCBfcmlnaHQ6IGFueSB8IHVuZGVmaW5lZCk6IGFueSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNMaXN0VG9rZW5FbGVtZW50KHhzOiBhbnlbXSkge1xuICByZXR1cm4geHMuc29tZSh4ID0+IHR5cGVvZih4KSA9PT0gJ3N0cmluZycgJiYgVG9rZW5TdHJpbmcuZm9yTGlzdFRva2VuKHgpLnRlc3QoKSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIG9iaiBpcyBhIHRva2VuIChpLmUuIGhhcyB0aGUgcmVzb2x2ZSgpIG1ldGhvZCBvciBpcyBhIHN0cmluZ1xuICogdGhhdCBpbmNsdWRlcyB0b2tlbiBtYXJrZXJzKSwgb3IgaXQncyBhIGxpc3RpZmljdGFpb24gb2YgYSBUb2tlbiBzdHJpbmcuXG4gKlxuICogQHBhcmFtIG9iaiBUaGUgb2JqZWN0IHRvIHRlc3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bnJlc29sdmVkKG9iajogYW55KTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2Yob2JqKSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gVG9rZW5TdHJpbmcuZm9yU3RyaW5nKG9iaikudGVzdCgpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBvYmogPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGV4dHJhY3RUb2tlbkRvdWJsZShvYmopICE9PSB1bmRlZmluZWQ7XG4gIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShvYmopICYmIG9iai5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gdHlwZW9mKG9ialswXSkgPT09ICdzdHJpbmcnICYmIFRva2VuU3RyaW5nLmZvckxpc3RUb2tlbihvYmpbMF0pLnRlc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaXNSZXNvbHZhYmxlT2JqZWN0KG9iaik7XG4gIH1cbn1cblxuLyoqXG4gKiBCaXQgcGF0dGVybiBpbiB0aGUgdG9wIDE2IGJpdHMgb2YgYSBkb3VibGUgdG8gaW5kaWNhdGUgYSBUb2tlblxuICpcbiAqIEFuIElFRUUgZG91YmxlIGluIExFIG1lbW9yeSBvcmRlciBsb29rcyBsaWtlIHRoaXMgKGdyb3VwZWRcbiAqIGludG8gb2N0ZXRzLCB0aGVuIGdyb3VwZWQgaW50byAzMi1iaXQgd29yZHMpOlxuICpcbiAqIG1tbW1tbW1tLm1tbW1tbW1tLm1tbW1tbW1tLm1tbW1tbW1tIHwgbW1tbW1tbW0ubW1tbW1tbW0uRUVFRW1tbW0uc0VFRUVFRUVcbiAqXG4gKiAtIG06IG1hbnRpc3NhICg1MiBiaXRzKVxuICogLSBFOiBleHBvbmVudCAoMTEgYml0cylcbiAqIC0gczogc2lnbiAoMSBiaXQpXG4gKlxuICogV2UgcHV0IHRoZSBmb2xsb3dpbmcgbWFya2VyIGludG8gdGhlIHRvcCAxNiBiaXRzIChleHBvbmVudCBhbmQgc2lnbiksIGFuZFxuICogdXNlIHRoZSBtYW50aXNzYSBwYXJ0IHRvIGVuY29kZSB0aGUgdG9rZW4gaW5kZXguIFRvIHNhdmUgc29tZSBiaXQgdHdpZGRsaW5nXG4gKiB3ZSB1c2UgYWxsIHRvcCAxNiBiaXRzIGZvciB0aGUgdGFnLiBUaGF0IGxvc2VzIHVzIDQgbWFudGlzc2EgYml0cyB0byBzdG9yZVxuICogaW5mb3JtYXRpb24gaW4gYnV0IHdlIHN0aWxsIGhhdmUgNDgsIHdoaWNoIGlzIGdvaW5nIHRvIGJlIHBsZW50eSBmb3IgYW55XG4gKiBudW1iZXIgb2YgdG9rZW5zIHRvIGJlIGNyZWF0ZWQgZHVyaW5nIHRoZSBsaWZldGltZSBvZiBhbnkgQ0RLIGFwcGxpY2F0aW9uLlxuICpcbiAqIENhbid0IGhhdmUgYWxsIGJpdHMgc2V0IGJlY2F1c2UgdGhhdCBtYWtlcyBhIE5hTiwgc28gdW5zZXQgdGhlIGxlYXN0XG4gKiBzaWduaWZpY2FudCBleHBvbmVudCBiaXQuXG4gKlxuICogQ3VycmVudGx5IG5vdCBzdXBwb3J0aW5nIEJFIGFyY2hpdGVjdHVyZXMuXG4gKi9cbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1iaXR3aXNlXG5jb25zdCBET1VCTEVfVE9LRU5fTUFSS0VSX0JJVFMgPSAweEZCRkYgPDwgMTY7XG5cbi8qKlxuICogSGlnaGVzdCBlbmNvZGFibGUgbnVtYmVyXG4gKi9cbmNvbnN0IE1BWF9FTkNPREFCTEVfSU5URUdFUiA9IE1hdGgucG93KDIsIDQ4KSAtIDE7XG5cbi8qKlxuICogR2V0IDJeMzIgYXMgYSBudW1iZXIsIHNvIHdlIGNhbiBkbyBtdWx0aXBsaWNhdGlvbiBhbmQgZGl2IGluc3RlYWQgb2YgYml0IHNoaWZ0aW5nXG4gKlxuICogTmVjZXNzYXJ5IGJlY2F1c2UgaW4gSmF2YVNjcmlwdCwgYml0IG9wZXJhdGlvbnMgaW1wbGljaXRseSBjb252ZXJ0XG4gKiB0byBpbnQzMiBhbmQgd2UgbmVlZCB0aGVtIHRvIHdvcmsgb24gXCJpbnQ2NFwicy5cbiAqXG4gKiBTbyBpbnN0ZWFkIG9mIHggPj4gMzIsIHdlIGRvIE1hdGguZmxvb3IoeCAvIDJeMzIpLCBhbmQgdmljZSB2ZXJzYS5cbiAqL1xuY29uc3QgQklUUzMyID0gTWF0aC5wb3coMiwgMzIpO1xuXG4vKipcbiAqIFJldHVybiBhIHNwZWNpYWwgRG91YmxlIHZhbHVlIHRoYXQgZW5jb2RlcyB0aGUgZ2l2ZW4gbm9ubmVnYXRpdmUgaW50ZWdlclxuICpcbiAqIFdlIHVzZSB0aGlzIHRvIGVuY29kZSBUb2tlbiBvcmRpbmFscy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVRva2VuRG91YmxlKHg6IG51bWJlcikge1xuICBpZiAoTWF0aC5mbG9vcih4KSAhPT0geCB8fCB4IDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG9ubHkgZW5jb2RlIHBvc2l0aXZlIGludGVnZXJzJyk7XG4gIH1cbiAgaWYgKHggPiBNQVhfRU5DT0RBQkxFX0lOVEVHRVIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEdvdCBhbiBpbmRleCB0b28gbGFyZ2UgdG8gZW5jb2RlOiAke3h9YCk7XG4gIH1cblxuICBjb25zdCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gIGNvbnN0IGludHMgPSBuZXcgVWludDMyQXJyYXkoYnVmKTtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZTpuby1iaXR3aXNlXG4gIGludHNbMF0gPSAgeCAmIDB4MDAwMEZGRkZGRkZGOyAvLyBCb3R0b20gMzIgYml0cyBvZiBudW1iZXJcblxuICAvLyBUaGlzIG5lZWRzIGFuIFwieCA+PiAzMlwiIGJ1dCB0aGF0IHdpbGwgbWFrZSBpdCBhIDMyLWJpdCBudW1iZXIgaW5zdGVhZFxuICAvLyBvZiBhIDY0LWJpdCBudW1iZXIuXG4gIGludHNbMV0gPSAoc2hyMzIoeCkgJiAweEZGRkYpIHwgRE9VQkxFX1RPS0VOX01BUktFUl9CSVRTOyAvLyBUb3AgMTYgYml0cyBvZiBudW1iZXIgYW5kIHRoZSBtYXNrXG4gIC8vIHRzbGludDplbmFibGU6bm8tYml0d2lzZVxuXG4gIHJldHVybiAobmV3IEZsb2F0NjRBcnJheShidWYpKVswXTtcbn1cblxuLyoqXG4gKiBTaGlmdCBhIDY0LWJpdCBpbnQgcmlnaHQgMzIgYml0c1xuICovXG5mdW5jdGlvbiBzaHIzMih4OiBudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguZmxvb3IoeCAvIEJJVFMzMik7XG59XG5cbi8qKlxuICogU2hpZnQgYSA2NC1iaXQgbGVmdCAzMiBiaXRzXG4gKi9cbmZ1bmN0aW9uIHNobDMyKHg6IG51bWJlcikge1xuICByZXR1cm4geCAqIEJJVFMzMjtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHRoZSBlbmNvZGVkIGludGVnZXIgb3V0IG9mIHRoZSBzcGVjaWFsIERvdWJsZSB2YWx1ZVxuICpcbiAqIFJldHVybnMgdW5kZWZpbmVkIGlmIHRoZSBmbG9hdCBpcyBhIG5vdCBhbiBlbmNvZGVkIHRva2VuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFRva2VuRG91YmxlKGVuY29kZWQ6IG51bWJlcik6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgKG5ldyBGbG9hdDY0QXJyYXkoYnVmKSlbMF0gPSBlbmNvZGVkO1xuXG4gIGNvbnN0IGludHMgPSBuZXcgVWludDMyQXJyYXkoYnVmKTtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZTpuby1iaXR3aXNlXG4gIGlmICgoaW50c1sxXSAmIDB4RkZGRjAwMDApICE9PSBET1VCTEVfVE9LRU5fTUFSS0VSX0JJVFMpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gTXVzdCB1c2UgKyBpbnN0ZWFkIG9mIHwgaGVyZSAoYml0d2lzZSBvcGVyYXRpb25zXG4gIC8vIHdpbGwgZm9yY2UgMzItYml0cyBpbnRlZ2VyIGFyaXRobWV0aWMsICsgd2lsbCBub3QpLlxuICByZXR1cm4gaW50c1swXSArIHNobDMyKGludHNbMV0gJiAweEZGRkYpO1xuICAvLyB0c2xpbnQ6ZW5hYmxlOm5vLWJpdHdpc2Vcbn1cbiJdfQ==