2026-10-08 16:09:04 +08:00
|
|
|
package core
|
2026-09-25 03:56:58 +08:00
|
|
|
|
|
|
|
|
import "strings"
|
|
|
|
|
|
|
|
|
|
// Five bytes per entry, alpha-3 then alpha-2, sorted by alpha-3.
|
|
|
|
|
const iso3166Packed = "ABWAWAFGAFAGOAOAIAAIALAAXALBALANDADAREAEARGARARMAMASMASATAAQ" +
|
|
|
|
|
"ATFTFATGAGAUSAUAUTATAZEAZBDIBIBELBEBENBJBESBQBFABFBGDBDBGRBG" +
|
|
|
|
|
"BHRBHBHSBSBIHBABLMBLBLRBYBLZBZBMUBMBOLBOBRABRBRBBBBRNBNBTNBT" +
|
|
|
|
|
"BVTBVBWABWCAFCFCANCACCKCCCHECHCHLCLCHNCNCIVCICMRCMCODCDCOGCG" +
|
|
|
|
|
"COKCKCOLCOCOMKMCPVCVCRICRCUBCUCUWCWCXRCXCYMKYCYPCYCZECZDEUDE" +
|
|
|
|
|
"DJIDJDMADMDNKDKDOMDODZADZECUECEGYEGERIERESHEHESPESESTEEETHET" +
|
|
|
|
|
"FINFIFJIFJFLKFKFRAFRFROFOFSMFMGABGAGBRGBGEOGEGGYGGGHAGHGIBGI" +
|
|
|
|
|
"GINGNGLPGPGMBGMGNBGWGNQGQGRCGRGRDGDGRLGLGTMGTGUFGFGUMGUGUYGY" +
|
|
|
|
|
"HKGHKHMDHMHNDHNHRVHRHTIHTHUNHUIDNIDIMNIMINDINIOTIOIRLIEIRNIR" +
|
|
|
|
|
"IRQIQISLISISRILITAITJAMJMJEYJEJORJOJPNJPKAZKZKENKEKGZKGKHMKH" +
|
|
|
|
|
"KIRKIKNAKNKORKRKWTKWLAOLALBNLBLBRLRLBYLYLCALCLIELILKALKLSOLS" +
|
|
|
|
|
"LTULTLUXLULVALVMACMOMAFMFMARMAMCOMCMDAMDMDGMGMDVMVMEXMXMHLMH" +
|
|
|
|
|
"MKDMKMLIMLMLTMTMMRMMMNEMEMNGMNMNPMPMOZMZMRTMRMSRMSMTQMQMUSMU" +
|
|
|
|
|
"MWIMWMYSMYMYTYTNAMNANCLNCNERNENFKNFNGANGNICNINIUNUNLDNLNORNO" +
|
|
|
|
|
"NPLNPNRUNRNZLNZOMNOMPAKPKPANPAPCNPNPERPEPHLPHPLWPWPNGPGPOLPL" +
|
|
|
|
|
"PRIPRPRKKPPRTPTPRYPYPSEPSPYFPFQATQAREUREROURORUSRURWARWSAUSA" +
|
|
|
|
|
"SDNSDSENSNSGPSGSGSGSSHNSHSJMSJSLBSBSLESLSLVSVSMRSMSOMSOSPMPM" +
|
|
|
|
|
"SRBRSSSDSSSTPSTSURSRSVKSKSVNSISWESESWZSZSXMSXSYCSCSYRSYTCATC" +
|
|
|
|
|
"TCDTDTGOTGTHATHTJKTJTKLTKTKMTMTLSTLTONTOTTOTTTUNTNTURTRTUVTV" +
|
|
|
|
|
"TWNTWTZATZUGAUGUKRUAUMIUMURYUYUSAUSUZBUZVATVAVCTVCVENVEVGBVG" +
|
|
|
|
|
"VIRVIVNMVNVUTVUWLFWFWSMWSYEMYEZAFZAZMBZMZWEZW"
|
|
|
|
|
|
|
|
|
|
// normalizeRegion folds a country code to the alpha-2 form Dart renders a flag
|
|
|
|
|
// from, or "" when it is not one. Only Gemini reports alpha-3.
|
|
|
|
|
func normalizeRegion(code string) string {
|
|
|
|
|
code = strings.ToUpper(strings.TrimSpace(code))
|
|
|
|
|
switch len(code) {
|
|
|
|
|
case 2:
|
|
|
|
|
if isAsciiUpper(code) {
|
|
|
|
|
return code
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
case 3:
|
|
|
|
|
if !isAsciiUpper(code) {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
low, high := 0, len(iso3166Packed)/5
|
|
|
|
|
for low < high {
|
|
|
|
|
mid := (low + high) / 2
|
|
|
|
|
entry := iso3166Packed[mid*5 : mid*5+3]
|
|
|
|
|
switch {
|
|
|
|
|
case entry < code:
|
|
|
|
|
low = mid + 1
|
|
|
|
|
case entry > code:
|
|
|
|
|
high = mid
|
|
|
|
|
default:
|
|
|
|
|
return iso3166Packed[mid*5+3 : mid*5+5]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
default:
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isAsciiUpper(value string) bool {
|
|
|
|
|
for _, char := range value {
|
|
|
|
|
if char < 'A' || char > 'Z' {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|