XIVChat/XIVChat Desktop/Util.cs

750 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Threading;
namespace XIVChat_Desktop {
public static class Util {
// GOOD HEAVENS! I REALISE HOW INEFFICIENT THIS IS
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static IEnumerable<List<T>> Chunks<T>(this List<T> locations, int nSize) {
for (var i = 0; i < locations.Count; i += nSize) {
yield return locations.GetRange(i, Math.Min(nSize, locations.Count - i));
}
}
public static void Dispatch(this DispatcherObject dispatcherObj, Action action) {
dispatcherObj.Dispatcher.BeginInvoke(action);
}
public static void Dispatch(this DispatcherObject dispatcherObj, DispatcherPriority priority, Action action) {
dispatcherObj.Dispatcher.BeginInvoke(priority, action);
}
public static bool IsAsciiPunctuation(this char c) {
// 2.1 Characters and lines
// An ASCII punctuation character is !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~.
switch (c) {
case '!':
case '"':
case '#':
case '$':
case '%':
case '&':
case '\'':
case '(':
case ')':
case '*':
case '+':
case ',':
case '-':
case '.':
case '/':
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '@':
case '[':
case '\\':
case ']':
case '^':
case '_':
case '`':
case '{':
case '|':
case '}':
case '~':
return true;
}
return false;
}
public static bool IsWhitespace(this char c) {
// 2.1 Characters and lines
// A whitespace character is a space(U + 0020), tab(U + 0009), newline(U + 000A), line tabulation (U + 000B), form feed (U + 000C), or carriage return (U + 000D).
return c is <= ' ' and (' ' or '\t' or '\n' or '\v' or '\f' or '\r');
}
public static string? WorldName(ushort id) {
return id switch {
1 => "reserved1",
2 => "c-contents",
3 => "c-whiteae",
4 => "c-baudinii",
5 => "c-contents2",
6 => "c-funereus",
16 => "konconv",
23 => "Asura",
24 => "Belias",
25 => "Chaos",
26 => "Hecatoncheir",
27 => "Moomba",
28 => "Pandaemonium",
29 => "Shinryu",
30 => "Unicorn",
31 => "Yojimbo",
32 => "Zeromus",
33 => "Twintania",
34 => "Brynhildr",
35 => "Famfrit",
36 => "Lich",
37 => "Mateus",
38 => "Shemhazai",
39 => "Omega",
40 => "Jenova",
41 => "Zalera",
42 => "Zodiark",
43 => "Alexander",
44 => "Anima",
45 => "Carbuncle",
46 => "Fenrir",
47 => "Hades",
48 => "Ixion",
49 => "Kujata",
50 => "Typhon",
51 => "Ultima",
52 => "Valefor",
53 => "Exodus",
54 => "Faerie",
55 => "Lamia",
56 => "Phoenix",
57 => "Siren",
58 => "Garuda",
59 => "Ifrit",
60 => "Ramuh",
61 => "Titan",
62 => "Diabolos",
63 => "Gilgamesh",
64 => "Leviathan",
65 => "Midgardsormr",
66 => "Odin",
67 => "Shiva",
68 => "Atomos",
69 => "Bahamut",
70 => "Chocobo",
71 => "Moogle",
72 => "Tonberry",
73 => "Adamantoise",
74 => "Coeurl",
75 => "Malboro",
76 => "Tiamat",
77 => "Ultros",
78 => "Behemoth",
79 => "Cactuar",
80 => "Cerberus",
81 => "Goblin",
82 => "Mandragora",
83 => "Louisoix",
84 => "Syldra",
85 => "Spriggan",
90 => "Aegis",
91 => "Balmung",
92 => "Durandal",
93 => "Excalibur",
94 => "Gungnir",
95 => "Hyperion",
96 => "Masamune",
97 => "Ragnarok",
98 => "Ridill",
99 => "Sargatanas",
100 => "dev_test",
101 => "zone_test",
102 => "trs_test",
103 => "contents_test",
110 => "b-tirica",
111 => "b-contents",
112 => "b-chiriri",
113 => "b-contents2",
114 => "b-jugularis",
115 => "e-regia",
116 => "e-pialii",
117 => "e-contents",
118 => "e-contents2",
119 => "e-coloria",
120 => "e-gouldiae",
121 => "e-contents3",
123 => "e-trichroa",
124 => "e-hyperion",
126 => "e-ragnarok",
127 => "e-ridill",
128 => "e-sargatanas",
129 => "a-militaris",
130 => "a-aegis",
131 => "a-balmung",
132 => "a-durandal",
133 => "a-excalibur",
134 => "a-gungnir",
135 => "a-hyperion",
136 => "a-masamune",
137 => "a-ragnarok",
138 => "a-ridill",
139 => "a-sargatanas",
140 => "a-contents",
141 => "b-contents3",
142 => "b-cyanoptera",
144 => "a-contentsx",
145 => "a-contents2",
156 => "z-japonicus",
157 => "z-dauma",
158 => "z-contents",
159 => "z-contents2",
160 => "s-bella",
161 => "Chocobo",
162 => "s-contents",
163 => "chs-contents",
164 => "s-contents2",
165 => "s-guttata",
166 => "Moogle",
167 => "chs-contents2",
168 => "Namazu",
169 => "chs-contents3",
170 => "s-poliogenys",
171 => "s-haematina",
172 => "s-contents3",
173 => "s-contents4",
174 => "s-public1",
175 => "s-public2",
176 => "s-public3",
177 => "s-public4",
178 => "s-public5",
179 => "s-public6",
180 => "s-public7",
181 => "s-public8",
182 => "s-macropus",
183 => "s-contents7",
184 => "s-latrans",
185 => "s-contents8",
186 => "s-cucullatus",
187 => "s-bicolor",
188 => "s-contents5",
189 => "s-contents6",
201 => "Nacontents01",
202 => "Nacontents02",
203 => "Nacontents03",
204 => "Nacontents04",
205 => "Nacontents05",
206 => "Nacontents06",
207 => "Nacontents07",
208 => "Nacontents08",
209 => "Nacontents09",
210 => "Nacontents10",
211 => "Nacontents11",
212 => "Nacontents12",
213 => "Nacontents13",
214 => "Nacontents14",
215 => "Nacontents15",
216 => "Nacontents16",
217 => "Nacontents17",
218 => "Nacontents18",
219 => "Nacontents19",
220 => "Nacontents20",
221 => "Nacontents21",
222 => "Nacontents22",
223 => "Nacontents23",
224 => "Nacontents24",
225 => "Jpcontents01",
226 => "Jpcontents02",
227 => "Jpcontents03",
228 => "Jpcontents04",
229 => "Jpcontents05",
230 => "Jpcontents06",
231 => "Jpcontents07",
232 => "Jpcontents08",
233 => "Jpcontents09",
234 => "Jpcontents10",
235 => "Jpcontents11",
236 => "Jpcontents12",
237 => "Jpcontents13",
238 => "Jpcontents14",
239 => "Jpcontents15",
240 => "Jpcontents16",
241 => "Jpcontents17",
242 => "Jpcontents18",
243 => "Jpcontents19",
244 => "Jpcontents20",
245 => "Jpcontents21",
246 => "Jpcontents22",
247 => "Jpcontents23",
248 => "Jpcontents24",
249 => "Jpcontents25",
250 => "Jpcontents26",
251 => "Jpcontents27",
252 => "Jpcontents28",
253 => "Jpcontents29",
254 => "Jpcontents30",
255 => "Nacontents25",
256 => "Nacontents26",
257 => "Nacontents27",
258 => "Nacontents28",
259 => "Nacontents29",
260 => "Nacontents30",
261 => "Nacontents31",
262 => "Nacontents32",
263 => "Nacontents33",
264 => "Nacontents34",
265 => "Jpcontents31",
266 => "Jpcontents32",
267 => "Jpcontents33",
268 => "Jpcontents34",
269 => "Jpcontents35",
270 => "Jpcontents36",
271 => "Nacontents36",
272 => "Nacontents37",
273 => "Nacontents38",
274 => "Nacontents39",
275 => "Nacontents40",
276 => "Nacontents41",
277 => "Nacontents42",
278 => "Nacontents43",
279 => "Nacontents44",
280 => "Nacontents45",
576 => "h-collaris",
577 => "h-metallica",
578 => "h-contents",
579 => "h-contents2",
580 => "h-cauta",
581 => "h-contents3",
582 => "h-picatus",
583 => "h-contents4",
584 => "h-sordidus",
585 => "h-canente",
586 => "h-contents5",
630 => "a-contents3",
631 => "a-contents4",
632 => "a-contents5",
633 => "a-contents6",
634 => "a-contents7",
635 => "a-contents8",
636 => "a-contents9",
637 => "a-contents10",
638 => "a-contents20",
640 => "a-public1",
641 => "a-public2",
642 => "a-public3",
643 => "a-public4",
644 => "a-public5",
645 => "a-public6",
646 => "a-public7",
647 => "a-public8",
648 => "a-public9",
649 => "a-public10",
650 => "a-public11",
651 => "a-public12",
652 => "a-public13",
653 => "a-public14",
654 => "a-public15",
655 => "a-public16",
656 => "a-public17",
657 => "a-public18",
1024 => "test1",
1025 => "test2",
1040 => "DiPingGuan",
1041 => "MiWuShiDi",
1042 => "LaNuoXiYa",
1043 => "ZiShuiZhanQiao",
1044 => "HuanYingQunDao",
1045 => "MoDuNa",
1046 => "MoShouLingYu",
1047 => "FengMoDong",
1048 => "TaiyangHaiAn",
1049 => "XiaoMaiJiuGang",
1050 => "YinLeiHu",
1051 => "ShengXiaTan",
1052 => "PuTaoJiuGang",
1053 => "HeiYiSenLin",
1054 => "QingLinQuan",
1055 => "JinChuiTaiDi",
1056 => "HongChaChuan",
1057 => "YiXiuJiaDe",
1058 => "XueSongYuan",
1059 => "YaoJingLing",
1060 => "MengYaChi",
1061 => "ZhiZhangXiaGu",
1062 => "MiYueZhiTa",
1063 => "MoLaBiWan",
1064 => "YueYaWan",
1065 => "YaoLanShu",
1066 => "QiaoMingDong",
1067 => "NiMuHe",
1068 => "HuangJinGu",
1069 => "BaiLingTi",
1070 => "TianLangXingDengTa",
1071 => "ZhuoReZouLang",
1072 => "SiYuJuMu",
1073 => "YueYingDao",
1074 => "ShuiJingTa",
1075 => "MengXiangGong",
1076 => "BaiJinHuanXiang",
1077 => "HeiJinHu",
1078 => "LongXiPuBu",
1079 => "ShiWeiTa",
1080 => "TongLingTongShan",
1081 => "ShenYiZhiDi",
1082 => "ShiJiuDaQiao",
1083 => "YongHengChuan",
1084 => "HaiWuShaTan",
1085 => "HeFengLiuDi",
1086 => "ZeMeiErYaoSai",
1087 => "JuShiQiu",
1088 => "JianDouLingYu",
1089 => "HeiChenYiZhan",
1090 => "ShuiLianYan",
1091 => "LingHangMingDeng",
1092 => "HaiCiShiKu",
1093 => "FeiCuiHu",
1094 => "XiongXinGuangChang",
1095 => "KuErZhaSi",
1096 => "LiuShaMiGong",
1097 => "FangXiangTang",
1098 => "HuaMiZhanQiao",
1099 => "LanWuYongQuan",
1100 => "ShenLingShengYu",
1101 => "BaiYunYa",
1102 => "HaiJiangShuiQu",
1103 => "YuanLingYouShu",
1104 => "ShaZhongLuTing",
1105 => "JieMeiQiu",
1106 => "JingYuZhuangYuan",
1107 => "ZuJiGu",
1108 => "ShanHuTa",
1109 => "HengDuanYa",
1110 => "ShuiShangTingYuan",
1111 => "WuXianHuiLang",
1112 => "JinDingChi",
1113 => "LvRenZhanQiao",
1114 => "LongWenYan",
1115 => "HaiManQiaoLang",
1116 => "YuanQuanZhiTi",
1117 => "MiShiTa",
1118 => "RiShengMen",
1119 => "XiFengJia",
1120 => "ShenLiZhiMen",
1121 => "FuXiaoZhiJian",
1122 => "HaiLangDong",
1123 => "XiangShuYuan",
1124 => "MoNvKaFeiGuan",
1125 => "JuLongShouYingDi",
1126 => "DiYuHeGu",
1127 => "FuRongYuanZhuo",
1128 => "ShenWoJiao",
1129 => "HuangJinGuangChang",
1130 => "WanZhiMuChang",
1131 => "QiMuQuan",
1132 => "JingChiZhanQiao",
1133 => "BaiOuTA",
1134 => "XiaoShiWangDu",
1135 => "KuaTianQiao",
1136 => "ShengRenLei",
1137 => "JianFeng",
1138 => "HouWeiTa",
1139 => "BaiYinJiShi",
1140 => "LaiShengHuiLang",
1141 => "BaoFengLuMen",
1142 => "YouLingHu",
1143 => "ShiLvHu",
1144 => "HuangHunWan",
1145 => "XiaoALaMiGe",
1146 => "FangLangShenLiTang",
1147 => "JingJiSen",
1148 => "LangYanQiu",
1149 => "ShengRenLvDao",
1150 => "BuHuiZhanQuan",
1151 => "JiuTeng",
1152 => "RongYaoXi",
1153 => "JingShu",
1154 => "YuMenYiXue",
1155 => "YiWangLvZhou",
1156 => "YanDiLing",
1157 => "GeYongLieGu",
1158 => "LiuShaWu",
1159 => "BaJianShiQianTing",
1160 => "Bahamute",
1161 => "Zhushenhuanghun",
1162 => "Wangzhezhijian",
1163 => "Luxingniao",
1164 => "Shenshengcaipansuo",
1165 => "Bingtiangong",
1166 => "Longchaoshendian",
1167 => "HongYuHai",
1168 => "HuangJinGang",
1169 => "YanXia",
1170 => "ChaoFengTing",
1171 => "ShenQuanHen",
1172 => "BaiYinXiang",
1173 => "YuZhouHeYin",
1174 => "WoXianXiRan",
1175 => "ChenXiWangZuo",
1176 => "MengYuBaoJing",
1177 => "HaiMaoChaWu",
1178 => "RouFengHaiWan",
1179 => "HuPoYuan",
1536 => "contentstest1",
1537 => "contentstest2",
1552 => "sdocontents1",
1553 => "sdocontents2",
1554 => "sdocontents3",
1555 => "sdocontents4",
1556 => "sdocontents5",
1557 => "sdocontents6",
1558 => "sdocontents7",
1559 => "sdocontents8",
1560 => "sdocontents9",
1561 => "sdocontents10",
1562 => "sdocontents11",
1563 => "sdocontents12",
1564 => "sdocontents13",
1565 => "sdocontents14",
1566 => "sdocontents15",
1567 => "sdocontents16",
1568 => "sdocontents17",
1569 => "sdocontents18",
1570 => "sdocontents19",
1571 => "sdocontents20",
1572 => "sdocontents21",
1573 => "sdocontents22",
1574 => "sdocontents23",
1575 => "sdocontents24",
1576 => "sdocontents25",
1577 => "sdocontents26",
1578 => "sdocontents27",
1579 => "sdocontents28",
1580 => "sdocontents29",
1581 => "sdocontents30",
1582 => "sdocontents31",
1583 => "sdocontents32",
1584 => "sdocontents33",
1585 => "sdocontents34",
1586 => "sdocontents35",
1587 => "sdocontents36",
1588 => "sdocontents37",
1589 => "sdocontents38",
1590 => "sdocontents39",
1591 => "sdocontents40",
1592 => "sdocontents41",
1593 => "sdocontents42",
1594 => "sdocontents43",
1595 => "sdocontents44",
1596 => "sdocontents45",
1597 => "sdocontents46",
1598 => "sdocontents47",
1599 => "sdocontents48",
1600 => "sdocontents49",
1601 => "sdocontents50",
1602 => "sdocontents51",
1603 => "sdocontents52",
1604 => "sdocontents53",
1605 => "sdocontents54",
1606 => "sdocontents55",
1607 => "sdocontents56",
1608 => "sdocontents57",
1609 => "sdocontents58",
1610 => "sdocontents59",
1611 => "sdocontents60",
1612 => "sdocontents61",
1613 => "sdocontents62",
1614 => "sdocontents63",
1615 => "sdocontents64",
1616 => "sdocontents65",
1617 => "sdocontents66",
1618 => "sdocontents67",
1619 => "sdocontents68",
1620 => "sdocontents69",
1621 => "sdocontents70",
1622 => "sdocontents71",
1623 => "sdocontents72",
1624 => "sdocontents73",
1625 => "sdocontents74",
1626 => "sdocontents75",
1627 => "sdocontents76",
1628 => "sdocontents77",
1629 => "sdocontents78",
1630 => "sdocontents79",
1631 => "sdocontents80",
1632 => "sdocontents81",
1633 => "sdocontents82",
1634 => "sdocontents83",
1635 => "sdocontents84",
1636 => "sdocontents85",
1637 => "sdocontents86",
1638 => "sdocontents87",
1639 => "sdocontents88",
1640 => "sdocontents89",
1641 => "sdocontents90",
1642 => "sdocontents91",
1643 => "sdocontents92",
1644 => "sdocontents93",
1645 => "sdocontents94",
1646 => "sdocontents95",
1647 => "sdocontents96",
1648 => "sdocontents97",
1649 => "sdocontents98",
1650 => "sdocontents99",
1651 => "sdocontents100",
1652 => "sdocontents101",
1653 => "sdocontents102",
1654 => "sdocontents103",
1655 => "sdocontents104",
1656 => "sdocontents105",
1657 => "sdocontents106",
1658 => "sdocontents107",
1659 => "sdocontents108",
1660 => "sdocontents109",
1661 => "sdocontents110",
1662 => "sdocontents111",
1663 => "sdocontents112",
1664 => "sdocontents113",
1665 => "sdocontents114",
1666 => "sdocontents115",
1667 => "sdocontents116",
1668 => "sdocontents117",
1669 => "sdocontents118",
1670 => "sdocontents119",
1671 => "sdocontents120",
2048 => "Unei",
2049 => "Doga",
2050 => "KrBahamut",
2051 => "KrIfrit",
2052 => "KrGaruda",
2053 => "KrRamuh",
2054 => "KrOdin",
2055 => "KrUltima",
2056 => "KrMandragora",
2057 => "KrTonberry2",
2058 => "KrExcalibur",
2059 => "KrPhoenix",
2060 => "KrAlexander",
2061 => "KrTitan",
2062 => "KrLeviathan",
2063 => "KrShiva",
2064 => "KrBehemoth",
2065 => "KrGilgamesh",
2066 => "KrSabotender",
2067 => "KrUnicorn",
2068 => "KrRagnarok",
2069 => "KrRamia",
2070 => "KrNewPublic1",
2071 => "KrNewPublic2",
2072 => "KrNewPublic3",
2073 => "KrNewPublic4",
2074 => "KrNewPublic5",
2075 => "KrCarbuncle",
2076 => "KrChocobo",
2077 => "KrMoogle",
2078 => "KrTonberry",
2079 => "KrCaitsith",
2560 => "koreacontents1",
2561 => "koreacontents2",
2562 => "krcontents1",
2563 => "krcontents2",
2564 => "krcontents3",
2565 => "krcontents4",
2566 => "krcontents5",
2567 => "krcontents6",
2568 => "krcontents7",
2569 => "krcontents8",
2570 => "krcontents9",
2571 => "krcontents10",
2572 => "krcontents11",
2573 => "krcontents12",
2574 => "krcontents13",
2575 => "krcontents14",
2576 => "krcontents15",
2577 => "krcontents16",
2578 => "krcontents17",
2579 => "krcontents18",
2580 => "krcontents19",
2581 => "krcontents20",
2582 => "krcontents21",
2583 => "krcontents22",
10000 => "crossworld_range",
10001 => "crossworld",
10002 => "crossworld",
10003 => "crossworld",
10004 => "crossworld",
10005 => "crossworld",
10006 => "crossworld",
10007 => "crossworld",
10008 => "crossworld",
10009 => "crossworld",
10010 => "crossworld",
65534 => "outofrange1",
65535 => "outofrange2",
_ => null,
};
}
public static bool ContainsIgnoreCase(this string haystack, string needle) {
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(haystack, needle, CompareOptions.IgnoreCase) >= 0;
}
public static bool IsValidRegex(this string regex) {
try {
_ = new Regex(regex);
return true;
} catch (ArgumentException) {
return false;
}
}
public static bool IsValidRegex(this string regex, out ArgumentException exception) {
try {
_ = new Regex(regex);
exception = default!;
return true;
} catch (ArgumentException ex) {
exception = ex;
return false;
}
}
}
public class RegexValidator : ValidationRule {
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
if (value is not string text) {
return new ValidationResult(false, "Value is not text.");
}
return text.IsValidRegex(out var ex)
? ValidationResult.ValidResult
: new ValidationResult(false, $"Invalid regular expression: {ex.Message}");
}
}
public class StringWrapper : INotifyPropertyChanged {
private string value;
public string Value {
get => this.value;
set {
this.value = value;
this.OnPropertyChanged(nameof(this.Value));
}
}
public StringWrapper(string value) {
this.value = value;
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? propertyName = null) {
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}