UNPKG

@magic-xpa/utils

Version:

magic utils package

723 lines 71.5 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /// <summary>JPN: DBCS support /// Utility Class for String /// In this class, considering DBCS, strings are counted by the number /// of bytes, not the number of characters. /// </summary> /// <author> Toshiro Nakayoshi (MSJ) </author> import { Encoding, StringBuilder } from "@magic-xpa/mscorelib"; export class UtilStrByteMode { /// <summary> Checks the environment whether it is running on DBCS environment /// Returns true if the language code for the current default Locale is /// DBCS language (in non-Unicode encoding). /// /// </summary> /// <returns> true if DBCS, or false if SBCS /// </returns> /** * @return {?} */ static isLocaleDefLangDBCS() { return UtilStrByteMode._bLocaleDefLangJPN || UtilStrByteMode._bLocaleDefLangCHN || UtilStrByteMode._bLocaleDefLangKOR; } /// <summary> Checks whether the language code for the current default Locale /// is JAPANESE. /// /// </summary> /// <returns> true if JAPANESE, or false if not /// </returns> /** * @return {?} */ static isLocaleDefLangJPN() { return UtilStrByteMode._bLocaleDefLangJPN; } /// <summary> Checks whether the language code for the current default Locale /// is KOREAN. /// /// </summary> /// <returns> true if KOREAN, or false if not /// </returns> /** * @return {?} */ static isLocaleDefLangKOR() { return UtilStrByteMode._bLocaleDefLangKOR; } /** * @param {?} c * @return {?} */ static isKoreanCharacter(c) { return (44032 <= /*'가'*/ c && c <= 55203 /*'힣'*/) || (4352 <= /*'ᄀ'*/ c && c <= 4607 /*'ᇿ'*/) || (12592 <= /*'㄰'*/ c && c <= 12687 /*'㆏'*/) || (43360 <= /*'ꥠ'*/ c && c <= 43391 /*'꥿'*/) || (55216 <= /*'ힰ'*/ c && c <= 55295 /*'퟿'*/); } /// <summary> Length of String /// Returns the number of bytes (in default encoding). /// /// </summary> /// <param name="strVal:">string (in Unicode) /// </param> /// <returns> the number of bytes (in default encoding) /// /// Example: lenB("abXYc") /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// 7. /// </returns> /** * @param {?} strVal * @return {?} */ static lenB(strVal) { // convert to byte[] by default-encoding return UtilStrByteMode.Encoding.GetByteCount(strVal); } /// <summary> Substring of String /// Extracts a specified number of characters (a substring) from a string. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strVal:">string (in Unicode) /// </param> /// <param name="ofs:">starting position (byte) of the substring /// </param> /// <param name="len:">number of bytes to be extracted (i.e. bytes of substring) /// </param> /// <returns> substring /// /// Example: midB("abXYc", 2, 4) /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// "bX ". /// </returns> /** * @param {?} strVal * @param {?} ofs * @param {?} len * @return {?} */ static midB(strVal, ofs, len) { /** @type {?} */ let intValidMaxIndex = -1; // param #1 of substring /** @type {?} */ let intValidMinIndex = -1; // param #2 of substring /** @type {?} */ let bHeadSpace = false; // flag: need to add space /** @type {?} */ let bEndSpace = false; // flag: need to add space /** @type {?} */ let strRet; // check and modify ofs & len if (len <= 0) return ""; if (ofs <= 0) { ofs = 0; intValidMinIndex = 0; bHeadSpace = false; } /** @type {?} */ let intByteLength = UtilStrByteMode.lenB(strVal); if (intByteLength < ofs) return ""; /** @type {?} */ let LenMax = intByteLength - ofs; if (LenMax < len) len = LenMax; // set MinIndex and MaxIndex for substring intByteLength = 0; for (let intIndex = 0; intIndex < strVal.length; intIndex = intIndex + 1) { /** @type {?} */ let s = strVal.substr(intIndex, 1); intByteLength = intByteLength + UtilStrByteMode.Encoding.GetByteCount(s); if (intValidMinIndex === -1) { if (intByteLength === ofs) { intValidMinIndex = intIndex + 1; bHeadSpace = false; } else if (intByteLength > ofs) { intValidMinIndex = intIndex + 1; bHeadSpace = true; } } if (intValidMaxIndex === -1) { if (intByteLength === ofs + len) { intValidMaxIndex = intIndex; bEndSpace = false; break; } else if (intByteLength > ofs + len) { intValidMaxIndex = intIndex - 1; bEndSpace = true; break; } } } // prepare for substring /** @type {?} */ let strbufAddingBuf = new StringBuilder(len); // execute Mid if (bHeadSpace) { strbufAddingBuf.Append(' '); } if (intValidMinIndex <= intValidMaxIndex) { strbufAddingBuf.Append(strVal.substr(intValidMinIndex, intValidMaxIndex + 1 - intValidMinIndex)); } if (bEndSpace) { strbufAddingBuf.Append(' '); } strRet = strbufAddingBuf.ToString(); strbufAddingBuf = null; return strRet; } /// <summary> Get Characters from Left of String /// Returns a specified number of bytes from the left side of a string. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strVal:">string (in Unicode) /// </param> /// <param name="len:">number of bytes to be retured /// </param> /// <returns> output string /// /// Example: leftB("abXYc", 4) /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// "abX". /// </returns> /** * @param {?} strVal * @param {?} len * @return {?} */ static leftB(strVal, len) { return UtilStrByteMode.midB(strVal, 0, len); } /// <summary> Get Characters from Right of String /// Returns a specified number of bytes from the right side of a string. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strVal:">string (in Unicode) /// </param> /// <param name="len:">number of bytes to be retured /// </param> /// <returns> output string /// /// Example: rightB("abXYc", 4) /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// " Yc". /// </returns> /** * @param {?} strVal * @param {?} len * @return {?} */ static rightB(strVal, len) { /** @type {?} */ let byteFldsValLen = UtilStrByteMode.lenB(strVal); if (len < 0) { len = 0; } /** @type {?} */ let ofs = byteFldsValLen - len; if (ofs < 0) { ofs = 0; } return UtilStrByteMode.midB(strVal, ofs, len); } /// <summary> Insert String /// Inserts one string into another. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strTarget:">A string that represents the target string. /// </param> /// <param name="strSource:">A string that represents the source string. /// </param> /// <param name="ofs:">A number that represents the starting position (byte) in /// the target. /// </param> /// <param name="len:">A number that represents the number of bytes from the /// source that will be inserted into the target. /// </param> /// <returns> output string /// /// Example: insB("abXYc", "de", 4, 1) /// Where 'a', 'b', 'c', 'd' and 'e' are SBCS, and 'X' and 'Y' are DBCS, /// it returns "ab d Yc". /// </returns> /** * @param {?} strTarget * @param {?} strSource * @param {?} ofs * @param {?} len * @return {?} */ static insB(strTarget, strSource, ofs, len) { if (ofs < 0) { ofs = 0; } else { if (ofs >= 1) { ofs = ofs - 1; } } if (len < 0) { len = 0; } /** @type {?} */ let intTargetLenB = UtilStrByteMode.lenB(strTarget); /** @type {?} */ let intSourceLenB = UtilStrByteMode.lenB(strSource); /** @type {?} */ let strbufRetVal = new StringBuilder(ofs + len); strbufRetVal.Append(UtilStrByteMode.leftB(strTarget, ofs)); for (let intAddSpaceLen = ofs - intTargetLenB; intAddSpaceLen > 0; intAddSpaceLen = intAddSpaceLen - 1) { strbufRetVal.Append(' '); } strbufRetVal.Append(UtilStrByteMode.leftB(strSource, len)); for (let i = len - intSourceLenB; i > 0; i = i - 1) { strbufRetVal.Append(' '); } strbufRetVal.Append(UtilStrByteMode.rightB(strTarget, intTargetLenB - ofs)); return strbufRetVal.ToString(); } /// <summary> Delete Characters /// Delete characters from a string. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strVal:">string (in Unicode) /// </param> /// <param name="ofs:">The position (byte) of the first character to be deleted. /// </param> /// <param name="len:">The number of characters to be deleted, beginning with /// position start and proceeding rightward. /// </param> /// <returns> output string /// /// Example: delB("abXYc", 2, 4) /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// "a c". /// </returns> /** * @param {?} strVal * @param {?} ofs * @param {?} len * @return {?} */ static delB(strVal, ofs, len) { if (ofs < 0) { ofs = 0; } else { if (ofs >= 1) { ofs = ofs - 1; } } /** @type {?} */ let intValLenB = UtilStrByteMode.lenB(strVal); if (ofs + len > intValLenB) { len = intValLenB - ofs; } /** @type {?} */ let strRet; if (len <= 0) { strRet = strVal; } else { /** @type {?} */ let intRightSideLenB = intValLenB - ofs - len; if (intRightSideLenB < 0) { strRet = strVal; } else { /** @type {?} */ let strbufRetVal = new StringBuilder(ofs + intRightSideLenB); strbufRetVal.Append(UtilStrByteMode.leftB(strVal, ofs)); strbufRetVal.Append(UtilStrByteMode.rightB(strVal, intRightSideLenB)); strRet = strbufRetVal.ToString(); } } return strRet; } /// <summary> In-String Search /// Returns a number that represents the first position (byte) of a /// substring within a string. /// /// </summary> /// <param name="strTarget:">string (in Unicode) /// </param> /// <param name="strSearch:">string which will be the search argument in string /// </param> /// <returns> number, 0 if not found /// /// Example: instrB("abXYc", "Y") /// Where 'a', 'b' and 'c' are SBCS, and 'X' and 'Y' are DBCS, it returns /// 5. /// </returns> /** * @param {?} strTarget * @param {?} strSearch * @return {?} */ static instrB(strTarget, strSearch) { if (strSearch.length === 0) { // nothing to look for return 0; } /** @type {?} */ let ofs = strTarget.indexOf(strSearch); if (ofs < 0) { // not found return 0; } return UtilStrByteMode.lenB(strTarget.substr(0, ofs)) + 1; } /// <summary> Replace Substring Within a String (Byte Mode) /// Replaces a substring within a string with another substring. /// If a DBCS character is divided in two, it will be replace to a space. /// /// </summary> /// <param name="strTarget:">target string where the replacement will take place. /// </param> /// <param name="strOrigin:">string that provides the substring to be copied to /// target. /// </param> /// <param name="ofs:">the first position (byte) in the target string that will /// receive the substring from origin. /// </param> /// <param name="len:">the number of bytes that will be moved from origin to /// target, starting from the leftmost character of origin. /// </param> /// <returns> string containing modified target string /// /// Example: repB("abXYc", "de", 4, 2) /// Where 'a', 'b', 'c', 'd' and 'e' are SBCS, and 'X' and 'Y' are DBCS, /// it returns "ab de c". /// </returns> /** * @param {?} strTarget * @param {?} strOrigin * @param {?} ofs * @param {?} len * @return {?} */ static repB(strTarget, strOrigin, ofs, len) { /** @type {?} */ let strbufAddingBuf = new StringBuilder(); if (ofs < 0) { ofs = 0; } else { if (ofs >= 1) { ofs = ofs - 1; } } if (len < 0) { len = 0; } strbufAddingBuf.Append(UtilStrByteMode.leftB(strTarget, ofs)); /** @type {?} */ let intAddSpaceLen = ofs - UtilStrByteMode.lenB(strTarget); for (; intAddSpaceLen > 0; intAddSpaceLen--) strbufAddingBuf.Append(' '); strbufAddingBuf.Append(UtilStrByteMode.leftB(strOrigin, len)); /** @type {?} */ let intRightLen = UtilStrByteMode.lenB(strTarget) - (ofs + len); if (intRightLen > 0) { strbufAddingBuf.Append(UtilStrByteMode.rightB(strTarget, intRightLen)); } // add blanks to the end intAddSpaceLen = len - UtilStrByteMode.lenB(strOrigin); for (; intAddSpaceLen > 0; intAddSpaceLen--) { strbufAddingBuf.Append(' '); } return strbufAddingBuf.ToString(); } /// <summary> Replace Substring Within a String (Character Mode) /// Replaces a substring within a string with another substring. /// /// </summary> /// <param name="strTarget:">target string where the replacement will take place. /// </param> /// <param name="strOrigin:">string that provides the substring to be copied to /// target. /// </param> /// <param name="ofs:">the first position (character) in the target string that /// will receive the substring from origin. /// </param> /// <param name="len:">the number of characters that will be moved from origin /// to target, starting from the leftmost character of origin. /// </param> /// <returns> string containing modified target string /// /// Example: repB("abXYc", "de", 4, 2) /// Whether each character is SBCS or DBCS, it returns "abXde". /// </returns> /** * @param {?} strTarget * @param {?} strOrigin * @param {?} ofs * @param {?} len * @return {?} */ static repC(strTarget, strOrigin, ofs, len) { /** @type {?} */ let strbufAddingBuf = new StringBuilder(); if (ofs < 0) { ofs = 0; } else { if (ofs >= 1) { ofs = ofs - 1; } } if (len < 0) { len = 0; } strbufAddingBuf.Append(strTarget.substr(0, ofs)); // add blanks between strTarget and strOrigin /** @type {?} */ let intAddSpaceLen = ofs - strTarget.length; for (; intAddSpaceLen > 0; intAddSpaceLen--) strbufAddingBuf.Append(' '); strbufAddingBuf.Append(strOrigin.substr(0, len)); /** @type {?} */ let intRightLen = strTarget.length - (ofs + len); if (intRightLen > 0) { strbufAddingBuf.Append(strTarget.substr(ofs + len)); } for (let i = len - strOrigin.length; i > 0; i = i - 1) { strbufAddingBuf.Append(' '); } return strbufAddingBuf.ToString(); } /// <summary> Checks whether a character is 1 byte (halfwidth) or not (fullwidth) /// Returns true if the character is represented by 1 byte in non-Unicode /// encoding. /// </summary> /// <param name="letter:">a character to be checked. /// </param> /// <returns> true if the character is halfwidth (SBCS), or false if it is /// fullwidth (DBCS). /// </returns> /** * @param {?} str * @return {?} */ static isHalfWidth(str) { /** @type {?} */ let letter = str.charCodeAt(0); if (32 <= /*' '*/ letter && letter <= 126 /*'~'*/) { return true; } else { /** @type {?} */ let len = UtilStrByteMode.lenB(str); if (len === 1) return true; } return false; } /// <summary> Checks whether a character is halfwidth digit letter /// Do not use "Character.isDigit" which cannot distinguish between /// halfwidth digit letter(SBCS) and fullwidth difit letter(DBCS). /// </summary> /// <param name="letter:">a character to be checked. /// </param> /// <returns> true if the character is halfwidth digit letter, or /// false if it is DBCS or not digit letter. /// </returns> /** * @param {?} letter * @return {?} */ static isDigit(letter) { return 48 <= /*'0'*/ letter.charCodeAt(0) && letter.charCodeAt(0) <= 57 /*'9'*/; } /// <summary>Checks whether a character is one of those supported for # Alpha Mask</summary> /// <param name="letter:">a character to be checked. /// </param> /// <returns> true if the character is halfwidth digit letter, or /// false if it is DBCS or not digit letter. /// </returns> /** * @param {?} letter * @return {?} */ static asNumeric(letter) { /** @type {?} */ let result; switch (letter.charCodeAt(0)) { case 42: /*'*'*/ case 43: /*'+'*/ case 44: /*','*/ case 45: /*'-'*/ case 46: /*'.'*/ case 47:/*'/'*/ result = true; break; default: result = false; break; } return result; } /// <summary> Converts a position for the 1st string (Source) to a position for /// the 2nd string (Dest). /// If a double byte character exists in the strings, the position for the /// Source could be different from the position for the Dest. /// (DBCS Support) /// /// </summary> /// <param name="strSource:">Source string /// </param> /// <param name="strDest:">Dest string /// </param> /// <param name="pos:">position in the Source string /// </param> /// <param name="isAdvance:">advance or retreat the ret pos if a DBCS char is split /// </param> /// <returns> position in the Dest string /// /// Example: convPos("abcYZ", "YZabc", 4) /// It returns 4, if the all characters in the strings are SBCS. /// /// If 'a', 'b' and 'c' are SBCS, and 'Y' and 'Z' are DBCS, it /// returns 3. /// pos /// Unicode index 0 1 2 3 [4] /// +-------------+ /// Source string |a|b|c| Y | Z | /// +-------------+ /// ANSI index 0 1 2 3 4[5]6 /// +-------------+ /// Dest string | Y | Z |a|b|c| /// +-------------+ /// Unicode index 0 1 2[3]4 /// ret /// </returns> /** * @param {?} strSource * @param {?} strDest * @param {?} pos * @param {?} isAdvance * @return {?} */ static convPos(strSource, strDest, pos, isAdvance) { /** @type {?} */ let retPos; if (pos < 0) return 0; if (pos > strSource.length) pos = strSource.length; // add blanks to the Dest string if it is shorter than the Src string /** @type {?} */ let diffLen = UtilStrByteMode.lenB(strSource) - UtilStrByteMode.lenB(strDest); if (diffLen > 0) { /** @type {?} */ let stringBuilder = new StringBuilder(strDest); for (; diffLen > 0; diffLen--) stringBuilder.Append(' '); strDest = stringBuilder.ToString(); } /** @type {?} */ let byteSource = UtilStrByteMode.Encoding.GetBytes(strSource.substr(0, pos)); /** @type {?} */ let strLeftB = UtilStrByteMode.leftB(strDest, byteSource.length); retPos = strLeftB.length; if (!isAdvance && retPos > 0 && strLeftB.charCodeAt(retPos - 1) === 32 /*' '*/ && strDest.charCodeAt(retPos - 1) !== 32 /*' '*/) { retPos = retPos - 1; } return retPos; } /// <summary> return the number of characters of picture which corresponds to /// given string. /// </summary> /// <param name="str:">given string /// </param> /// <param name="picture:">picture /// </param> /// <returns> minimal length of picture /// Example: getMinLenPicture("ZZ20/11/", "JJJJYY/MM/DD") [ZZ is DBCS] /// It returns 10. /// </returns> /// (DBCS Support) /** * @param {?} str * @param {?} picture * @return {?} */ static getMinLenPicture(str, picture) { /** @type {?} */ let len = 0; if (UtilStrByteMode.lenB(picture) - UtilStrByteMode.lenB(str) > 0) { len = UtilStrByteMode.convPos(str, picture, str.length, false); } else len = picture.length; return len; } /// <summary> /// </summary> Compares two specified strings in the DBCS sort order and returns an integer /// that indicates their relative position. /// <param name="str1:">The first string to compare. /// </param> /// <param name="str2:">The second string to compare. /// </param> /// <returns>an integer that indicates the lexical relationship between the two strings. /// -1: str1 is less than str2. /// 0: str1 equals str2. /// 1: str1 is greater than str2. /// </returns> /** * @param {?} str1 * @param {?} str2 * @return {?} */ static strcmp(str1, str2) { /** @type {?} */ let array1 = UtilStrByteMode.Encoding.GetBytes(str1); /** @type {?} */ let array2 = UtilStrByteMode.Encoding.GetBytes(str2); for (let i = 0; i < array1.length && i < array2.length; i++) { if (array1[i] > array2[i]) { return 1; } else if (array1[i] < array2[i]) { return -1; } } if (array1.length > array2.length) return 1; if (array1.length < array2.length) return -1; else return 0; } } UtilStrByteMode.Encoding = Encoding.UTF8; // TODO : need to check what to do with CultureInfo UtilStrByteMode.twoLetterISOLanguageName = " "; UtilStrByteMode._bLocaleDefLangJPN = (UtilStrByteMode.twoLetterISOLanguageName === "ja"); UtilStrByteMode._bLocaleDefLangCHN = (UtilStrByteMode.twoLetterISOLanguageName === "zh"); UtilStrByteMode._bLocaleDefLangKOR = (UtilStrByteMode.twoLetterISOLanguageName === "ko"); if (false) { /** @type {?} */ UtilStrByteMode.Encoding; /** @type {?} */ UtilStrByteMode.twoLetterISOLanguageName; /** @type {?} */ UtilStrByteMode._bLocaleDefLangJPN; /** @type {?} */ UtilStrByteMode._bLocaleDefLangCHN; /** @type {?} */ UtilStrByteMode._bLocaleDefLangKOR; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXRpbFN0ckJ5dGVNb2RlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG1hZ2ljLXhwYS91dGlscy8iLCJzb3VyY2VzIjpbInNyYy9VdGlsU3RyQnl0ZU1vZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQU1BLE9BQU8sRUFBVSxRQUFRLEVBQUUsYUFBYSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFdEUsTUFBTTs7Ozs7Ozs7Ozs7SUFlSixNQUFNLENBQUMsbUJBQW1CO1FBQ3hCLE1BQU0sQ0FBQyxlQUFlLENBQUMsa0JBQWtCLElBQUksZUFBZSxDQUFDLGtCQUFrQixJQUFJLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQztJQUN4SCxDQUFDOzs7Ozs7Ozs7O0lBUUQsTUFBTSxDQUFDLGtCQUFrQjtRQUN2QixNQUFNLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDO0lBQzVDLENBQUM7Ozs7Ozs7Ozs7SUFRRCxNQUFNLENBQUMsa0JBQWtCO1FBQ3ZCLE1BQU0sQ0FBQyxlQUFlLENBQUMsa0JBQWtCLENBQUM7SUFDNUMsQ0FBQzs7Ozs7SUFFRCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBUztRQUNoQyxNQUFNLENBQUMsQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFBLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFBLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUEsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUEsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFBLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFBLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQSxPQUFPLENBQUMsQ0FBQztJ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QyxDQUFDLENBQUM7UUFFWCxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDaEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ1osSUFBSTtZQUNGLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDYixDQUFDOztBQW5uQmEsd0JBQVEsR0FBYSxRQUFRLENBQUMsSUFBSSxDQUFDO0FBQy9DLG1EQUFtRDtBQUM5Qyx3Q0FBd0IsR0FBVyxHQUFHLENBQUM7QUFDL0Isa0NBQWtCLEdBQVksQ0FBQyxlQUFlLENBQUMsd0JBQXdCLEtBQUssSUFBSSxDQUFDLENBQUM7QUFDbEYsa0NBQWtCLEdBQVksQ0FBQyxlQUFlLENBQUMsd0JBQXdCLEtBQUssSUFBSSxDQUFDLENBQUM7QUFDbEYsa0NBQWtCLEdBQVksQ0FBQyxlQUFlLENBQUMsd0JBQXdCLEtBQUssSUFBSSxDQUFDLENBQUM7OztJQUxqRyx5QkFBaUQ7O0lBRWpELHlDQUE4Qzs7SUFDOUMsbUNBQWlHOztJQUNqRyxtQ0FBaUc7O0lBQ2pHLG1DQUFpRyIsInNvdXJjZXNDb250ZW50IjpbIi8vLyA8c3VtbWFyeT5KUE46IERCQ1Mgc3VwcG9ydFxyXG4vLy8gVXRpbGl0eSBDbGFzcyBmb3IgU3RyaW5nXHJcbi8vLyBJbiB0aGlzIGNsYXNzLCBjb25zaWRlcmluZyBEQkNTLCBzdHJpbmdzIGFyZSBjb3VudGVkIGJ5IHRoZSBudW1iZXJcclxuLy8vIG9mIGJ5dGVzLCBub3QgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzLlxyXG4vLy8gPC9zdW1tYXJ5PlxyXG4vLy8gPGF1dGhvcj4gIFRvc2hpcm8gTmFrYXlvc2hpIChNU0opIDwvYXV0aG9yPlxyXG5pbXBvcnQge05TdHJpbmcsIEVuY29kaW5nLCBTdHJpbmdCdWlsZGVyfSBmcm9tIFwiQG1hZ2ljLXhwYS9tc2NvcmVsaWJcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBVdGlsU3RyQnl0ZU1vZGUgIHtcclxuICBwdWJsaWMgc3RhdGljIEVuY29kaW5nOiBFbmNvZGluZyA9IEVuY29kaW5nLlVURjg7XHJcbiAgICAvLyBUT0RPIDogbmVlZCB0byBjaGVjayB3aGF0IHRvIGRvIHdpdGggQ3VsdHVyZUluZm9cclxuICBzdGF0aWMgdHdvTGV0dGVySVNPTGFuZ3VhZ2VOYW1lOiBzdHJpbmcgPSBcIiBcIjtcclxuICBwcml2YXRlIHN0YXRpYyBfYkxvY2FsZURlZkxhbmdKUE46IGJvb2xlYW4gPSAoVXRpbFN0ckJ5dGVNb2RlLnR3b0xldHRlcklTT0xhbmd1YWdlTmFtZSA9PT0gXCJqYVwiKTtcclxuICBwcml2YXRlIHN0YXRpYyBfYkxvY2FsZURlZkxhbmdDSE46IGJvb2xlYW4gPSAoVXRpbFN0ckJ5dGVNb2RlLnR3b0xldHRlcklTT0xhbmd1YWdlTmFtZSA9PT0gXCJ6aFwiKTtcclxuICBwcml2YXRlIHN0YXRpYyBfYkxvY2FsZURlZkxhbmdLT1I6IGJvb2xlYW4gPSAoVXRpbFN0ckJ5dGVNb2RlLnR3b0xldHRlcklTT0xhbmd1YWdlTmFtZSA9PT0gXCJrb1wiKTtcclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiBDaGVja3MgdGhlIGVudmlyb25tZW50IHdoZXRoZXIgaXQgaXMgcnVubmluZyBvbiBEQkNTIGVudmlyb25tZW50XHJcbiAgLy8vIFJldHVybnMgdHJ1ZSBpZiB0aGUgbGFuZ3VhZ2UgY29kZSBmb3IgdGhlIGN1cnJlbnQgZGVmYXVsdCBMb2NhbGUgaXNcclxuICAvLy8gREJDUyBsYW5ndWFnZSAoaW4gbm9uLVVuaWNvZGUgZW5jb2RpbmcpLlxyXG4gIC8vL1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxyZXR1cm5zPiB0cnVlIGlmIERCQ1MsIG9yIGZhbHNlIGlmIFNCQ1NcclxuICAvLy8gPC9yZXR1cm5zPlxyXG4gIHN0YXRpYyBpc0xvY2FsZURlZkxhbmdEQkNTKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIFV0aWxTdHJCeXRlTW9kZS5fYkxvY2FsZURlZkxhbmdKUE4gfHwgVXRpbFN0ckJ5dGVNb2RlLl9iTG9jYWxlRGVmTGFuZ0NITiB8fCBVdGlsU3RyQnl0ZU1vZGUuX2JMb2NhbGVEZWZMYW5nS09SO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiBDaGVja3Mgd2hldGhlciB0aGUgbGFuZ3VhZ2UgY29kZSBmb3IgdGhlIGN1cnJlbnQgZGVmYXVsdCBMb2NhbGVcclxuICAvLy8gaXMgSkFQQU5FU0UuXHJcbiAgLy8vXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHJldHVybnM+IHRydWUgaWYgSkFQQU5FU0UsIG9yIGZhbHNlIGlmIG5vdFxyXG4gIC8vLyA8L3JldHVybnM+XHJcbiAgc3RhdGljIGlzTG9jYWxlRGVmTGFuZ0pQTigpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBVdGlsU3RyQnl0ZU1vZGUuX2JMb2NhbGVEZWZMYW5nSlBOO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiBDaGVja3Mgd2hldGhlciB0aGUgbGFuZ3VhZ2UgY29kZSBmb3IgdGhlIGN1cnJlbnQgZGVmYXVsdCBMb2NhbGVcclxuICAvLy8gaXMgS09SRUFOLlxyXG4gIC8vL1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxyZXR1cm5zPiB0cnVlIGlmIEtPUkVBTiwgb3IgZmFsc2UgaWYgbm90XHJcbiAgLy8vIDwvcmV0dXJucz5cclxuICBzdGF0aWMgaXNMb2NhbGVEZWZMYW5nS09SKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIFV0aWxTdHJCeXRlTW9kZS5fYkxvY2FsZURlZkxhbmdLT1I7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgaXNLb3JlYW5DaGFyYWN0ZXIoYzogbnVtYmVyKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKDQ0MDMyIDw9IC8qJ+qwgCcqL2MgJiYgYyA8PSA1NTIwMy8qJ+2eoycqLykgfHwgKDQzNTIgPD0gLyon4YSAJyovYyAmJiBjIDw9IDQ2MDcvKifhh78nKi8pIHx8ICgxMjU5MiA8PSAvKifjhLAnKi9jICYmIGMgPD0gMTI2ODcvKifjho8nKi8pIHx8ICg0MzM2MCA8PSAvKifqpaAnKi9jICYmIGMgPD0gNDMzOTEvKifqpb8nKi8pIHx8ICg1NTIxNiA8PSAvKiftnrAnKi9jICYmIGMgPD0gNTUyOTUvKiftn78nKi8pO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiBMZW5ndGggb2YgU3RyaW5nXHJcbiAgLy8vIFJldHVybnMgdGhlIG51bWJlciBvZiBieXRlcyAoaW4gZGVmYXVsdCBlbmNvZGluZykuXHJcbiAgLy8vXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJzdHJWYWw6XCI+c3RyaW5nIChpbiBVbmljb2RlKVxyXG4gIC8vLyA8L3BhcmFtPlxyXG4gIC8vLyA8cmV0dXJucz4gdGhlIG51bWJlciBvZiBieXRlcyAoaW4gZGVmYXVsdCBlbmNvZGluZylcclxuICAvLy9cclxuICAvLy8gRXhhbXBsZTogbGVuQihcImFiWFljXCIpXHJcbiAgLy8vIFdoZXJlICdhJywgJ2InIGFuZCAgJ2MnIGFyZSBTQkNTLCBhbmQgJ1gnIGFuZCAnWScgYXJlIERCQ1MsIGl0IHJldHVybnNcclxuICAvLy8gNy5cclxuICAvLy8gPC9yZXR1cm5zPlxyXG4gIHN0YXRpYyBsZW5CKHN0clZhbDogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgIC8vIGNvbnZlcnQgdG8gYnl0ZVtdIGJ5IGRlZmF1bHQtZW5jb2RpbmdcclxuICAgIHJldHVybiBVdGlsU3RyQnl0ZU1vZGUuRW5jb2RpbmcuR2V0Qnl0ZUNvdW50KHN0clZhbCk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+IFN1YnN0cmluZyBvZiBTdHJpbmdcclxuICAvLy8gRXh0cmFjdHMgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGNoYXJhY3RlcnMgKGEgc3Vic3RyaW5nKSBmcm9tIGEgc3RyaW5nLlxyXG4gIC8vLyBJZiBhIERCQ1MgY2hhcmFjdGVyIGlzIGRpdmlkZWQgaW4gdHdvLCBpdCB3aWxsIGJlIHJlcGxhY2UgdG8gYSBzcGFjZS5cclxuICAvLy9cclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInN0clZhbDpcIj5zdHJpbmcgKGluIFVuaWNvZGUpXHJcbiAgLy8vIDwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwib2ZzOlwiPnN0YXJ0aW5nIHBvc2l0aW9uIChieXRlKSBvZiB0aGUgc3Vic3RyaW5nXHJcbiAgLy8vIDwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibGVuOlwiPm51bWJlciBvZiBieXRlcyB0byBiZSBleHRyYWN0ZWQgKGkuZS4gYnl0ZXMgb2Ygc3Vic3RyaW5nKVxyXG4gIC8vLyA8L3BhcmFtPlxyXG4gIC8vLyA8cmV0dXJucz4gc3Vic3RyaW5nXHJcbiAgLy8vXHJcbiAgLy8vIEV4YW1wbGU6IG1pZEIoXCJhYlhZY1wiLCAyLCA0KVxyXG4gIC8vLyBXaGVyZSAnYScsICdiJyBhbmQgICdjJyBhcmUgU0JDUywgYW5kICdYJyBhbmQgJ1knIGFyZSBEQkNTLCBpdCByZXR1cm5zXHJcbiAgLy8vIFwiYlggXCIuXHJcbiAgLy8vIDwvcmV0dXJucz5cclxuICBzdGF0aWMgbWlkQihzdHJWYWw6IHN0cmluZywgb2ZzOiBudW1iZXIsIGxlbjogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIGxldCBpbnRWYWxpZE1heEluZGV4OiBudW1iZXIgPSAtMTsgLy8gcGFyYW0gIzEgb2Ygc3Vic3RyaW5nXHJcbiAgICBsZXQgaW50VmFsaWRNaW5JbmRleDogbnVtYmVyID0gLTE7IC8vIHBhcmFtICMyIG9mIHN1YnN0cmluZ1xyXG4gICAgbGV0IGJIZWFkU3BhY2U6IGJvb2xlYW4gPSBmYWxzZTsgICAvLyBmbGFnOiBuZWVkIHRvIGFkZCBzcGFjZVxyXG4gICAgbGV0IGJFbmRTcGFjZTogYm9vbGVhbiA9IGZhbHNlOyAgICAvLyBmbGFnOiBuZWVkIHRvIGFkZCBzcGFjZVxyXG5cclxuICAgIGxldCBzdHJSZXQ6IHN0cmluZztcclxuXHJcbiAgICAvLyBjaGVjayBhbmQgbW9kaWZ5IG9mcyAmIGxlblxyXG4gICAgaWYgKGxlbiA8PSAwKVxyXG4gICAgICByZXR1cm4gXCJcIjtcclxuXHJcbiAgICBpZiAob2ZzIDw9IDApIHtcclxuICAgICAgb2ZzID0gMDtcclxuICAgICAgaW50VmFsaWRNaW5JbmRleCA9IDA7XHJcbiAgICAgIGJIZWFkU3BhY2UgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgaW50Qnl0ZUxlbmd0aDogbnVtYmVyID0gVXRpbFN0ckJ5dGVNb2RlLmxlbkIoc3RyVmFsKTtcclxuXHJcbiAgICBpZiAoaW50Qnl0ZUxlbmd0aCA8IG9mcylcclxuICAgICAgcmV0dXJuIFwiXCI7XHJcblxyXG4gICAgbGV0IExlbk1heDogbnVtYmVyID0gaW50Qnl0ZUxlbmd0aCAtIG9mcztcclxuICAgIGlmIChMZW5NYXggPCBsZW4pXHJcbiAgICAgIGxlbiA9IExlbk1heDtcclxuXHJcbiAgICAvLyBzZXQgTWluSW5kZXggYW5kIE1heEluZGV4IGZvciBzdWJzdHJpbmdcclxuICAgIGludEJ5dGVMZW5ndGggPSAwO1xyXG5cclxuICAgIGZvciAobGV0IGludEluZGV4OiBudW1iZXIgPSAwOyBpbnRJbmRleCA8IHN0clZhbC5sZW5ndGg7IGludEluZGV4ID0gaW50SW5kZXggKyAxKSB7XHJcbiAgICAgIGxldCBzOiBzdHJpbmcgPSBzdHJWYWwuc3Vic3RyKGludEluZGV4LCAxKTtcclxuICAgICAgaW50Qnl0ZUxlbmd0aCA9IGludEJ5dGVMZW5ndGggKyBVdGlsU3RyQnl0ZU1vZGUuRW5jb2RpbmcuR2V0Qnl0ZUNvdW50KHMpO1xyXG5cclxuICAgICAgaWYgKGludFZhbGlkTWluSW5kZXggPT09IC0xKSB7XHJcbiAgICAgICAgaWYgKGludEJ5dGVMZW5ndGggPT09IG9mcykge1xyXG4gICAgICAgICAgaW50VmFsaWRNaW5JbmRleCA9IGludEluZGV4ICsgMTtcclxuICAgICAgICAgIGJIZWFkU3BhY2UgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoaW50Qnl0ZUxlbmd0aCA+IG9mcykge1xyXG4gICAgICAgICAgaW50VmFsaWRNaW5JbmRleCA9IGludEluZGV4ICsgMTtcclxuICAgICAgICAgIGJIZWFkU3BhY2UgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGludFZhbGlkTWF4SW5kZXggPT09IC0xKSB7XHJcbiAgICAgICAgaWYgKGludEJ5dGVMZW5ndGggPT09IG9mcyArIGxlbikge1xyXG4gICAgICAgICAgaW50VmFsaWRNYXhJbmRleCA9IGludEluZGV4O1xyXG4gICAgICAgICAgYkVuZFNwYWNlID0gZmFsc2U7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoaW50Qnl0ZUxlbmd0aCA+IG9mcyArIGxlbikge1xyXG4gICAgICAgICAgaW50VmFsaWRNYXhJbmRleCA9IGludEluZGV4IC0gMTtcclxuICAgICAgICAgIGJFbmRTcGFjZSA9IHRydWU7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBwcmVwYXJlIGZvciBzdWJzdHJpbmdcclxuICAgIGxldCBzdHJidWZBZGRpbmdCdWY6IFN0cmluZ0J1aWxkZXIgPSBuZXcgU3RyaW5nQnVpbGRlcihsZW4pO1xyXG5cclxuICAgIC8vIGV4ZWN1dGUgTWlkXHJcbiAgICBpZiAoYkhlYWRTcGFjZSkge1xyXG4gICAgICBzdHJidWZBZGRpbmdCdWYuQXBwZW5kKCcgJyk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGludFZhbGlkTWluSW5kZXggPD0gaW50VmFsaWRNYXhJbmRleCkge1xyXG4gICAgICBzdHJidWZBZGRpbmdCdWYuQXBwZW5kKHN0clZhbC5zdWJzdHIoaW50VmFsaWRNaW5JbmRleCwgaW50VmFsaWRNYXhJbmRleCArIDEgLSBpbnRWYWxpZE1pbkluZGV4KSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGJFbmRTcGFjZSkge1xyXG4gICAgICBzdHJidWZBZGRpbmdCdWYuQXBwZW5kKCcgJyk7XHJcbiAgICB9XHJcblxyXG4gICAgc3RyUmV0ID0gc3RyYnVmQWRkaW5nQnVmLlRvU3RyaW5nKCk7XHJcbiAgICBzdHJidWZBZGRpbmdCdWYgPSBudWxsO1xyXG5cclxuICAgIHJldHVybiBzdHJSZXQ7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+IEdldCBDaGFyYWN0ZXJzIGZyb20gTGVmdCBvZiBTdHJpbmdcclxuICAvLy8gUmV0dXJucyBhIHNwZWNpZmllZCBudW1iZXIgb2YgYnl0ZXMgZnJvbSB0aGUgbGVmdCBzaWRlIG9mIGEgc3RyaW5nLlxyXG4gIC8vLyBJZiBhIERCQ1MgY2hhcmFjdGVyIGlzIGRpdmlkZWQgaW4gdHdvLCBpdCB3aWxsIGJlIHJlcGxhY2UgdG8gYSBzcGFjZS5cclxuICAvLy9cclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInN0clZhbDpcIj5zdHJpbmcgKGluIFVuaWNvZGUpXHJcbiAgLy8vIDwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibGVuOlwiPm51bWJlciBvZiBieXRlcyB0byBiZSByZXR1cmVkXHJcbiAgLy8vIDwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPiBvdXRwdXQgc3RyaW5nXHJcbiAgLy8vXHJcbiAgLy8vIEV4YW1wbGU6IGxlZnRCKFwiYWJYWWNcIiwgNClcclxuICAvLy8gV2hlcmUgJ2EnLCAnYicgYW5kICAnYycgYXJlIFN