vendor: update all dependencies

This commit is contained in:
Nick Craig-Wood
2017-07-23 08:51:42 +01:00
parent 0b6fba34a3
commit eb87cf6f12
2008 changed files with 352617 additions and 1004734 deletions
+783 -782
View File
File diff suppressed because it is too large Load Diff
+110 -112
View File
@@ -10,7 +10,7 @@ type pluralTest struct {
}
var ordinalTests = []pluralTest{ // 59 elements
0: {locales: "af am ar bg bs ce cs da de dsb el es et eu fa fi fy gl he hr hsb id in is iw ja km kn ko ky lt lv ml mn my nb nl pa pl prg pt root ru sh si sk sl sr sw ta te th tr ur uz yue zh zu", form: 0, integer: []string{"0~15", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
0: {locales: "af am ar bg bs ce cs da de dsb el es et eu fa fi fy gl gsw he hr hsb id in is iw ja km kn ko ky lt lv ml mn my nb nl pa pl prg pt root ru sh si sk sl sr sw ta te th tr ur uz yue zh zu", form: 0, integer: []string{"0~15", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
1: {locales: "sv", form: 2, integer: []string{"1", "2", "21", "22", "31", "32", "41", "42", "51", "52", "61", "62", "71", "72", "81", "82", "101", "1001"}, decimal: []string(nil)},
2: {locales: "sv", form: 0, integer: []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
3: {locales: "fil fr ga hy lo mo ms ro tl vi", form: 2, integer: []string{"1"}, decimal: []string(nil)},
@@ -71,122 +71,120 @@ var ordinalTests = []pluralTest{ // 59 elements
58: {locales: "cy", form: 0, integer: []string{"10~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
} // Size: 4272 bytes
var cardinalTests = []pluralTest{ // 115 elements
var cardinalTests = []pluralTest{ // 113 elements
0: {locales: "bm bo dz id ig ii in ja jbo jv jw kde kea km ko lkt lo ms my nqo root sah ses sg th to vi wo yo yue zh", form: 0, integer: []string{"0~15", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
1: {locales: "am as bn fa gu hi kn mr zu", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.0", "0.00~0.04"}},
2: {locales: "am as bn fa gu hi kn mr zu", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"1.1~2.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
3: {locales: "ff fr hy kab", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.5"}},
4: {locales: "ff fr hy kab", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
5: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 2, integer: []string{"1"}, decimal: []string(nil)},
6: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
7: {locales: "si", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0", "0.1", "1.0", "0.00", "0.01", "1.00", "0.000", "0.001", "1.000", "0.0000", "0.0001", "1.0000"}},
8: {locales: "si", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.2~0.9", "1.1~1.8", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
9: {locales: "ak bh guw ln mg nso pa ti wa", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"}},
10: {locales: "ak bh guw ln mg nso pa ti wa", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
11: {locales: "tzm", form: 2, integer: []string{"0", "1", "11~24"}, decimal: []string{"0.0", "1.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0"}},
12: {locales: "tzm", form: 0, integer: []string{"2~10", "100~106", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
13: {locales: "pt", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"}},
14: {locales: "pt", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
5: {locales: "pt", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.5"}},
6: {locales: "pt", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
7: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 2, integer: []string{"1"}, decimal: []string(nil)},
8: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
9: {locales: "si", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0", "0.1", "1.0", "0.00", "0.01", "1.00", "0.000", "0.001", "1.000", "0.0000", "0.0001", "1.0000"}},
10: {locales: "si", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.2~0.9", "1.1~1.8", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
11: {locales: "ak bh guw ln mg nso pa ti wa", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"}},
12: {locales: "ak bh guw ln mg nso pa ti wa", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
13: {locales: "tzm", form: 2, integer: []string{"0", "1", "11~24"}, decimal: []string{"0.0", "1.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0"}},
14: {locales: "tzm", form: 0, integer: []string{"2~10", "100~106", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
15: {locales: "af asa az bem bez bg brx ce cgg chr ckb dv ee el eo es eu fo fur gsw ha haw hu jgo jmc ka kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn nah nb nd ne nn nnh no nr ny nyn om or os pap ps rm rof rwk saq sdh seh sn so sq ss ssy st syr ta te teo tig tk tn tr ts ug uz ve vo vun wae xh xog", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
16: {locales: "af asa az bem bez bg brx ce cgg chr ckb dv ee el eo es eu fo fur gsw ha haw hu jgo jmc ka kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn nah nb nd ne nn nnh no nr ny nyn om or os pap ps rm rof rwk saq sdh seh sn so sq ss ssy st syr ta te teo tig tk tn tr ts ug uz ve vo vun wae xh xog", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
17: {locales: "pt_PT", form: 2, integer: []string{"1"}, decimal: []string(nil)},
18: {locales: "pt_PT", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
19: {locales: "da", form: 2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
20: {locales: "da", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0~3.4", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
21: {locales: "is", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1~1.6", "10.1", "100.1", "1000.1"}},
22: {locales: "is", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
23: {locales: "mk", form: 2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
24: {locales: "mk", form: 0, integer: []string{"0", "2~10", "12~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.2~1.0", "1.2~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
25: {locales: "fil tl", form: 2, integer: []string{"0~3", "5", "7", "8", "10~13", "15", "17", "18", "20", "21", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.3", "0.5", "0.7", "0.8", "1.0~1.3", "1.5", "1.7", "1.8", "2.0", "2.1", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
26: {locales: "fil tl", form: 0, integer: []string{"4", "6", "9", "14", "16", "19", "24", "26", "104", "1004"}, decimal: []string{"0.4", "0.6", "0.9", "1.4", "1.6", "1.9", "2.4", "2.6", "10.4", "100.4", "1000.4"}},
27: {locales: "lv prg", form: 1, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
28: {locales: "lv prg", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.0", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
29: {locales: "lv prg", form: 0, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"0.2~0.9", "1.2~1.9", "10.2", "100.2", "1000.2"}},
30: {locales: "lag", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
31: {locales: "lag", form: 2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
32: {locales: "lag", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
33: {locales: "ksh", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
34: {locales: "ksh", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
35: {locales: "ksh", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
36: {locales: "iu kw naq se sma smi smj smn sms", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
37: {locales: "iu kw naq se sma smi smj smn sms", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
38: {locales: "iu kw naq se sma smi smj smn sms", form: 0, integer: []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
39: {locales: "shi", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.0", "0.00~0.04"}},
40: {locales: "shi", form: 4, integer: []string{"2~10"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "2.00", "3.00", "4.00", "5.00", "6.00", "7.00", "8.00"}},
41: {locales: "shi", form: 0, integer: []string{"11~26", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"1.1~1.9", "2.1~2.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
42: {locales: "mo ro", form: 2, integer: []string{"1"}, decimal: []string(nil)},
43: {locales: "mo ro", form: 4, integer: []string{"0", "2~16", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
44: {locales: "mo ro", form: 0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
45: {locales: "bs hr sh sr", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
46: {locales: "bs hr sh sr", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"0.2~0.4", "1.2~1.4", "2.2~2.4", "3.2~3.4", "4.2~4.4", "5.2", "10.2", "100.2", "1000.2"}},
47: {locales: "bs hr sh sr", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
48: {locales: "gd", form: 2, integer: []string{"1", "11"}, decimal: []string{"1.0", "11.0", "1.00", "11.00", "1.000", "11.000", "1.0000"}},
49: {locales: "gd", form: 3, integer: []string{"2", "12"}, decimal: []string{"2.0", "12.0", "2.00", "12.00", "2.000", "12.000", "2.0000"}},
50: {locales: "gd", form: 4, integer: []string{"3~10", "13~19"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "3.00"}},
51: {locales: "gd", form: 0, integer: []string{"0", "20~34", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
52: {locales: "sl", form: 2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string(nil)},
53: {locales: "sl", form: 3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string(nil)},
54: {locales: "sl", form: 4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
55: {locales: "sl", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
56: {locales: "dsb hsb", form: 2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
57: {locales: "dsb hsb", form: 3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string{"0.2", "1.2", "2.2", "3.2", "4.2", "5.2", "6.2", "7.2", "10.2", "100.2", "1000.2"}},
58: {locales: "dsb hsb", form: 4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.3", "0.4", "1.3", "1.4", "2.3", "2.4", "3.3", "3.4", "4.3", "4.4", "5.3", "5.4", "6.3", "6.4", "7.3", "7.4", "10.3", "100.3", "1000.3"}},
59: {locales: "dsb hsb", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
60: {locales: "he iw", form: 2, integer: []string{"1"}, decimal: []string(nil)},
61: {locales: "he iw", form: 3, integer: []string{"2"}, decimal: []string(nil)},
62: {locales: "he iw", form: 5, integer: []string{"20", "30", "40", "50", "60", "70", "80", "90", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
63: {locales: "he iw", form: 0, integer: []string{"0", "3~17", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
64: {locales: "cs sk", form: 2, integer: []string{"1"}, decimal: []string(nil)},
65: {locales: "cs sk", form: 4, integer: []string{"2~4"}, decimal: []string(nil)},
66: {locales: "cs sk", form: 5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
67: {locales: "cs sk", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
68: {locales: "pl", form: 2, integer: []string{"1"}, decimal: []string(nil)},
69: {locales: "pl", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
70: {locales: "pl", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
71: {locales: "pl", form: 0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
72: {locales: "be", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
73: {locales: "be", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "22.0", "23.0", "24.0", "32.0", "33.0", "102.0", "1002.0"}},
74: {locales: "be", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "11.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
75: {locales: "be", form: 0, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
76: {locales: "lt", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
77: {locales: "lt", form: 4, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "22.0", "102.0", "1002.0"}},
78: {locales: "lt", form: 5, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
79: {locales: "lt", form: 0, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
80: {locales: "mt", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
81: {locales: "mt", form: 4, integer: []string{"0", "2~10", "102~107", "1002"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "102.0", "1002.0"}},
82: {locales: "mt", form: 5, integer: []string{"11~19", "111~117", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
83: {locales: "mt", form: 0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
84: {locales: "ru uk", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string(nil)},
85: {locales: "ru uk", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
86: {locales: "ru uk", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
87: {locales: "ru uk", form: 0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
88: {locales: "br", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "81.0", "101.0", "1001.0"}},
89: {locales: "br", form: 3, integer: []string{"2", "22", "32", "42", "52", "62", "82", "102", "1002"}, decimal: []string{"2.0", "22.0", "32.0", "42.0", "52.0", "62.0", "82.0", "102.0", "1002.0"}},
90: {locales: "br", form: 4, integer: []string{"3", "4", "9", "23", "24", "29", "33", "34", "39", "43", "44", "49", "103", "1003"}, decimal: []string{"3.0", "4.0", "9.0", "23.0", "24.0", "29.0", "33.0", "34.0", "103.0", "1003.0"}},
91: {locales: "br", form: 5, integer: []string{"1000000"}, decimal: []string{"1000000.0", "1000000.00", "1000000.000"}},
92: {locales: "br", form: 0, integer: []string{"0", "5~8", "10~20", "100", "1000", "10000", "100000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0"}},
93: {locales: "ga", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
94: {locales: "ga", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
95: {locales: "ga", form: 4, integer: []string{"3~6"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "3.00", "4.00", "5.00", "6.00", "3.000", "4.000", "5.000", "6.000", "3.0000", "4.0000", "5.0000", "6.0000"}},
96: {locales: "ga", form: 5, integer: []string{"7~10"}, decimal: []string{"7.0", "8.0", "9.0", "10.0", "7.00", "8.00", "9.00", "10.00", "7.000", "8.000", "9.000", "10.000", "7.0000", "8.0000", "9.0000", "10.0000"}},
97: {locales: "ga", form: 0, integer: []string{"0", "11~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
98: {locales: "gv", form: 2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string(nil)},
99: {locales: "gv", form: 3, integer: []string{"2", "12", "22", "32", "42", "52", "62", "72", "102", "1002"}, decimal: []string(nil)},
100: {locales: "gv", form: 4, integer: []string{"0", "20", "40", "60", "80", "100", "120", "140", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
101: {locales: "gv", form: 5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
102: {locales: "gv", form: 0, integer: []string{"3~10", "13~19", "23", "103", "1003"}, decimal: []string(nil)},
103: {locales: "ar ars", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
104: {locales: "ar ars", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
105: {locales: "ar ars", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
106: {locales: "ar ars", form: 4, integer: []string{"3~10", "103~110", "1003"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "103.0", "1003.0"}},
107: {locales: "ar ars", form: 5, integer: []string{"11~26", "111", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
108: {locales: "ar ars", form: 0, integer: []string{"100~102", "200~202", "300~302", "400~402", "500~502", "600", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
109: {locales: "cy", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
110: {locales: "cy", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
111: {locales: "cy", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
112: {locales: "cy", form: 4, integer: []string{"3"}, decimal: []string{"3.0", "3.00", "3.000", "3.0000"}},
113: {locales: "cy", form: 5, integer: []string{"6"}, decimal: []string{"6.0", "6.00", "6.000", "6.0000"}},
114: {locales: "cy", form: 0, integer: []string{"4", "5", "7~20", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
} // Size: 8304 bytes
17: {locales: "da", form: 2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
18: {locales: "da", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0~3.4", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
19: {locales: "is", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1~1.6", "10.1", "100.1", "1000.1"}},
20: {locales: "is", form: 0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
21: {locales: "mk", form: 2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
22: {locales: "mk", form: 0, integer: []string{"0", "2~10", "12~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.2~1.0", "1.2~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
23: {locales: "fil tl", form: 2, integer: []string{"0~3", "5", "7", "8", "10~13", "15", "17", "18", "20", "21", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.3", "0.5", "0.7", "0.8", "1.0~1.3", "1.5", "1.7", "1.8", "2.0", "2.1", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
24: {locales: "fil tl", form: 0, integer: []string{"4", "6", "9", "14", "16", "19", "24", "26", "104", "1004"}, decimal: []string{"0.4", "0.6", "0.9", "1.4", "1.6", "1.9", "2.4", "2.6", "10.4", "100.4", "1000.4"}},
25: {locales: "lv prg", form: 1, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
26: {locales: "lv prg", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.0", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
27: {locales: "lv prg", form: 0, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"0.2~0.9", "1.2~1.9", "10.2", "100.2", "1000.2"}},
28: {locales: "lag", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
29: {locales: "lag", form: 2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
30: {locales: "lag", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
31: {locales: "ksh", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
32: {locales: "ksh", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
33: {locales: "ksh", form: 0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
34: {locales: "iu kw naq se sma smi smj smn sms", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
35: {locales: "iu kw naq se sma smi smj smn sms", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
36: {locales: "iu kw naq se sma smi smj smn sms", form: 0, integer: []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
37: {locales: "shi", form: 2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.0", "0.00~0.04"}},
38: {locales: "shi", form: 4, integer: []string{"2~10"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "2.00", "3.00", "4.00", "5.00", "6.00", "7.00", "8.00"}},
39: {locales: "shi", form: 0, integer: []string{"11~26", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"1.1~1.9", "2.1~2.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
40: {locales: "mo ro", form: 2, integer: []string{"1"}, decimal: []string(nil)},
41: {locales: "mo ro", form: 4, integer: []string{"0", "2~16", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
42: {locales: "mo ro", form: 0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
43: {locales: "bs hr sh sr", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
44: {locales: "bs hr sh sr", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"0.2~0.4", "1.2~1.4", "2.2~2.4", "3.2~3.4", "4.2~4.4", "5.2", "10.2", "100.2", "1000.2"}},
45: {locales: "bs hr sh sr", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
46: {locales: "gd", form: 2, integer: []string{"1", "11"}, decimal: []string{"1.0", "11.0", "1.00", "11.00", "1.000", "11.000", "1.0000"}},
47: {locales: "gd", form: 3, integer: []string{"2", "12"}, decimal: []string{"2.0", "12.0", "2.00", "12.00", "2.000", "12.000", "2.0000"}},
48: {locales: "gd", form: 4, integer: []string{"3~10", "13~19"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "3.00"}},
49: {locales: "gd", form: 0, integer: []string{"0", "20~34", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
50: {locales: "sl", form: 2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string(nil)},
51: {locales: "sl", form: 3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string(nil)},
52: {locales: "sl", form: 4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
53: {locales: "sl", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
54: {locales: "dsb hsb", form: 2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
55: {locales: "dsb hsb", form: 3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string{"0.2", "1.2", "2.2", "3.2", "4.2", "5.2", "6.2", "7.2", "10.2", "100.2", "1000.2"}},
56: {locales: "dsb hsb", form: 4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.3", "0.4", "1.3", "1.4", "2.3", "2.4", "3.3", "3.4", "4.3", "4.4", "5.3", "5.4", "6.3", "6.4", "7.3", "7.4", "10.3", "100.3", "1000.3"}},
57: {locales: "dsb hsb", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
58: {locales: "he iw", form: 2, integer: []string{"1"}, decimal: []string(nil)},
59: {locales: "he iw", form: 3, integer: []string{"2"}, decimal: []string(nil)},
60: {locales: "he iw", form: 5, integer: []string{"20", "30", "40", "50", "60", "70", "80", "90", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
61: {locales: "he iw", form: 0, integer: []string{"0", "3~17", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
62: {locales: "cs sk", form: 2, integer: []string{"1"}, decimal: []string(nil)},
63: {locales: "cs sk", form: 4, integer: []string{"2~4"}, decimal: []string(nil)},
64: {locales: "cs sk", form: 5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
65: {locales: "cs sk", form: 0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
66: {locales: "pl", form: 2, integer: []string{"1"}, decimal: []string(nil)},
67: {locales: "pl", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
68: {locales: "pl", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
69: {locales: "pl", form: 0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
70: {locales: "be", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
71: {locales: "be", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "22.0", "23.0", "24.0", "32.0", "33.0", "102.0", "1002.0"}},
72: {locales: "be", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "11.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
73: {locales: "be", form: 0, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
74: {locales: "lt", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
75: {locales: "lt", form: 4, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "22.0", "102.0", "1002.0"}},
76: {locales: "lt", form: 5, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
77: {locales: "lt", form: 0, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
78: {locales: "mt", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
79: {locales: "mt", form: 4, integer: []string{"0", "2~10", "102~107", "1002"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "102.0", "1002.0"}},
80: {locales: "mt", form: 5, integer: []string{"11~19", "111~117", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
81: {locales: "mt", form: 0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
82: {locales: "ru uk", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string(nil)},
83: {locales: "ru uk", form: 4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
84: {locales: "ru uk", form: 5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
85: {locales: "ru uk", form: 0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
86: {locales: "br", form: 2, integer: []string{"1", "21", "31", "41", "51", "61", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "81.0", "101.0", "1001.0"}},
87: {locales: "br", form: 3, integer: []string{"2", "22", "32", "42", "52", "62", "82", "102", "1002"}, decimal: []string{"2.0", "22.0", "32.0", "42.0", "52.0", "62.0", "82.0", "102.0", "1002.0"}},
88: {locales: "br", form: 4, integer: []string{"3", "4", "9", "23", "24", "29", "33", "34", "39", "43", "44", "49", "103", "1003"}, decimal: []string{"3.0", "4.0", "9.0", "23.0", "24.0", "29.0", "33.0", "34.0", "103.0", "1003.0"}},
89: {locales: "br", form: 5, integer: []string{"1000000"}, decimal: []string{"1000000.0", "1000000.00", "1000000.000"}},
90: {locales: "br", form: 0, integer: []string{"0", "5~8", "10~20", "100", "1000", "10000", "100000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0"}},
91: {locales: "ga", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
92: {locales: "ga", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
93: {locales: "ga", form: 4, integer: []string{"3~6"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "3.00", "4.00", "5.00", "6.00", "3.000", "4.000", "5.000", "6.000", "3.0000", "4.0000", "5.0000", "6.0000"}},
94: {locales: "ga", form: 5, integer: []string{"7~10"}, decimal: []string{"7.0", "8.0", "9.0", "10.0", "7.00", "8.00", "9.00", "10.00", "7.000", "8.000", "9.000", "10.000", "7.0000", "8.0000", "9.0000", "10.0000"}},
95: {locales: "ga", form: 0, integer: []string{"0", "11~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
96: {locales: "gv", form: 2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string(nil)},
97: {locales: "gv", form: 3, integer: []string{"2", "12", "22", "32", "42", "52", "62", "72", "102", "1002"}, decimal: []string(nil)},
98: {locales: "gv", form: 4, integer: []string{"0", "20", "40", "60", "80", "100", "120", "140", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
99: {locales: "gv", form: 5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
100: {locales: "gv", form: 0, integer: []string{"3~10", "13~19", "23", "103", "1003"}, decimal: []string(nil)},
101: {locales: "ar ars", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
102: {locales: "ar ars", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
103: {locales: "ar ars", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
104: {locales: "ar ars", form: 4, integer: []string{"3~10", "103~110", "1003"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "103.0", "1003.0"}},
105: {locales: "ar ars", form: 5, integer: []string{"11~26", "111", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
106: {locales: "ar ars", form: 0, integer: []string{"100~102", "200~202", "300~302", "400~402", "500~502", "600", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
107: {locales: "cy", form: 1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
108: {locales: "cy", form: 2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
109: {locales: "cy", form: 3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
110: {locales: "cy", form: 4, integer: []string{"3"}, decimal: []string{"3.0", "3.00", "3.000", "3.0000"}},
111: {locales: "cy", form: 5, integer: []string{"6"}, decimal: []string{"6.0", "6.00", "6.000", "6.0000"}},
112: {locales: "cy", form: 0, integer: []string{"4", "5", "7~20", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
} // Size: 8160 bytes
// Total table size 12576 bytes (12KiB); checksum: 166DAB75
// Total table size 12432 bytes (12KiB); checksum: 166DAB71
+309 -310
View File
@@ -3,7 +3,7 @@
package plural
// CLDRVersion is the CLDR version from which the tables in this package are derived.
const CLDRVersion = "30"
const CLDRVersion = "31"
var ordinalRules = []pluralCheck{ // 58 elements
0: {cat: 0x2f, setID: 0x4},
@@ -72,7 +72,7 @@ var ordinalIndex = []uint8{ // 20 elements
0x2d, 0x31, 0x35, 0x3a,
} // Size: 44 bytes
var ordinalLangToIndex = []uint8{ // 752 elements
var ordinalLangToIndex = []uint8{ // 754 elements
// Entry 0 - 3F
0x00, 0x0d, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -113,40 +113,40 @@ var ordinalLangToIndex = []uint8{ // 752 elements
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 140 - 17F
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 180 - 1BF
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 1C0 - 1FF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0e,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x02, 0x02,
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 200 - 23F
0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -155,31 +155,32 @@ var ordinalLangToIndex = []uint8{ // 752 elements
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 240 - 27F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
// Entry 280 - 2BF
0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00,
// Entry 2C0 - 2FF
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
} // Size: 776 bytes
0x00, 0x00,
} // Size: 778 bytes
var ordinalInclusionMasks = []uint64{ // 100 elements
// Entry 0 - 1F
@@ -215,327 +216,325 @@ var ordinalInclusionMasks = []uint64{ // 100 elements
// Slots used for ordinal: 3A of 0xFF rules; 14 of 0xFF indexes; 37 of 64 sets
var cardinalRules = []pluralCheck{ // 169 elements
var cardinalRules = []pluralCheck{ // 166 elements
0: {cat: 0x2, setID: 0x3},
1: {cat: 0x22, setID: 0x1},
2: {cat: 0x2, setID: 0x4},
3: {cat: 0x7, setID: 0x1},
4: {cat: 0x62, setID: 0x3},
5: {cat: 0x22, setID: 0x4},
6: {cat: 0x7, setID: 0x3},
7: {cat: 0x42, setID: 0x1},
8: {cat: 0x22, setID: 0x4},
3: {cat: 0x2, setID: 0x4},
4: {cat: 0x7, setID: 0x1},
5: {cat: 0x62, setID: 0x3},
6: {cat: 0x22, setID: 0x4},
7: {cat: 0x7, setID: 0x3},
8: {cat: 0x42, setID: 0x1},
9: {cat: 0x22, setID: 0x4},
10: {cat: 0x22, setID: 0x5},
11: {cat: 0x27, setID: 0x6},
12: {cat: 0x32, setID: 0x2},
10: {cat: 0x22, setID: 0x4},
11: {cat: 0x22, setID: 0x5},
12: {cat: 0x22, setID: 0x1},
13: {cat: 0x22, setID: 0x1},
14: {cat: 0x27, setID: 0x1},
15: {cat: 0x62, setID: 0x3},
16: {cat: 0x22, setID: 0x1},
17: {cat: 0x7, setID: 0x4},
18: {cat: 0x92, setID: 0x3},
19: {cat: 0xf, setID: 0x7},
20: {cat: 0x1f, setID: 0x8},
21: {cat: 0x82, setID: 0x3},
22: {cat: 0x92, setID: 0x3},
23: {cat: 0xf, setID: 0x7},
14: {cat: 0x7, setID: 0x4},
15: {cat: 0x92, setID: 0x3},
16: {cat: 0xf, setID: 0x6},
17: {cat: 0x1f, setID: 0x7},
18: {cat: 0x82, setID: 0x3},
19: {cat: 0x92, setID: 0x3},
20: {cat: 0xf, setID: 0x6},
21: {cat: 0x62, setID: 0x3},
22: {cat: 0x4a, setID: 0x6},
23: {cat: 0x7, setID: 0x8},
24: {cat: 0x62, setID: 0x3},
25: {cat: 0x4a, setID: 0x7},
26: {cat: 0x7, setID: 0x9},
27: {cat: 0x62, setID: 0x3},
28: {cat: 0x1f, setID: 0xa},
29: {cat: 0x62, setID: 0x3},
30: {cat: 0x5f, setID: 0xa},
31: {cat: 0x72, setID: 0x3},
32: {cat: 0x29, setID: 0xb},
33: {cat: 0x29, setID: 0xc},
34: {cat: 0x4f, setID: 0xc},
35: {cat: 0x61, setID: 0x2},
36: {cat: 0x2f, setID: 0x7},
37: {cat: 0x3a, setID: 0x8},
38: {cat: 0x4f, setID: 0x7},
39: {cat: 0x5f, setID: 0x8},
40: {cat: 0x62, setID: 0x2},
41: {cat: 0x4f, setID: 0x7},
42: {cat: 0x72, setID: 0x2},
25: {cat: 0x1f, setID: 0x9},
26: {cat: 0x62, setID: 0x3},
27: {cat: 0x5f, setID: 0x9},
28: {cat: 0x72, setID: 0x3},
29: {cat: 0x29, setID: 0xa},
30: {cat: 0x29, setID: 0xb},
31: {cat: 0x4f, setID: 0xb},
32: {cat: 0x61, setID: 0x2},
33: {cat: 0x2f, setID: 0x6},
34: {cat: 0x3a, setID: 0x7},
35: {cat: 0x4f, setID: 0x6},
36: {cat: 0x5f, setID: 0x7},
37: {cat: 0x62, setID: 0x2},
38: {cat: 0x4f, setID: 0x6},
39: {cat: 0x72, setID: 0x2},
40: {cat: 0x21, setID: 0x3},
41: {cat: 0x7, setID: 0x4},
42: {cat: 0x32, setID: 0x3},
43: {cat: 0x21, setID: 0x3},
44: {cat: 0x7, setID: 0x4},
45: {cat: 0x32, setID: 0x3},
46: {cat: 0x21, setID: 0x3},
47: {cat: 0x22, setID: 0x1},
44: {cat: 0x22, setID: 0x1},
45: {cat: 0x22, setID: 0x1},
46: {cat: 0x23, setID: 0x2},
47: {cat: 0x2, setID: 0x3},
48: {cat: 0x22, setID: 0x1},
49: {cat: 0x23, setID: 0x2},
50: {cat: 0x2, setID: 0x3},
51: {cat: 0x22, setID: 0x1},
52: {cat: 0x24, setID: 0xd},
53: {cat: 0x7, setID: 0x1},
54: {cat: 0x62, setID: 0x3},
55: {cat: 0x74, setID: 0x3},
56: {cat: 0x24, setID: 0x3},
57: {cat: 0x2f, setID: 0xe},
58: {cat: 0x34, setID: 0x1},
59: {cat: 0xf, setID: 0x7},
60: {cat: 0x1f, setID: 0x8},
61: {cat: 0x62, setID: 0x3},
62: {cat: 0x4f, setID: 0x7},
63: {cat: 0x5a, setID: 0x8},
64: {cat: 0xf, setID: 0xf},
65: {cat: 0x1f, setID: 0x10},
66: {cat: 0x64, setID: 0x3},
67: {cat: 0x4f, setID: 0xf},
68: {cat: 0x5c, setID: 0x10},
69: {cat: 0x22, setID: 0x11},
70: {cat: 0x23, setID: 0x12},
71: {cat: 0x24, setID: 0x13},
72: {cat: 0xf, setID: 0x1},
73: {cat: 0x62, setID: 0x3},
74: {cat: 0xf, setID: 0x2},
75: {cat: 0x63, setID: 0x3},
76: {cat: 0xf, setID: 0x14},
77: {cat: 0x64, setID: 0x3},
78: {cat: 0x74, setID: 0x3},
79: {cat: 0xf, setID: 0x1},
80: {cat: 0x62, setID: 0x3},
81: {cat: 0x4a, setID: 0x1},
82: {cat: 0xf, setID: 0x2},
83: {cat: 0x63, setID: 0x3},
84: {cat: 0x4b, setID: 0x2},
85: {cat: 0xf, setID: 0x14},
86: {cat: 0x64, setID: 0x3},
87: {cat: 0x4c, setID: 0x14},
88: {cat: 0x7, setID: 0x1},
89: {cat: 0x62, setID: 0x3},
90: {cat: 0x7, setID: 0x2},
91: {cat: 0x63, setID: 0x3},
92: {cat: 0x2f, setID: 0xb},
93: {cat: 0x37, setID: 0x15},
94: {cat: 0x65, setID: 0x3},
95: {cat: 0x7, setID: 0x1},
96: {cat: 0x62, setID: 0x3},
97: {cat: 0x7, setID: 0x16},
98: {cat: 0x64, setID: 0x3},
99: {cat: 0x75, setID: 0x3},
100: {cat: 0x7, setID: 0x1},
101: {cat: 0x62, setID: 0x3},
102: {cat: 0xf, setID: 0xf},
103: {cat: 0x1f, setID: 0x10},
104: {cat: 0x64, setID: 0x3},
49: {cat: 0x24, setID: 0xc},
50: {cat: 0x7, setID: 0x1},
51: {cat: 0x62, setID: 0x3},
52: {cat: 0x74, setID: 0x3},
53: {cat: 0x24, setID: 0x3},
54: {cat: 0x2f, setID: 0xd},
55: {cat: 0x34, setID: 0x1},
56: {cat: 0xf, setID: 0x6},
57: {cat: 0x1f, setID: 0x7},
58: {cat: 0x62, setID: 0x3},
59: {cat: 0x4f, setID: 0x6},
60: {cat: 0x5a, setID: 0x7},
61: {cat: 0xf, setID: 0xe},
62: {cat: 0x1f, setID: 0xf},
63: {cat: 0x64, setID: 0x3},
64: {cat: 0x4f, setID: 0xe},
65: {cat: 0x5c, setID: 0xf},
66: {cat: 0x22, setID: 0x10},
67: {cat: 0x23, setID: 0x11},
68: {cat: 0x24, setID: 0x12},
69: {cat: 0xf, setID: 0x1},
70: {cat: 0x62, setID: 0x3},
71: {cat: 0xf, setID: 0x2},
72: {cat: 0x63, setID: 0x3},
73: {cat: 0xf, setID: 0x13},
74: {cat: 0x64, setID: 0x3},
75: {cat: 0x74, setID: 0x3},
76: {cat: 0xf, setID: 0x1},
77: {cat: 0x62, setID: 0x3},
78: {cat: 0x4a, setID: 0x1},
79: {cat: 0xf, setID: 0x2},
80: {cat: 0x63, setID: 0x3},
81: {cat: 0x4b, setID: 0x2},
82: {cat: 0xf, setID: 0x13},
83: {cat: 0x64, setID: 0x3},
84: {cat: 0x4c, setID: 0x13},
85: {cat: 0x7, setID: 0x1},
86: {cat: 0x62, setID: 0x3},
87: {cat: 0x7, setID: 0x2},
88: {cat: 0x63, setID: 0x3},
89: {cat: 0x2f, setID: 0xa},
90: {cat: 0x37, setID: 0x14},
91: {cat: 0x65, setID: 0x3},
92: {cat: 0x7, setID: 0x1},
93: {cat: 0x62, setID: 0x3},
94: {cat: 0x7, setID: 0x15},
95: {cat: 0x64, setID: 0x3},
96: {cat: 0x75, setID: 0x3},
97: {cat: 0x7, setID: 0x1},
98: {cat: 0x62, setID: 0x3},
99: {cat: 0xf, setID: 0xe},
100: {cat: 0x1f, setID: 0xf},
101: {cat: 0x64, setID: 0x3},
102: {cat: 0xf, setID: 0x16},
103: {cat: 0x17, setID: 0x1},
104: {cat: 0x65, setID: 0x3},
105: {cat: 0xf, setID: 0x17},
106: {cat: 0x17, setID: 0x1},
107: {cat: 0x65, setID: 0x3},
108: {cat: 0xf, setID: 0x18},
109: {cat: 0x65, setID: 0x3},
110: {cat: 0xf, setID: 0x10},
111: {cat: 0x65, setID: 0x3},
112: {cat: 0x2f, setID: 0x7},
113: {cat: 0x3a, setID: 0x8},
114: {cat: 0x2f, setID: 0xf},
115: {cat: 0x3c, setID: 0x10},
116: {cat: 0x2d, setID: 0xb},
117: {cat: 0x2d, setID: 0x18},
118: {cat: 0x2d, setID: 0x19},
119: {cat: 0x2f, setID: 0x7},
120: {cat: 0x3a, setID: 0xc},
121: {cat: 0x2f, setID: 0x1a},
122: {cat: 0x3c, setID: 0xc},
123: {cat: 0x55, setID: 0x3},
124: {cat: 0x22, setID: 0x1},
125: {cat: 0x24, setID: 0x3},
126: {cat: 0x2c, setID: 0xd},
127: {cat: 0x2d, setID: 0xc},
128: {cat: 0xf, setID: 0x7},
129: {cat: 0x1f, setID: 0x8},
130: {cat: 0x62, setID: 0x3},
131: {cat: 0xf, setID: 0xf},
132: {cat: 0x1f, setID: 0x10},
133: {cat: 0x64, setID: 0x3},
134: {cat: 0xf, setID: 0xb},
135: {cat: 0x65, setID: 0x3},
136: {cat: 0xf, setID: 0x18},
137: {cat: 0x65, setID: 0x3},
138: {cat: 0xf, setID: 0x19},
139: {cat: 0x65, setID: 0x3},
140: {cat: 0x2f, setID: 0x7},
141: {cat: 0x3a, setID: 0x1b},
142: {cat: 0x2f, setID: 0x1c},
143: {cat: 0x3b, setID: 0x1d},
144: {cat: 0x2f, setID: 0x1e},
145: {cat: 0x3c, setID: 0x1f},
146: {cat: 0x37, setID: 0x3},
147: {cat: 0xa5, setID: 0x0},
148: {cat: 0x22, setID: 0x1},
149: {cat: 0x23, setID: 0x2},
150: {cat: 0x24, setID: 0x20},
151: {cat: 0x25, setID: 0x21},
152: {cat: 0xf, setID: 0x7},
153: {cat: 0x62, setID: 0x3},
154: {cat: 0xf, setID: 0x1c},
155: {cat: 0x63, setID: 0x3},
156: {cat: 0xf, setID: 0x22},
157: {cat: 0x64, setID: 0x3},
158: {cat: 0x75, setID: 0x3},
159: {cat: 0x21, setID: 0x3},
160: {cat: 0x22, setID: 0x1},
161: {cat: 0x23, setID: 0x2},
162: {cat: 0x2c, setID: 0x23},
163: {cat: 0x2d, setID: 0x5},
164: {cat: 0x21, setID: 0x3},
165: {cat: 0x22, setID: 0x1},
166: {cat: 0x23, setID: 0x2},
167: {cat: 0x24, setID: 0x24},
168: {cat: 0x25, setID: 0x25},
} // Size: 362 bytes
106: {cat: 0x65, setID: 0x3},
107: {cat: 0xf, setID: 0xf},
108: {cat: 0x65, setID: 0x3},
109: {cat: 0x2f, setID: 0x6},
110: {cat: 0x3a, setID: 0x7},
111: {cat: 0x2f, setID: 0xe},
112: {cat: 0x3c, setID: 0xf},
113: {cat: 0x2d, setID: 0xa},
114: {cat: 0x2d, setID: 0x17},
115: {cat: 0x2d, setID: 0x18},
116: {cat: 0x2f, setID: 0x6},
117: {cat: 0x3a, setID: 0xb},
118: {cat: 0x2f, setID: 0x19},
119: {cat: 0x3c, setID: 0xb},
120: {cat: 0x55, setID: 0x3},
121: {cat: 0x22, setID: 0x1},
122: {cat: 0x24, setID: 0x3},
123: {cat: 0x2c, setID: 0xc},
124: {cat: 0x2d, setID: 0xb},
125: {cat: 0xf, setID: 0x6},
126: {cat: 0x1f, setID: 0x7},
127: {cat: 0x62, setID: 0x3},
128: {cat: 0xf, setID: 0xe},
129: {cat: 0x1f, setID: 0xf},
130: {cat: 0x64, setID: 0x3},
131: {cat: 0xf, setID: 0xa},
132: {cat: 0x65, setID: 0x3},
133: {cat: 0xf, setID: 0x17},
134: {cat: 0x65, setID: 0x3},
135: {cat: 0xf, setID: 0x18},
136: {cat: 0x65, setID: 0x3},
137: {cat: 0x2f, setID: 0x6},
138: {cat: 0x3a, setID: 0x1a},
139: {cat: 0x2f, setID: 0x1b},
140: {cat: 0x3b, setID: 0x1c},
141: {cat: 0x2f, setID: 0x1d},
142: {cat: 0x3c, setID: 0x1e},
143: {cat: 0x37, setID: 0x3},
144: {cat: 0xa5, setID: 0x0},
145: {cat: 0x22, setID: 0x1},
146: {cat: 0x23, setID: 0x2},
147: {cat: 0x24, setID: 0x1f},
148: {cat: 0x25, setID: 0x20},
149: {cat: 0xf, setID: 0x6},
150: {cat: 0x62, setID: 0x3},
151: {cat: 0xf, setID: 0x1b},
152: {cat: 0x63, setID: 0x3},
153: {cat: 0xf, setID: 0x21},
154: {cat: 0x64, setID: 0x3},
155: {cat: 0x75, setID: 0x3},
156: {cat: 0x21, setID: 0x3},
157: {cat: 0x22, setID: 0x1},
158: {cat: 0x23, setID: 0x2},
159: {cat: 0x2c, setID: 0x22},
160: {cat: 0x2d, setID: 0x5},
161: {cat: 0x21, setID: 0x3},
162: {cat: 0x22, setID: 0x1},
163: {cat: 0x23, setID: 0x2},
164: {cat: 0x24, setID: 0x23},
165: {cat: 0x25, setID: 0x24},
} // Size: 356 bytes
var cardinalIndex = []uint8{ // 37 elements
0x00, 0x00, 0x02, 0x03, 0x05, 0x08, 0x09, 0x0b,
0x0d, 0x0e, 0x10, 0x13, 0x17, 0x1a, 0x20, 0x2b,
0x2e, 0x30, 0x32, 0x35, 0x3b, 0x45, 0x48, 0x4f,
0x58, 0x5f, 0x64, 0x70, 0x77, 0x7c, 0x80, 0x8c,
0x94, 0x98, 0x9f, 0xa4, 0xa9,
} // Size: 61 bytes
var cardinalIndex = []uint8{ // 36 elements
0x00, 0x00, 0x02, 0x03, 0x04, 0x06, 0x09, 0x0a,
0x0c, 0x0d, 0x10, 0x14, 0x17, 0x1d, 0x28, 0x2b,
0x2d, 0x2f, 0x32, 0x38, 0x42, 0x45, 0x4c, 0x55,
0x5c, 0x61, 0x6d, 0x74, 0x79, 0x7d, 0x89, 0x91,
0x95, 0x9c, 0xa1, 0xa6,
} // Size: 60 bytes
var cardinalLangToIndex = []uint8{ // 752 elements
var cardinalLangToIndex = []uint8{ // 754 elements
// Entry 0 - 3F
0x00, 0x03, 0x03, 0x08, 0x08, 0x08, 0x00, 0x00,
0x05, 0x05, 0x01, 0x01, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x01, 0x01, 0x08, 0x08, 0x03, 0x03,
0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x1b,
0x1b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x05,
0x00, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00,
0x06, 0x06, 0x01, 0x01, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x01, 0x01, 0x08, 0x08, 0x04, 0x04,
0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x1a,
0x1a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06,
// Entry 40 - 7F
0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x1f, 0x1f, 0x08, 0x08, 0x14, 0x00, 0x00, 0x14,
0x14, 0x03, 0x03, 0x03, 0x03, 0x03, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x19,
0x19, 0x00, 0x00, 0x23, 0x23, 0x0a, 0x0a, 0x0a,
0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x00, 0x00, 0x17, 0x17, 0x00, 0x00,
0x1e, 0x1e, 0x08, 0x08, 0x13, 0x00, 0x00, 0x13,
0x13, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18,
0x18, 0x00, 0x00, 0x22, 0x22, 0x09, 0x09, 0x09,
0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x00, 0x00, 0x16, 0x16, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
// Entry 80 - BF
0x08, 0x08, 0x08, 0x08, 0x08, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry C0 - FF
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x08, 0x08,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
// Entry 100 - 13F
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x03, 0x03, 0x08, 0x08,
0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
0x02, 0x02, 0x03, 0x03, 0x0d, 0x0d, 0x08, 0x08,
0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x08,
0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
0x02, 0x02, 0x02, 0x04, 0x04, 0x0c, 0x0c, 0x08,
0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 140 - 17F
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x08, 0x08, 0x03, 0x03, 0x20, 0x20, 0x15, 0x15,
0x03, 0x03, 0x08, 0x08, 0x08, 0x08, 0x01, 0x01,
0x05, 0x00, 0x00, 0x21, 0x21, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x18, 0x18, 0x01, 0x01, 0x14,
0x14, 0x14, 0x17, 0x17, 0x08, 0x08, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0b,
0x02, 0x08, 0x08, 0x04, 0x04, 0x1f, 0x1f, 0x14,
0x14, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x01,
0x01, 0x06, 0x00, 0x00, 0x20, 0x20, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x17, 0x17, 0x01, 0x01,
0x13, 0x13, 0x13, 0x16, 0x16, 0x08, 0x08, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
// Entry 180 - 1BF
0x03, 0x03, 0x03, 0x03, 0x11, 0x00, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x02,
0x02, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x08, 0x11,
0x11, 0x08, 0x08, 0x0f, 0x0f, 0x08, 0x08, 0x08,
0x0a, 0x04, 0x04, 0x04, 0x04, 0x04, 0x10, 0x00,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
0x08, 0x02, 0x02, 0x08, 0x00, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0f, 0x0f,
0x08, 0x10, 0x10, 0x08, 0x08, 0x0e, 0x0e, 0x08,
// Entry 1C0 - 1FF
0x08, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0e, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
0x00, 0x00, 0x08, 0x08, 0x0c, 0x0c, 0x08, 0x08,
0x08, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x1d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x11, 0x11, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x00, 0x00, 0x06, 0x06, 0x06,
0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
0x0d, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x08, 0x08, 0x0b, 0x0b,
0x08, 0x08, 0x08, 0x08, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x10, 0x10, 0x08, 0x08, 0x08,
// Entry 200 - 23F
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x05,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x05, 0x00, 0x00,
0x05, 0x05, 0x08, 0x1a, 0x1a, 0x0e, 0x0e, 0x08,
0x08, 0x07, 0x09, 0x07, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00,
0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x08, 0x06, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06,
0x00, 0x00, 0x06, 0x06, 0x08, 0x19, 0x19, 0x0d,
0x0d, 0x08, 0x08, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
// Entry 240 - 27F
0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x13, 0x13,
0x13, 0x08, 0x08, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x1e, 0x1e, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
0x08, 0x08, 0x00, 0x00, 0x08, 0x11, 0x11, 0x11,
0x11, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x12,
0x00, 0x00, 0x12, 0x12, 0x04, 0x04, 0x19, 0x19,
0x16, 0x16, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
// Entry 280 - 2BF
0x08, 0x08, 0x08, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x08, 0x08,
0x08, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x05,
0x05, 0x05, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x06, 0x06,
0x08, 0x08, 0x1e, 0x1e, 0x03, 0x03, 0x03, 0x08,
// Entry 2C0 - 2FF
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x05, 0x08, 0x08, 0x00, 0x08, 0x08,
0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
0x12, 0x12, 0x12, 0x08, 0x08, 0x1d, 0x1d, 0x1d,
0x1d, 0x1d, 0x1d, 0x1d, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10,
0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x11, 0x00, 0x00, 0x11, 0x11, 0x05, 0x05,
0x18, 0x18, 0x15, 0x15, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
// Entry 280 - 2BF
0x08, 0x08, 0x08, 0x08, 0x08, 0x13, 0x13, 0x13,
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x00, 0x06, 0x06, 0x06, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x07, 0x07, 0x08, 0x08, 0x1d, 0x1d, 0x04, 0x04,
// Entry 2C0 - 2FF
0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x00,
0x08, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
} // Size: 776 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01,
} // Size: 778 bytes
var cardinalInclusionMasks = []uint64{ // 100 elements
// Entry 0 - 1F
0x0000000400a00859, 0x0000000000a242d3, 0x000000001464e245, 0x000000194478e201,
0x000000094478e401, 0x0000000905286001, 0x0000002905286401, 0x0000000a05286001,
0x0000000a05286001, 0x0000000a45286401, 0x0000000a80a86801, 0x000000008a8251a1,
0x00000000b605d021, 0x00000000c609d021, 0x00000000c609d421, 0x0000000085085021,
0x0000000085085421, 0x0000000085085021, 0x0000000085085021, 0x00000000c5085421,
0x0000000400800821, 0x00000000008000a1, 0x0000000014008021, 0x0000000044008021,
0x0000000044008421, 0x0000000005000021, 0x0000000005000421, 0x0000000005000021,
0x0000000005000021, 0x0000000045000421, 0x0000000000800821, 0x00000000008000a1,
0x0000000200500419, 0x0000000000512153, 0x000000000a327105, 0x0000000ca23c7101,
0x00000004a23c7201, 0x0000000482943001, 0x0000001482943201, 0x0000000502943001,
0x0000000502943001, 0x0000000522943201, 0x0000000540543401, 0x00000000454128e1,
0x000000005b02e821, 0x000000006304e821, 0x000000006304ea21, 0x0000000042842821,
0x0000000042842a21, 0x0000000042842821, 0x0000000042842821, 0x0000000062842a21,
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
// Entry 20 - 3F
0x0000000014008021, 0x0000000044008021, 0x0000000044008421, 0x0000000005000021,
0x0000000005000421, 0x0000000005000021, 0x0000000005000021, 0x0000000045000421,
0x0000000400800821, 0x00000000008000a1, 0x0000000014008021, 0x0000000044008021,
0x0000000044008421, 0x0000000005000021, 0x0000000005000421, 0x0000000005000021,
0x0000000005000021, 0x0000000045000421, 0x0000000000800821, 0x00000000008000a1,
0x0000000014008021, 0x0000000044008021, 0x0000000044008421, 0x0000000005000021,
0x0000000005000421, 0x0000000005000021, 0x0000000005000021, 0x0000000045000421,
0x0000000400800821, 0x00000000008000a1, 0x0000000014008021, 0x0000000044008021,
0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
// Entry 40 - 5F
0x0000000044008421, 0x0000000005000021, 0x0000000005000421, 0x0000000005000021,
0x0000000005000021, 0x0000000045000421, 0x0000000080800821, 0x00000000888000a1,
0x00000000b4008021, 0x00000000c4008021, 0x00000000c4008421, 0x0000000085000021,
0x0000000085000421, 0x0000000085000021, 0x0000000085000021, 0x00000000c5000421,
0x0000000400800821, 0x00000000008000a1, 0x0000000014008021, 0x0000000044008021,
0x0000000044008421, 0x0000000005000021, 0x0000000005000421, 0x0000000005000021,
0x0000000005000021, 0x0000000045000421, 0x0000000080800821, 0x00000000888000a1,
0x00000000b4008021, 0x00000000c4008021, 0x00000000c4008421, 0x0000000085000021,
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
// Entry 60 - 7F
0x0000000085000421, 0x0000000085000021, 0x0000000085000021, 0x00000000c5000421,
0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
} // Size: 824 bytes
// Slots used for cardinal: A9 of 0xFF rules; 25 of 0xFF indexes; 38 of 64 sets
// Slots used for cardinal: A6 of 0xFF rules; 24 of 0xFF indexes; 37 of 64 sets
// Total table size 3807 bytes (3KiB); checksum: A9B90899
// Total table size 3804 bytes (3KiB); checksum: FFC009FC
+366
View File
@@ -0,0 +1,366 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package catmsg contains support types for package x/text/message/catalog.
//
// This package contains the low-level implementations of Message used by the
// catalog package and provides primitives for other packages to implement their
// own. For instance, the plural package provides functionality for selecting
// translation strings based on the plural category of substitution arguments.
//
//
// Encoding and Decoding
//
// Catalogs store Messages encoded as a single string. Compiling a message into
// a string both results in compacter representation and speeds up evaluation.
//
// A Message must implement a Compile method to convert its arbitrary
// representation to a string. The Compile method takes an Encoder which
// facilitates serializing the message. Encoders also provide more context of
// the messages's creation (such as for which language the message is intended),
// which may not be known at the time of the creation of the message.
//
// Each message type must also have an accompanying decoder registered to decode
// the message. This decoder takes a Decoder argument which provides the
// counterparts for the decoding.
//
//
// Renderers
//
// A Decoder must be initialized with a Renderer implementation. These
// implementations must be provided by packages that use Catalogs, typically
// formatting packages such as x/text/message. A typical user will not need to
// worry about this type; it is only relevant to packages that do string
// formatting and want to use the catalog package to handle localized strings.
//
// A package that uses catalogs for selecting strings receives selection results
// as sequence of substrings passed to the Renderer. The following snippet shows
// how to express the above example using the message package.
//
// message.Set(language.English, "You are %d minute(s) late.",
// catalog.Var("minutes", plural.Select(1, "one", "minute")),
// catalog.String("You are %[1]d ${minutes} late."))
//
// p := message.NewPrinter(language.English)
// p.Printf("You are %d minute(s) late.", 5) // always 5 minutes late.
//
// To evaluate the Printf, package message wraps the arguments in a Renderer
// that is passed to the catalog for message decoding. The call sequence that
// results from evaluating the above message, assuming the person is rather
// tardy, is:
//
// Render("You are %[1]d ")
// Arg(1)
// Render("minutes")
// Render(" late.")
//
// The calls to Arg is caused by the plural.Select execution, which evaluates
// the argument to determine whether the singular or plural message form should
// be selected. The calls to Render reports the partial results to the message
// package for further evaluation.
package catmsg
import (
"errors"
"fmt"
"strconv"
"strings"
"sync"
"golang.org/x/text/language"
)
// A Handle refers to a registered message type.
type Handle int
// First is used as a Handle to EncodeMessageType, followed by a series of calls
// to EncodeMessage, to implement selecting the first matching Message.
//
// TODO: this can be removed once we either can use type aliases or if the
// internals of this package are merged with the catalog package.
var First Handle = msgFirst
// A Handler decodes and evaluates data compiled by a Message and sends the
// result to the Decoder. The output may depend on the value of the substitution
// arguments, accessible by the Decoder's Arg method. The Handler returns false
// if there is no translation for the given substitution arguments.
type Handler func(d *Decoder) bool
// Register records the existence of a message type and returns a Handle that
// can be used in the Encoder's EncodeMessageType method to create such
// messages. The prefix of the name should be the package path followed by
// an optional disambiguating string.
// Register will panic if a handle for the same name was already registered.
func Register(name string, handler Handler) Handle {
mutex.Lock()
defer mutex.Unlock()
if _, ok := names[name]; ok {
panic(fmt.Errorf("catmsg: handler for %q already exists", name))
}
h := Handle(len(handlers))
names[name] = h
handlers = append(handlers, handler)
return h
}
// These handlers require fixed positions in the handlers slice.
const (
msgVars Handle = iota
msgFirst
msgRaw
msgString
numFixed
)
const prefix = "golang.org/x/text/internal/catmsg."
var (
mutex sync.Mutex
names = map[string]Handle{
prefix + "Vars": msgVars,
prefix + "First": msgFirst,
prefix + "Raw": msgRaw,
prefix + "String": msgString,
}
handlers = make([]Handler, numFixed)
)
func init() {
// This handler is a message type wrapper that initializes a decoder
// with a variable block. This message type, if present, is always at the
// start of an encoded message.
handlers[msgVars] = func(d *Decoder) bool {
blockSize := int(d.DecodeUint())
d.vars = d.data[:blockSize]
d.data = d.data[blockSize:]
return d.executeMessage()
}
// First takes the first message in a sequence that results in a match for
// the given substitution arguments.
handlers[msgFirst] = func(d *Decoder) bool {
for !d.Done() {
if d.ExecuteMessage() {
return true
}
}
return false
}
handlers[msgRaw] = func(d *Decoder) bool {
d.Render(d.data)
return true
}
// A String message alternates between a string constant and a variable
// substitution.
handlers[msgString] = func(d *Decoder) bool {
for !d.Done() {
if str := d.DecodeString(); str != "" {
d.Render(str)
}
if d.Done() {
break
}
d.ExecuteSubstitution()
}
return true
}
}
var (
// ErrIncomplete indicates a compiled message does not define translations
// for all possible argument values. If this message is returned, evaluating
// a message may result in the ErrNoMatch error.
ErrIncomplete = errors.New("catmsg: incomplete message; may not give result for all inputs")
// ErrNoMatch indicates no translation message matched the given input
// parameters when evaluating a message.
ErrNoMatch = errors.New("catmsg: no translation for inputs")
)
// A Message holds a collection of translations for the same phrase that may
// vary based on the values of substitution arguments.
type Message interface {
// Compile encodes the format string(s) of the message as a string for later
// evaluation.
//
// The first call Compile makes on the encoder must be EncodeMessageType.
// The handle passed to this call may either be a handle returned by
// Register to encode a single custom message, or HandleFirst followed by
// a sequence of calls to EncodeMessage.
//
// Compile must return ErrIncomplete if it is possible for evaluation to
// not match any translation for a given set of formatting parameters.
// For example, selecting a translation based on plural form may not yield
// a match if the form "Other" is not one of the selectors.
//
// Compile may return any other application-specific error. For backwards
// compatibility with package like fmt, which often do not do sanity
// checking of format strings ahead of time, Compile should still make an
// effort to have some sensible fallback in case of an error.
Compile(e *Encoder) error
}
// Compile converts a Message to a data string that can be stored in a Catalog.
// The resulting string can subsequently be decoded by passing to the Execute
// method of a Decoder.
func Compile(tag language.Tag, macros Dictionary, m Message) (data string, err error) {
// TODO: pass macros so they can be used for validation.
v := &Encoder{inBody: true} // encoder for variables
v.root = v
e := &Encoder{root: v, parent: v, tag: tag} // encoder for messages
err = m.Compile(e)
// This package serves te message package, which in turn is meant to be a
// drop-in replacement for fmt. With the fmt package, format strings are
// evaluated lazily and errors are handled by substituting strings in the
// result, rather then returning an error. Dealing with multiple languages
// makes it more important to check errors ahead of time. We chose to be
// consistent and compatible and allow graceful degradation in case of
// errors.
buf := e.buf[stripPrefix(e.buf):]
if len(v.buf) > 0 {
// Prepend variable block.
b := make([]byte, 1+maxVarintBytes+len(v.buf)+len(buf))
b[0] = byte(msgVars)
b = b[:1+encodeUint(b[1:], uint64(len(v.buf)))]
b = append(b, v.buf...)
b = append(b, buf...)
buf = b
}
if err == nil {
err = v.err
}
return string(buf), err
}
// Var defines a message that can be substituted for a placeholder of the same
// name. If an expression does not result in a string after evaluation, Name is
// used as the substitution. For example:
// Var{
// Name: "minutes",
// Message: plural.Select(1, "one", "minute"),
// }
// will resolve to minute for singular and minutes for plural forms.
type Var struct {
Name string
Message Message
}
var errIsVar = errors.New("catmsg: variable used as message")
// Compile implements Message.
//
// Note that this method merely registers a variable; it does not create an
// encoded message.
func (v *Var) Compile(e *Encoder) error {
if err := e.addVar(v.Name, v.Message); err != nil {
return err
}
// Using a Var by itself is an error. If it is in a sequence followed by
// other messages referring to it, this error will be ignored.
return errIsVar
}
// Raw is a message consisting of a single format string that is passed as is
// to the Renderer.
//
// Note that a Renderer may still do its own variable substitution.
type Raw string
// Compile implements Message.
func (r Raw) Compile(e *Encoder) (err error) {
e.EncodeMessageType(msgRaw)
// Special case: raw strings don't have a size encoding and so don't use
// EncodeString.
e.buf = append(e.buf, r...)
return nil
}
// String is a message consisting of a single format string which contains
// placeholders that may be substituted with variables.
//
// Variable substitutions are marked with placeholders and a variable name of
// the form ${name}. Any other substitutions such as Go templates or
// printf-style substitutions are left to be done by the Renderer.
//
// When evaluation a string interpolation, a Renderer will receive separate
// calls for each placeholder and interstitial string. For example, for the
// message: "%[1]v ${invites} %[2]v to ${their} party." The sequence of calls
// is:
// d.Render("%[1]v ")
// d.Arg(1)
// d.Render(resultOfInvites)
// d.Render(" %[2]v to ")
// d.Arg(1)
// d.Render(resultOfTheir)
// d.Render(" party.")
// where the messages for "invites" and "their" both use a plural.Select
// referring to the first argument.
//
// Strings may also invoke macros. Macros are essentially variables that can be
// reused. Macros may, for instance, be used to make selections between
// different conjugations of a verb. See the catalog package description for an
// overview of macros.
type String string
// Compile implements Message. It parses the placeholder formats and returns
// any error.
func (s String) Compile(e *Encoder) (err error) {
msg := string(s)
const subStart = "${"
hasHeader := false
p := 0
b := []byte{}
for {
i := strings.Index(msg[p:], subStart)
if i == -1 {
break
}
b = append(b, msg[p:p+i]...)
p += i + len(subStart)
if i = strings.IndexByte(msg[p:], '}'); i == -1 {
b = append(b, "$!(MISSINGBRACE)"...)
err = fmt.Errorf("catmsg: missing '}'")
p = len(msg)
break
}
name := strings.TrimSpace(msg[p : p+i])
if q := strings.IndexByte(name, '('); q == -1 {
if !hasHeader {
hasHeader = true
e.EncodeMessageType(msgString)
}
e.EncodeString(string(b))
e.EncodeSubstitution(name)
b = b[:0]
} else if j := strings.IndexByte(name[q:], ')'); j == -1 {
// TODO: what should the error be?
b = append(b, "$!(MISSINGPAREN)"...)
err = fmt.Errorf("catmsg: missing ')'")
} else if x, sErr := strconv.ParseUint(strings.TrimSpace(name[q+1:q+j]), 10, 32); sErr != nil {
// TODO: handle more than one argument
b = append(b, "$!(BADNUM)"...)
err = fmt.Errorf("catmsg: invalid number %q", strings.TrimSpace(name[q+1:q+j]))
} else {
if !hasHeader {
hasHeader = true
e.EncodeMessageType(msgString)
}
e.EncodeString(string(b))
e.EncodeSubstitution(name[:q], int(x))
b = b[:0]
}
p += i + 1
}
b = append(b, msg[p:]...)
if !hasHeader {
// Simplify string to a raw string.
Raw(string(b)).Compile(e)
} else if len(b) > 0 {
e.EncodeString(string(b))
}
return err
}
+294
View File
@@ -0,0 +1,294 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package catmsg
import (
"errors"
"strings"
"testing"
"golang.org/x/text/language"
)
type renderer struct {
args []int
result string
}
func (r *renderer) Arg(i int) interface{} {
if i >= len(r.args) {
return nil
}
return r.args[i]
}
func (r *renderer) Render(s string) {
if r.result != "" {
r.result += "|"
}
r.result += s
}
func TestCodec(t *testing.T) {
type test struct {
args []int
out string
decErr string
}
single := func(out, err string) []test { return []test{{out: out, decErr: err}} }
testCases := []struct {
desc string
m Message
enc string
encErr string
tests []test
}{{
desc: "unused variable",
m: &Var{"name", String("foo")},
encErr: errIsVar.Error(),
tests: single("", ""),
}, {
desc: "empty",
m: empty{},
tests: single("", ""),
}, {
desc: "sequence with empty",
m: seq{empty{}},
tests: single("", ""),
}, {
desc: "raw string",
m: Raw("foo"),
tests: single("foo", ""),
}, {
desc: "raw string no sub",
m: Raw("${foo}"),
enc: "\x02${foo}",
tests: single("${foo}", ""),
}, {
desc: "simple string",
m: String("foo"),
tests: single("foo", ""),
}, {
desc: "missing var",
m: String("foo${bar}"),
enc: "\x03\x03foo\x02\x03bar",
encErr: `unknown var "bar"`,
tests: single("foo|bar", ""),
}, {
desc: "empty var",
m: seq{
&Var{"bar", seq{}},
String("foo${bar}"),
},
enc: "\x00\x05\x04\x02bar\x03\x03foo\x00\x00",
// TODO: recognize that it is cheaper to substitute bar.
tests: single("foo|bar", ""),
}, {
desc: "var after value",
m: seq{
String("foo${bar}"),
&Var{"bar", String("baz")},
},
encErr: errIsVar.Error(),
tests: single("foo|bar", ""),
}, {
desc: "substitution",
m: seq{
&Var{"bar", String("baz")},
String("foo${bar}"),
},
tests: single("foo|baz", ""),
}, {
desc: "shadowed variable",
m: seq{
&Var{"bar", String("baz")},
seq{
&Var{"bar", String("BAZ")},
String("foo${bar}"),
},
},
tests: single("foo|BAZ", ""),
}, {
desc: "not shadowed variable",
m: seq{
&Var{"bar", String("baz")},
seq{
String("foo${bar}"),
&Var{"bar", String("BAZ")},
},
},
encErr: errIsVar.Error(),
tests: single("foo|baz", ""),
}, {
desc: "duplicate variable",
m: seq{
&Var{"bar", String("baz")},
&Var{"bar", String("BAZ")},
String("${bar}"),
},
encErr: "catmsg: duplicate variable \"bar\"",
tests: single("baz", ""),
}, {
desc: "complete incomplete variable",
m: seq{
&Var{"bar", incomplete{}},
String("${bar}"),
},
enc: "\x00\t\b\x01\x01\x04\x04\x02bar\x03\x00\x00\x00",
// TODO: recognize that it is cheaper to substitute bar.
tests: single("bar", ""),
}, {
desc: "incomplete sequence",
m: seq{
incomplete{},
incomplete{},
},
encErr: ErrIncomplete.Error(),
tests: single("", ErrNoMatch.Error()),
}, {
desc: "compile error variable",
m: seq{
&Var{"bar", errorCompileMsg{}},
String("${bar}"),
},
encErr: errCompileTest.Error(),
tests: single("bar", ""),
}, {
desc: "compile error message",
m: errorCompileMsg{},
encErr: errCompileTest.Error(),
tests: single("", ""),
}, {
desc: "compile error sequence",
m: seq{
errorCompileMsg{},
errorCompileMsg{},
},
encErr: errCompileTest.Error(),
tests: single("", ""),
}, {
desc: "macro",
m: String("${exists(1)}"),
tests: single("you betya!", ""),
}, {
desc: "macro incomplete",
m: String("${incomplete(1)}"),
enc: "\x03\x00\x01\nincomplete\x01",
tests: single("incomplete", ""),
}, {
desc: "macro undefined at end",
m: String("${undefined(1)}"),
enc: "\x03\x00\x01\tundefined\x01",
tests: single("undefined", "catmsg: undefined macro \"undefined\""),
}, {
desc: "macro undefined with more text following",
m: String("${undefined(1)}."),
enc: "\x03\x00\x01\tundefined\x01\x01.",
tests: single("undefined|.", "catmsg: undefined macro \"undefined\""),
}, {
desc: "macro missing paren",
m: String("${missing(1}"),
encErr: "catmsg: missing ')'",
tests: single("$!(MISSINGPAREN)", ""),
}, {
desc: "macro bad num",
m: String("aa${bad(a)}"),
encErr: "catmsg: invalid number \"a\"",
tests: single("aa$!(BADNUM)", ""),
}, {
desc: "var missing brace",
m: String("a${missing"),
encErr: "catmsg: missing '}'",
tests: single("a$!(MISSINGBRACE)", ""),
}}
r := &renderer{}
dec := NewDecoder(language.Und, r, macros)
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
data, err := Compile(language.Und, macros, tc.m)
if failErr(err, tc.encErr) {
t.Errorf("encoding error: got %+q; want %+q", err, tc.encErr)
}
if tc.enc != "" && data != tc.enc {
t.Errorf("encoding: got %+q; want %+q", data, tc.enc)
}
for _, st := range tc.tests {
t.Run("", func(t *testing.T) {
*r = renderer{args: st.args}
if err = dec.Execute(data); failErr(err, st.decErr) {
t.Errorf("decoding error: got %+q; want %+q", err, st.decErr)
}
if r.result != st.out {
t.Errorf("decode: got %+q; want %+q", r.result, st.out)
}
})
}
})
}
}
func failErr(got error, want string) bool {
if got == nil {
return want != ""
}
return want == "" || !strings.Contains(got.Error(), want)
}
type seq []Message
func (s seq) Compile(e *Encoder) (err error) {
err = ErrIncomplete
e.EncodeMessageType(First)
for _, m := range s {
// Pass only the last error, but allow erroneous or complete messages
// here to allow testing different scenarios.
err = e.EncodeMessage(m)
}
return err
}
type empty struct{}
func (empty) Compile(e *Encoder) (err error) { return nil }
var msgIncomplete = Register(
"golang.org/x/text/internal/catmsg.incomplete",
func(d *Decoder) bool { return false })
type incomplete struct{}
func (incomplete) Compile(e *Encoder) (err error) {
e.EncodeMessageType(msgIncomplete)
return ErrIncomplete
}
type errorCompileMsg struct{}
var errCompileTest = errors.New("catmsg: compile error test")
func (errorCompileMsg) Compile(e *Encoder) (err error) {
return errCompileTest
}
type dictionary struct{}
var (
macros = dictionary{}
dictMessages = map[string]string{
"exists": compile(String("you betya!")),
"incomplete": compile(incomplete{}),
}
)
func (d dictionary) Lookup(key string) (data string, ok bool) {
data, ok = dictMessages[key]
return
}
func compile(m Message) (data string) {
data, _ = Compile(language.Und, macros, m)
return data
}
+407
View File
@@ -0,0 +1,407 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package catmsg
import (
"errors"
"fmt"
"golang.org/x/text/language"
)
// A Renderer renders a Message.
type Renderer interface {
// Render renders the given string. The given string may be interpreted as a
// format string, such as the one used by the fmt package or a template.
Render(s string)
// Arg returns the i-th argument passed to format a message. This method
// should return nil if there is no such argument. Messages need access to
// arguments to allow selecting a message based on linguistic features of
// those arguments.
Arg(i int) interface{}
}
// A Dictionary specifies a source of messages, including variables or macros.
type Dictionary interface {
// Lookup returns the message for the given key. It returns false for ok if
// such a message could not be found.
Lookup(key string) (data string, ok bool)
// TODO: consider returning an interface, instead of a string. This will
// allow implementations to do their own message type decoding.
}
// An Encoder serializes a Message to a string.
type Encoder struct {
// The root encoder is used for storing encoded variables.
root *Encoder
// The parent encoder provides the surrounding scopes for resolving variable
// names.
parent *Encoder
tag language.Tag
// buf holds the encoded message so far. After a message completes encoding,
// the contents of buf, prefixed by the encoded length, are flushed to the
// parent buffer.
buf []byte
// vars is the lookup table of variables in the current scope.
vars []keyVal
err error
inBody bool // if false next call must be EncodeMessageType
}
type keyVal struct {
key string
offset int
}
// Language reports the language for which the encoded message will be stored
// in the Catalog.
func (e *Encoder) Language() language.Tag { return e.tag }
func (e *Encoder) setError(err error) {
if e.root.err == nil {
e.root.err = err
}
}
// EncodeUint encodes x.
func (e *Encoder) EncodeUint(x uint64) {
e.checkInBody()
var buf [maxVarintBytes]byte
n := encodeUint(buf[:], x)
e.buf = append(e.buf, buf[:n]...)
}
// EncodeString encodes s.
func (e *Encoder) EncodeString(s string) {
e.checkInBody()
e.EncodeUint(uint64(len(s)))
e.buf = append(e.buf, s...)
}
// EncodeMessageType marks the current message to be of type h.
//
// It must be the first call of a Message's Compile method.
func (e *Encoder) EncodeMessageType(h Handle) {
if e.inBody {
panic("catmsg: EncodeMessageType not the first method called")
}
e.inBody = true
e.EncodeUint(uint64(h))
}
// EncodeMessage serializes the given message inline at the current position.
func (e *Encoder) EncodeMessage(m Message) error {
e = &Encoder{root: e.root, parent: e}
err := m.Compile(e)
if _, ok := m.(*Var); !ok {
e.flushTo(e.parent)
}
return err
}
func (e *Encoder) checkInBody() {
if !e.inBody {
panic("catmsg: expected prior call to EncodeMessageType")
}
}
// stripPrefix indicates the number of prefix bytes that must be stripped to
// turn a single-element sequence into a message that is just this single member
// without its size prefix. If the message can be stripped, b[1:n] contains the
// size prefix.
func stripPrefix(b []byte) (n int) {
if len(b) > 0 && Handle(b[0]) == msgFirst {
x, n, _ := decodeUint(b[1:])
if 1+n+int(x) == len(b) {
return 1 + n
}
}
return 0
}
func (e *Encoder) flushTo(dst *Encoder) {
data := e.buf
p := stripPrefix(data)
if p > 0 {
data = data[1:]
} else {
// Prefix the size.
dst.EncodeUint(uint64(len(data)))
}
dst.buf = append(dst.buf, data...)
}
func (e *Encoder) addVar(key string, m Message) error {
for _, v := range e.parent.vars {
if v.key == key {
err := fmt.Errorf("catmsg: duplicate variable %q", key)
e.setError(err)
return err
}
}
scope := e.parent
// If a variable message is Incomplete, and does not evaluate to a message
// during execution, we fall back to the variable name. We encode this by
// appending the variable name if the message reports it's incomplete.
err := m.Compile(e)
if err != ErrIncomplete {
e.setError(err)
}
switch {
case len(e.buf) == 1 && Handle(e.buf[0]) == msgFirst: // empty sequence
e.buf = e.buf[:0]
e.inBody = false
fallthrough
case len(e.buf) == 0:
// Empty message.
if err := String(key).Compile(e); err != nil {
e.setError(err)
}
case err == ErrIncomplete:
if Handle(e.buf[0]) != msgFirst {
seq := &Encoder{root: e.root, parent: e}
seq.EncodeMessageType(First)
e.flushTo(seq)
e = seq
}
// e contains a sequence; append the fallback string.
e.EncodeMessage(String(key))
}
// Flush result to variable heap.
offset := len(e.root.buf)
e.flushTo(e.root)
e.buf = e.buf[:0]
// Record variable offset in current scope.
scope.vars = append(scope.vars, keyVal{key: key, offset: offset})
return err
}
const (
substituteVar = iota
substituteMacro
substituteError
)
// EncodeSubstitution inserts a resolved reference to a variable or macro.
//
// This call must be matched with a call to ExecuteSubstitution at decoding
// time.
func (e *Encoder) EncodeSubstitution(name string, arguments ...int) {
if arity := len(arguments); arity > 0 {
// TODO: also resolve macros.
e.EncodeUint(substituteMacro)
e.EncodeString(name)
for _, a := range arguments {
e.EncodeUint(uint64(a))
}
return
}
for scope := e; scope != nil; scope = scope.parent {
for _, v := range scope.vars {
if v.key != name {
continue
}
e.EncodeUint(substituteVar) // TODO: support arity > 0
e.EncodeUint(uint64(v.offset))
return
}
}
// TODO: refer to dictionary-wide scoped variables.
e.EncodeUint(substituteError)
e.EncodeString(name)
e.setError(fmt.Errorf("catmsg: unknown var %q", name))
}
// A Decoder deserializes and evaluates messages that are encoded by an encoder.
type Decoder struct {
tag language.Tag
dst Renderer
macros Dictionary
err error
vars string
data string
macroArg int // TODO: allow more than one argument
}
// NewDecoder returns a new Decoder.
//
// Decoders are designed to be reused for multiple invocations of Execute.
// Only one goroutine may call Execute concurrently.
func NewDecoder(tag language.Tag, r Renderer, macros Dictionary) *Decoder {
return &Decoder{
tag: tag,
dst: r,
macros: macros,
}
}
func (d *Decoder) setError(err error) {
if d.err == nil {
d.err = err
}
}
// Language returns the language in which the message is being rendered.
//
// The destination language may be a child language of the language used for
// encoding. For instance, a decoding language of "pt-PT"" is consistent with an
// encoding language of "pt".
func (d *Decoder) Language() language.Tag { return d.tag }
// Done reports whether there are more bytes to process in this message.
func (d *Decoder) Done() bool { return len(d.data) == 0 }
// Render implements Renderer.
func (d *Decoder) Render(s string) { d.dst.Render(s) }
// Arg implements Renderer.
//
// During evaluation of macros, the argument positions may be mapped to
// arguments that differ from the original call.
func (d *Decoder) Arg(i int) interface{} {
if d.macroArg != 0 {
if i != 1 {
panic("catmsg: only macros with single argument supported")
}
i = d.macroArg
}
return d.dst.Arg(i)
}
// DecodeUint decodes a number that was encoded with EncodeUint and advances the
// position.
func (d *Decoder) DecodeUint() uint64 {
x, n, err := decodeUintString(d.data)
d.data = d.data[n:]
if err != nil {
d.setError(err)
}
return x
}
// DecodeString decodes a string that was encoded with EncodeString and advances
// the position.
func (d *Decoder) DecodeString() string {
size := d.DecodeUint()
s := d.data[:size]
d.data = d.data[size:]
return s
}
// SkipMessage skips the message at the current location and advances the
// position.
func (d *Decoder) SkipMessage() {
n := int(d.DecodeUint())
d.data = d.data[n:]
}
// Execute decodes and evaluates msg.
//
// Only one goroutine may call execute.
func (d *Decoder) Execute(msg string) error {
d.err = nil
if !d.execute(msg) {
return ErrNoMatch
}
return d.err
}
func (d *Decoder) execute(msg string) bool {
saved := d.data
d.data = msg
ok := d.executeMessage()
d.data = saved
return ok
}
// executeMessageFromData is like execute, but also decodes a leading message
// size and clips the given string accordingly.
//
// It reports the number of bytes consumed and whether a message was selected.
func (d *Decoder) executeMessageFromData(s string) (n int, ok bool) {
saved := d.data
d.data = s
size := int(d.DecodeUint())
n = len(s) - len(d.data)
// Sanitize the setting. This allows skipping a size argument for
// RawString and method Done.
d.data = d.data[:size]
ok = d.executeMessage()
n += size - len(d.data)
d.data = saved
return n, ok
}
var errUnknownHandler = errors.New("catmsg: string contains unsupported handler")
// executeMessage reads the handle id, initializes the decoder and executes the
// message. It is assumed that all of d.data[d.p:] is the single message.
func (d *Decoder) executeMessage() bool {
if d.Done() {
// We interpret no data as a valid empty message.
return true
}
handle := d.DecodeUint()
var fn Handler
mutex.Lock()
if int(handle) < len(handlers) {
fn = handlers[handle]
}
mutex.Unlock()
if fn == nil {
d.setError(errUnknownHandler)
d.execute(fmt.Sprintf("\x02$!(UNKNOWNMSGHANDLER=%#x)", handle))
return true
}
return fn(d)
}
// ExecuteMessage decodes and executes the message at the current position.
func (d *Decoder) ExecuteMessage() bool {
n, ok := d.executeMessageFromData(d.data)
d.data = d.data[n:]
return ok
}
// ExecuteSubstitution executes the message corresponding to the substitution
// as encoded by EncodeSubstitution.
func (d *Decoder) ExecuteSubstitution() {
switch x := d.DecodeUint(); x {
case substituteVar:
offset := d.DecodeUint()
d.executeMessageFromData(d.vars[offset:])
case substituteMacro:
name := d.DecodeString()
data, ok := d.macros.Lookup(name)
old := d.macroArg
// TODO: support macros of arity other than 1.
d.macroArg = int(d.DecodeUint())
switch {
case !ok:
// TODO: detect this at creation time.
d.setError(fmt.Errorf("catmsg: undefined macro %q", name))
fallthrough
case !d.execute(data):
d.dst.Render(name) // fall back to macro name.
}
d.macroArg = old
case substituteError:
d.dst.Render(d.DecodeString())
default:
panic("catmsg: unreachable")
}
}
+33 -18
View File
@@ -67,6 +67,15 @@ func VerifyDNSLength(verify bool) Option {
return func(o *options) { o.verifyDNSLength = verify }
}
// RemoveLeadingDots removes leading label separators. Leading runes that map to
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
//
// This is the behavior suggested by the UTS #46 and is adopted by some
// browsers.
func RemoveLeadingDots(remove bool) Option {
return func(o *options) { o.removeLeadingDots = remove }
}
// ValidateLabels sets whether to check the mandatory label validation criteria
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
// of hyphens ('-'), normalization, validity of runes, and the context rules.
@@ -133,14 +142,16 @@ func MapForLookup() Option {
o.mapping = validateAndMap
StrictDomainName(true)(o)
ValidateLabels(true)(o)
RemoveLeadingDots(true)(o)
}
}
type options struct {
transitional bool
useSTD3Rules bool
validateLabels bool
verifyDNSLength bool
transitional bool
useSTD3Rules bool
validateLabels bool
verifyDNSLength bool
removeLeadingDots bool
trie *idnaTrie
@@ -240,21 +251,23 @@ var (
punycode = &Profile{}
lookup = &Profile{options{
transitional: true,
useSTD3Rules: true,
validateLabels: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
transitional: true,
useSTD3Rules: true,
validateLabels: true,
removeLeadingDots: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
}}
display = &Profile{options{
useSTD3Rules: true,
validateLabels: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
useSTD3Rules: true,
validateLabels: true,
removeLeadingDots: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
}}
registration = &Profile{options{
useSTD3Rules: true,
@@ -293,7 +306,9 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
s, err = p.mapping(p, s)
}
// Remove leading empty labels.
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
if p.removeLeadingDots {
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
}
}
// It seems like we should only create this error on ToASCII, but the
// UTS 46 conformance tests suggests we should always check this.
+16 -7
View File
@@ -117,7 +117,7 @@ func TestLabelErrors(t *testing.T) {
f func(string) (string, error)
}
punyA := kind{"PunycodeA", punycode.ToASCII}
resolve := kind{"ToASCII", Lookup.ToASCII}
resolve := kind{"ResolveA", Lookup.ToASCII}
display := kind{"ToUnicode", Display.ToUnicode}
p := New(VerifyDNSLength(true), MapForLookup(), BidiRule())
lengthU := kind{"CheckLengthU", p.ToUnicode}
@@ -145,16 +145,25 @@ func TestLabelErrors(t *testing.T) {
{display, "foo.xn--.bar", "foo..bar", ""},
{lengthA, "a..b", "a..b", "A4"},
// Stripping leading empty labels here but not for "empty" punycode
// above seems inconsistent, but seems to be applied by both the
// conformance test and Chrome. Different interpretations would be
// possible, though.
{punyA, ".b", ".b", ""},
// For backwards compatibility, the Punycode profile does not map runes.
{punyA, "\u3002b", "xn--b-83t", ""},
{punyA, "..b", "..b", ""},
// Only strip leading empty labels for certain profiles. Stripping
// leading empty labels here but not for "empty" punycode above seems
// inconsistent, but seems to be applied by both the conformance test
// and Chrome. So we turn it off by default, support it as an option,
// and enable it in profiles where it seems commonplace.
{lengthA, ".b", "b", ""},
{lengthA, "\u3002b", "b", ""},
{lengthA, "..b", "b", ""},
{lengthA, "b..", "b..", ""}, // TODO: remove trailing dots?
{lengthA, "b..", "b..", ""},
{resolve, "a..b", "a..b", ""},
{resolve, ".b", "b", ""},
{resolve, "\u3002b", "b", ""},
{resolve, "..b", "b", ""},
{resolve, "b..", "b..", ""}, // TODO: remove trailing dots?
{resolve, "b..", "b..", ""},
// Raw punycode
{punyA, "", "", ""},
+433
View File
@@ -0,0 +1,433 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate stringer -type RoundingMode
package number
import (
"math"
"strconv"
)
// RoundingMode determines how a number is rounded to the desired precision.
type RoundingMode byte
const (
ToNearestEven RoundingMode = iota // towards the nearest integer, or towards an even number if equidistant.
ToNearestZero // towards the nearest integer, or towards zero if equidistant.
ToNearestAway // towards the nearest integer, or away from zero if equidistant.
ToPositiveInf // towards infinity
ToNegativeInf // towards negative infinity
ToZero // towards zero
AwayFromZero // away from zero
numModes
)
// A RoundingContext indicates how a number should be converted to digits.
type RoundingContext struct {
Mode RoundingMode
Increment int32 // if > 0, round to Increment * 10^-Scale
Precision int32 // maximum number of significant digits.
Scale int32 // maximum number of decimals after the dot.
}
const maxIntDigits = 20
// A Decimal represents floating point number represented in digits of the base
// in which a number is to be displayed. Digits represents a number [0, 1.0),
// and the absolute value represented by Decimal is Digits * 10^Exp.
// Leading and trailing zeros may be omitted and Exp may point outside a valid
// position in Digits.
//
// Examples:
// Number Decimal
// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5
// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2
// 12000 Digits: [1, 2], Exp: 5
// 0.00123 Digits: [1, 2, 3], Exp: -2
type Decimal struct {
Digits []byte // mantissa digits, big-endian
Exp int32 // exponent
Neg bool
Inf bool // Takes precedence over Digits and Exp.
NaN bool // Takes precedence over Inf.
buf [maxIntDigits]byte
}
// normalize retuns a new Decimal with leading and trailing zeros removed.
func (d *Decimal) normalize() (n Decimal) {
n = *d
b := n.Digits
// Strip leading zeros. Resulting number of digits is significant digits.
for len(b) > 0 && b[0] == 0 {
b = b[1:]
n.Exp--
}
// Strip trailing zeros
for len(b) > 0 && b[len(b)-1] == 0 {
b = b[:len(b)-1]
}
if len(b) == 0 {
n.Exp = 0
}
n.Digits = b
return n
}
func (d *Decimal) clear() {
b := d.Digits
if b == nil {
b = d.buf[:0]
}
*d = Decimal{}
d.Digits = b[:0]
}
func (x *Decimal) String() string {
if x.NaN {
return "NaN"
}
var buf []byte
if x.Neg {
buf = append(buf, '-')
}
if x.Inf {
buf = append(buf, "Inf"...)
return string(buf)
}
switch {
case len(x.Digits) == 0:
buf = append(buf, '0')
case x.Exp <= 0:
// 0.00ddd
buf = append(buf, "0."...)
buf = appendZeros(buf, -int(x.Exp))
buf = appendDigits(buf, x.Digits)
case /* 0 < */ int(x.Exp) < len(x.Digits):
// dd.ddd
buf = appendDigits(buf, x.Digits[:x.Exp])
buf = append(buf, '.')
buf = appendDigits(buf, x.Digits[x.Exp:])
default: // len(x.Digits) <= x.Exp
// ddd00
buf = appendDigits(buf, x.Digits)
buf = appendZeros(buf, int(x.Exp)-len(x.Digits))
}
return string(buf)
}
func appendDigits(buf []byte, digits []byte) []byte {
for _, c := range digits {
buf = append(buf, c+'0')
}
return buf
}
// appendZeros appends n 0 digits to buf and returns buf.
func appendZeros(buf []byte, n int) []byte {
for ; n > 0; n-- {
buf = append(buf, '0')
}
return buf
}
func (d *Decimal) round(mode RoundingMode, n int) {
if n >= len(d.Digits) {
return
}
// Make rounding decision: The result mantissa is truncated ("rounded down")
// by default. Decide if we need to increment, or "round up", the (unsigned)
// mantissa.
inc := false
switch mode {
case ToNegativeInf:
inc = d.Neg
case ToPositiveInf:
inc = !d.Neg
case ToZero:
// nothing to do
case AwayFromZero:
inc = true
case ToNearestEven:
inc = d.Digits[n] > 5 || d.Digits[n] == 5 &&
(len(d.Digits) > n+1 || n == 0 || d.Digits[n-1]&1 != 0)
case ToNearestAway:
inc = d.Digits[n] >= 5
case ToNearestZero:
inc = d.Digits[n] > 5 || d.Digits[n] == 5 && len(d.Digits) > n+1
default:
panic("unreachable")
}
if inc {
d.roundUp(n)
} else {
d.roundDown(n)
}
}
// roundFloat rounds a floating point number.
func (r RoundingMode) roundFloat(x float64) float64 {
// Make rounding decision: The result mantissa is truncated ("rounded down")
// by default. Decide if we need to increment, or "round up", the (unsigned)
// mantissa.
abs := x
if x < 0 {
abs = -x
}
i, f := math.Modf(abs)
if f == 0.0 {
return x
}
inc := false
switch r {
case ToNegativeInf:
inc = x < 0
case ToPositiveInf:
inc = x >= 0
case ToZero:
// nothing to do
case AwayFromZero:
inc = true
case ToNearestEven:
// TODO: check overflow
inc = f > 0.5 || f == 0.5 && int64(i)&1 != 0
case ToNearestAway:
inc = f >= 0.5
case ToNearestZero:
inc = f > 0.5
default:
panic("unreachable")
}
if inc {
i += 1
}
if abs != x {
i = -i
}
return i
}
func (x *Decimal) roundUp(n int) {
if n < 0 || n >= len(x.Digits) {
return // nothing to do
}
// find first digit < 9
for n > 0 && x.Digits[n-1] >= 9 {
n--
}
if n == 0 {
// all digits are 9s => round up to 1 and update exponent
x.Digits[0] = 1 // ok since len(x.Digits) > n
x.Digits = x.Digits[:1]
x.Exp++
return
}
x.Digits[n-1]++
x.Digits = x.Digits[:n]
// x already trimmed
}
func (x *Decimal) roundDown(n int) {
if n < 0 || n >= len(x.Digits) {
return // nothing to do
}
x.Digits = x.Digits[:n]
trim(x)
}
// trim cuts off any trailing zeros from x's mantissa;
// they are meaningless for the value of x.
func trim(x *Decimal) {
i := len(x.Digits)
for i > 0 && x.Digits[i-1] == 0 {
i--
}
x.Digits = x.Digits[:i]
if i == 0 {
x.Exp = 0
}
}
// A Converter converts a number into decimals according to the given rounding
// criteria.
type Converter interface {
Convert(d *Decimal, r *RoundingContext)
}
const (
signed = true
unsigned = false
)
// Convert converts the given number to the decimal representation using the
// supplied RoundingContext.
func (d *Decimal) Convert(r *RoundingContext, number interface{}) {
switch f := number.(type) {
case Converter:
d.clear()
f.Convert(d, r)
case float32:
d.ConvertFloat(r, float64(f), 32)
case float64:
d.ConvertFloat(r, f, 64)
case int:
d.ConvertInt(r, signed, uint64(f))
case int8:
d.ConvertInt(r, signed, uint64(f))
case int16:
d.ConvertInt(r, signed, uint64(f))
case int32:
d.ConvertInt(r, signed, uint64(f))
case int64:
d.ConvertInt(r, signed, uint64(f))
case uint:
d.ConvertInt(r, unsigned, uint64(f))
case uint8:
d.ConvertInt(r, unsigned, uint64(f))
case uint16:
d.ConvertInt(r, unsigned, uint64(f))
case uint32:
d.ConvertInt(r, unsigned, uint64(f))
case uint64:
d.ConvertInt(r, unsigned, f)
// TODO:
// case string: if produced by strconv, allows for easy arbitrary pos.
// case reflect.Value:
// case big.Float
// case big.Int
// case big.Rat?
// catch underlyings using reflect or will this already be done by the
// message package?
}
}
// ConvertInt converts an integer to decimals.
func (d *Decimal) ConvertInt(r *RoundingContext, signed bool, x uint64) {
if r.Increment > 0 {
// TODO: if uint64 is too large, fall back to float64
if signed {
d.ConvertFloat(r, float64(int64(x)), 64)
} else {
d.ConvertFloat(r, float64(x), 64)
}
return
}
d.clear()
if signed && int64(x) < 0 {
x = uint64(-int64(x))
d.Neg = true
}
d.fillIntDigits(x)
d.Exp = int32(len(d.Digits))
}
// ConvertFloat converts a floating point number to decimals.
func (d *Decimal) ConvertFloat(r *RoundingContext, x float64, size int) {
d.clear()
if math.IsNaN(x) {
d.NaN = true
return
}
abs := x
if x < 0 {
d.Neg = true
abs = -x
}
if math.IsInf(abs, 1) {
d.Inf = true
return
}
// Simple case: decimal notation
if r.Scale > 0 || r.Increment > 0 || r.Precision == 0 {
if int(r.Scale) > len(scales) {
x *= math.Pow(10, float64(r.Scale))
} else {
x *= scales[r.Scale]
}
if r.Increment > 0 {
inc := float64(r.Increment)
x /= float64(inc)
x = r.Mode.roundFloat(x)
x *= inc
} else {
x = r.Mode.roundFloat(x)
}
d.fillIntDigits(uint64(math.Abs(x)))
d.Exp = int32(len(d.Digits)) - r.Scale
return
}
// Nasty case (for non-decimal notation).
// Asides from being inefficient, this result is also wrong as it will
// apply ToNearestEven rounding regardless of the user setting.
// TODO: expose functionality in strconv so we can avoid this hack.
// Something like this would work:
// AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int)
// TODO: This only supports the nearest even rounding mode.
prec := int(r.Precision)
if prec > 0 {
prec--
}
b := strconv.AppendFloat(d.Digits, abs, 'e', prec, size)
i := 0
k := 0
// No need to check i < len(b) as we always have an 'e'.
for {
if c := b[i]; '0' <= c && c <= '9' {
b[k] = c - '0'
k++
} else if c != '.' {
break
}
i++
}
d.Digits = b[:k]
i += len("e")
pSign := i
exp := 0
for i++; i < len(b); i++ {
exp *= 10
exp += int(b[i] - '0')
}
if b[pSign] == '-' {
exp = -exp
}
d.Exp = int32(exp) + 1
}
func (d *Decimal) fillIntDigits(x uint64) {
if cap(d.Digits) < maxIntDigits {
d.Digits = d.buf[:]
} else {
d.Digits = d.buf[:maxIntDigits]
}
i := 0
for ; x > 0; x /= 10 {
d.Digits[i] = byte(x % 10)
i++
}
d.Digits = d.Digits[:i]
for p := 0; p < i; p++ {
i--
d.Digits[p], d.Digits[i] = d.Digits[i], d.Digits[p]
}
}
var scales [70]float64
func init() {
x := 1.0
for i := range scales {
scales[i] = x
x *= 10
}
}
+291
View File
@@ -0,0 +1,291 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package number
import (
"fmt"
"math"
"strconv"
"strings"
"testing"
)
func mkfloat(num string) float64 {
u, _ := strconv.ParseUint(num, 10, 32)
return float64(u)
}
// mkdec creates a decimal from a string. All ASCII digits are converted to
// digits in the decimal. The dot is used to indicate the scale by which the
// digits are shifted. Numbers may have an additional exponent or be the special
// value NaN, Inf, or -Inf.
func mkdec(num string) (d Decimal) {
if num[0] == '-' {
d.Neg = true
num = num[1:]
}
switch num {
case "NaN":
d.NaN = true
return
case "Inf":
d.Inf = true
return
}
if p := strings.IndexAny(num, "eE"); p != -1 {
i64, err := strconv.ParseInt(num[p+1:], 10, 32)
if err != nil {
panic(err)
}
d.Exp = int32(i64)
num = num[:p]
}
if p := strings.IndexByte(num, '.'); p != -1 {
d.Exp += int32(p)
num = num[:p] + num[p+1:]
} else {
d.Exp += int32(len(num))
}
d.Digits = []byte(num)
for i := range d.Digits {
d.Digits[i] -= '0'
}
return d.normalize()
}
func byteNum(s string) []byte {
b := make([]byte, len(s))
for i := 0; i < len(s); i++ {
if c := s[i]; '0' <= c && c <= '9' {
b[i] = s[i] - '0'
} else {
b[i] = s[i] - 'a' + 10
}
}
return b
}
func strNum(s string) string {
return string(byteNum(s))
}
func TestDecimalString(t *testing.T) {
for _, test := range []struct {
x Decimal
want string
}{
{want: "0"},
{Decimal{Digits: nil, Exp: 1000}, "0"}, // exponent of 1000 is ignored
{Decimal{Digits: byteNum("12345"), Exp: 0}, "0.12345"},
{Decimal{Digits: byteNum("12345"), Exp: -3}, "0.00012345"},
{Decimal{Digits: byteNum("12345"), Exp: +3}, "123.45"},
{Decimal{Digits: byteNum("12345"), Exp: +10}, "1234500000"},
} {
if got := test.x.String(); got != test.want {
t.Errorf("%v == %q; want %q", test.x, got, test.want)
}
}
}
func TestRounding(t *testing.T) {
testCases := []struct {
x string
n int
// modes is the result for modes. Signs are left out of the result.
// The results are stored in the following order:
// zero, negInf
// nearZero, nearEven, nearAway
// away, posInf
modes [numModes]string
}{
{"0", 1, [numModes]string{
"0", "0",
"0", "0", "0",
"0", "0"}},
{"1", 1, [numModes]string{
"1", "1",
"1", "1", "1",
"1", "1"}},
{"5", 1, [numModes]string{
"5", "5",
"5", "5", "5",
"5", "5"}},
{"15", 1, [numModes]string{
"10", "10",
"10", "20", "20",
"20", "20"}},
{"45", 1, [numModes]string{
"40", "40",
"40", "40", "50",
"50", "50"}},
{"95", 1, [numModes]string{
"90", "90",
"90", "100", "100",
"100", "100"}},
{"12344999", 4, [numModes]string{
"12340000", "12340000",
"12340000", "12340000", "12340000",
"12350000", "12350000"}},
{"12345000", 4, [numModes]string{
"12340000", "12340000",
"12340000", "12340000", "12350000",
"12350000", "12350000"}},
{"12345001", 4, [numModes]string{
"12340000", "12340000",
"12350000", "12350000", "12350000",
"12350000", "12350000"}},
{"12345100", 4, [numModes]string{
"12340000", "12340000",
"12350000", "12350000", "12350000",
"12350000", "12350000"}},
{"23454999", 4, [numModes]string{
"23450000", "23450000",
"23450000", "23450000", "23450000",
"23460000", "23460000"}},
{"23455000", 4, [numModes]string{
"23450000", "23450000",
"23450000", "23460000", "23460000",
"23460000", "23460000"}},
{"23455001", 4, [numModes]string{
"23450000", "23450000",
"23460000", "23460000", "23460000",
"23460000", "23460000"}},
{"23455100", 4, [numModes]string{
"23450000", "23450000",
"23460000", "23460000", "23460000",
"23460000", "23460000"}},
{"99994999", 4, [numModes]string{
"99990000", "99990000",
"99990000", "99990000", "99990000",
"100000000", "100000000"}},
{"99995000", 4, [numModes]string{
"99990000", "99990000",
"99990000", "100000000", "100000000",
"100000000", "100000000"}},
{"99999999", 4, [numModes]string{
"99990000", "99990000",
"100000000", "100000000", "100000000",
"100000000", "100000000"}},
{"12994999", 4, [numModes]string{
"12990000", "12990000",
"12990000", "12990000", "12990000",
"13000000", "13000000"}},
{"12995000", 4, [numModes]string{
"12990000", "12990000",
"12990000", "13000000", "13000000",
"13000000", "13000000"}},
{"12999999", 4, [numModes]string{
"12990000", "12990000",
"13000000", "13000000", "13000000",
"13000000", "13000000"}},
}
modes := []RoundingMode{
ToZero, ToNegativeInf,
ToNearestZero, ToNearestEven, ToNearestAway,
AwayFromZero, ToPositiveInf,
}
for _, tc := range testCases {
// Create negative counterpart tests: the sign is reversed and
// ToPositiveInf and ToNegativeInf swapped.
negModes := tc.modes
negModes[1], negModes[6] = negModes[6], negModes[1]
for i, res := range negModes {
negModes[i] = "-" + res
}
for i, m := range modes {
t.Run(fmt.Sprintf("x:%s/n:%d/%s", tc.x, tc.n, m), func(t *testing.T) {
d := mkdec(tc.x)
d.round(m, tc.n)
if got := d.String(); got != tc.modes[i] {
t.Errorf("pos decimal: got %q; want %q", d.String(), tc.modes[i])
}
mult := math.Pow(10, float64(len(tc.x)-tc.n))
f := mkfloat(tc.x)
f = m.roundFloat(f/mult) * mult
if got := fmt.Sprintf("%.0f", f); got != tc.modes[i] {
t.Errorf("pos float: got %q; want %q", got, tc.modes[i])
}
// Test the negative case. This is the same as the positive
// case, but with ToPositiveInf and ToNegativeInf swapped.
d = mkdec(tc.x)
d.Neg = true
d.round(m, tc.n)
if got, want := d.String(), negModes[i]; got != want {
t.Errorf("neg decimal: got %q; want %q", d.String(), want)
}
f = -mkfloat(tc.x)
f = m.roundFloat(f/mult) * mult
if got := fmt.Sprintf("%.0f", f); got != negModes[i] {
t.Errorf("neg float: got %q; want %q", got, negModes[i])
}
})
}
}
}
func TestConvert(t *testing.T) {
scale2 := &RoundingContext{Scale: 2}
scale2away := &RoundingContext{Scale: 2, Mode: AwayFromZero}
inc0_05 := &RoundingContext{Increment: 5, Scale: 2}
inc50 := &RoundingContext{Increment: 50}
prec3 := &RoundingContext{Precision: 3}
testCases := []struct {
x interface{}
rc *RoundingContext
out string
}{
{int8(-34), scale2, "-34"},
{int16(-234), scale2, "-234"},
{int32(-234), scale2, "-234"},
{int64(-234), scale2, "-234"},
{int(-234), scale2, "-234"},
{uint8(234), scale2, "234"},
{uint16(234), scale2, "234"},
{uint32(234), scale2, "234"},
{uint64(234), scale2, "234"},
{uint(234), scale2, "234"},
{-0.001, scale2, "-0"},
{-1e9, scale2, "-1000000000.00"},
{0.234, scale2, "0.23"},
{0.234, scale2away, "0.24"},
{0.1234, prec3, "0.123"},
{1234.0, prec3, "1230"},
{1.2345e10, prec3, "12300000000"},
{0.03, inc0_05, "0.05"},
{0.025, inc0_05, "0"},
{0.075, inc0_05, "0.10"},
{325, inc50, "300"},
{375, inc50, "400"},
{converter(3), scale2, "100"},
{math.Inf(1), inc50, "Inf"},
{math.Inf(-1), inc50, "-Inf"},
{math.NaN(), inc50, "NaN"},
}
for _, tc := range testCases {
var d Decimal
t.Run(fmt.Sprintf("%T:%v-%v", tc.x, tc.x, tc.rc), func(t *testing.T) {
d.Convert(tc.rc, tc.x)
if got := d.String(); got != tc.out {
t.Errorf("got %q; want %q", got, tc.out)
}
})
}
}
type converter int
func (c converter) Convert(d *Decimal, r *RoundingContext) {
d.Digits = append(d.Digits, 1, 0, 0)
d.Exp = 3
}
+467
View File
@@ -0,0 +1,467 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package number
import (
"strconv"
"unicode/utf8"
"golang.org/x/text/language"
)
// TODO:
// - grouping of fractions
// - allow user-defined superscript notation (such as <sup>4</sup>)
// - same for non-breaking spaces, like &nbsp;
// Formatting proceeds along the following lines:
// 0) Compose rounding information from format and context.
// 1) Convert a number into a Decimal.
// 2) Sanitize Decimal by adding trailing zeros, removing leading digits, and
// (non-increment) rounding. The Decimal that results from this is suitable
// for determining the plural form.
// 3) Render the Decimal in the localized form.
// Formatter contains all the information needed to render a number.
type Formatter struct {
Pattern
Info
RoundingContext
}
func (f *Formatter) init(t language.Tag, index []uint8) {
f.Info = InfoFromTag(t)
for ; ; t = t.Parent() {
if ci, ok := language.CompactIndex(t); ok {
f.Pattern = formats[index[ci]]
break
}
}
}
// InitPattern initializes a Formatter for the given Pattern.
func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
f.Info = InfoFromTag(t)
f.Pattern = *pat
}
// InitDecimal initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitDecimal(t language.Tag) {
f.init(t, tagToDecimal)
}
// InitScientific initializes a Formatter using the default Pattern for the
// given language.
func (f *Formatter) InitScientific(t language.Tag) {
f.init(t, tagToScientific)
}
// InitEngineering initializes a Formatter using the default Pattern for the
// given language.
func (f *Formatter) InitEngineering(t language.Tag) {
f.init(t, tagToScientific)
f.Pattern.MaxIntegerDigits = 3
f.Pattern.MinIntegerDigits = 1
}
// InitPercent initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitPercent(t language.Tag) {
f.init(t, tagToPercent)
}
// InitPerMille initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitPerMille(t language.Tag) {
f.init(t, tagToPercent)
f.Pattern.DigitShift = 3
}
func (f *Formatter) Append(dst []byte, x interface{}) []byte {
var d Decimal
d.Convert(&f.RoundingContext, x)
return f.Format(dst, &d)
}
func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
var result []byte
var postPrefix, preSuffix int
if f.MinExponentDigits > 0 {
result, postPrefix, preSuffix = appendScientific(dst, f, d)
} else {
result, postPrefix, preSuffix = appendDecimal(dst, f, d)
}
if f.PadRune == 0 {
return result
}
width := int(f.FormatWidth)
if count := utf8.RuneCount(result); count < width {
insertPos := 0
switch f.Flags & PadMask {
case PadAfterPrefix:
insertPos = postPrefix
case PadBeforeSuffix:
insertPos = preSuffix
case PadAfterSuffix:
insertPos = len(result)
}
num := width - count
pad := [utf8.UTFMax]byte{' '}
sz := 1
if r := f.PadRune; r != 0 {
sz = utf8.EncodeRune(pad[:], r)
}
extra := sz * num
if n := len(result) + extra; n < cap(result) {
result = result[:n]
copy(result[insertPos+extra:], result[insertPos:])
} else {
buf := make([]byte, n)
copy(buf, result[:insertPos])
copy(buf[insertPos+extra:], result[insertPos:])
result = buf
}
for ; num > 0; num-- {
insertPos += copy(result[insertPos:], pad[:sz])
}
}
return result
}
// appendDecimal appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
if dst, ok := f.renderSpecial(dst, d); ok {
return dst, 0, len(dst)
}
n := d.normalize()
if maxSig := int(f.MaxSignificantDigits); maxSig > 0 {
n.round(ToZero, maxSig)
}
digits := n.Digits
exp := n.Exp
exp += int32(f.Pattern.DigitShift)
// Split in integer and fraction part.
var intDigits, fracDigits []byte
var numInt, numFrac int
if exp > 0 {
numInt = int(exp)
if int(exp) >= len(digits) { // ddddd | ddddd00
intDigits = digits
} else { // ddd.dd
intDigits = digits[:exp]
fracDigits = digits[exp:]
numFrac = len(fracDigits)
}
} else {
fracDigits = digits
numFrac = -int(exp) + len(digits)
}
// Cap integer digits. Remove *most-significant* digits.
if f.MaxIntegerDigits > 0 && numInt > int(f.MaxIntegerDigits) {
offset := numInt - int(f.MaxIntegerDigits)
if offset > len(intDigits) {
numInt = 0
intDigits = nil
} else {
numInt = int(f.MaxIntegerDigits)
intDigits = intDigits[offset:]
// for keeping track of significant digits
digits = digits[offset:]
}
// Strip leading zeros. Resulting number of digits is significant digits.
for len(intDigits) > 0 && intDigits[0] == 0 {
intDigits = intDigits[1:]
digits = digits[1:]
numInt--
}
}
if f.MaxSignificantDigits == 0 && int(f.MaxFractionDigits) < numFrac {
if extra := numFrac - int(f.MaxFractionDigits); extra > len(fracDigits) {
numFrac = 0
fracDigits = nil
} else {
numFrac = int(f.MaxFractionDigits)
fracDigits = fracDigits[:len(fracDigits)-extra]
}
}
neg := d.Neg
affix, suffix := f.getAffixes(neg)
dst = appendAffix(dst, f, affix, neg)
savedLen := len(dst)
minInt := int(f.MinIntegerDigits)
if minInt == 0 && f.MinSignificantDigits > 0 {
minInt = 1
}
// add leading zeros
for i := minInt; i > numInt; i-- {
dst = f.AppendDigit(dst, 0)
if f.needsSep(i) {
dst = append(dst, f.Symbol(SymGroup)...)
}
}
i := 0
for ; i < len(intDigits); i++ {
dst = f.AppendDigit(dst, intDigits[i])
if f.needsSep(numInt - i) {
dst = append(dst, f.Symbol(SymGroup)...)
}
}
for ; i < numInt; i++ {
dst = f.AppendDigit(dst, 0)
if f.needsSep(numInt - i) {
dst = append(dst, f.Symbol(SymGroup)...)
}
}
trailZero := int(f.MinFractionDigits) - numFrac
if d := int(f.MinSignificantDigits) - len(digits); d > 0 && d > trailZero {
trailZero = d
}
if numFrac > 0 || trailZero > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
dst = append(dst, f.Symbol(SymDecimal)...)
}
// Add leading zeros
for i := numFrac - len(fracDigits); i > 0; i-- {
dst = f.AppendDigit(dst, 0)
}
i = 0
for ; i < len(fracDigits); i++ {
dst = f.AppendDigit(dst, fracDigits[i])
}
for ; trailZero > 0; trailZero-- {
dst = f.AppendDigit(dst, 0)
}
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}
// appendScientific appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendScientific(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
if dst, ok := f.renderSpecial(dst, d); ok {
return dst, 0, 0
}
// Significant digits are transformed by parser for scientific notation and
// do not need to be handled here.
maxInt, numInt := int(f.MaxIntegerDigits), int(f.MinIntegerDigits)
if numInt == 0 {
numInt = 1
}
maxSig := int(f.MaxFractionDigits) + numInt
minSig := int(f.MinFractionDigits) + numInt
n := d.normalize()
if maxSig > 0 {
n.round(ToZero, maxSig)
}
digits := n.Digits
exp := n.Exp
// If a maximum number of integers is specified, the minimum must be 1
// and the exponent is grouped by this number (e.g. for engineering)
if len(digits) == 0 {
exp = 0
} else if maxInt > numInt {
// Correct the exponent to reflect a single integer digit.
exp--
numInt = 1
// engineering
// 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3
// 12345 ([12345]e+5) -> 1.2345e4 12.345e3
d := int(exp) % maxInt
if d < 0 {
d += maxInt
}
exp -= int32(d)
numInt += d
} else {
exp -= int32(numInt)
}
var intDigits, fracDigits []byte
if numInt <= len(digits) {
intDigits = digits[:numInt]
fracDigits = digits[numInt:]
} else {
intDigits = digits
}
neg := d.Neg
affix, suffix := f.getAffixes(neg)
dst = appendAffix(dst, f, affix, neg)
savedLen := len(dst)
i := 0
for ; i < len(intDigits); i++ {
dst = f.AppendDigit(dst, intDigits[i])
if f.needsSep(numInt - i) {
dst = append(dst, f.Symbol(SymGroup)...)
}
}
for ; i < numInt; i++ {
dst = f.AppendDigit(dst, 0)
if f.needsSep(numInt - i) {
dst = append(dst, f.Symbol(SymGroup)...)
}
}
trailZero := minSig - numInt - len(fracDigits)
if len(fracDigits) > 0 || trailZero > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
dst = append(dst, f.Symbol(SymDecimal)...)
}
i = 0
for ; i < len(fracDigits); i++ {
dst = f.AppendDigit(dst, fracDigits[i])
}
for ; trailZero > 0; trailZero-- {
dst = f.AppendDigit(dst, 0)
}
// exp
buf := [12]byte{}
// TODO: use exponential if superscripting is not available (no Latin
// numbers or no tags) and use exponential in all other cases.
exponential := f.Symbol(SymExponential)
if exponential == "E" {
dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
dst = append(dst, f.Symbol(SymSuperscriptingExponent)...)
dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
dst = f.AppendDigit(dst, 1)
dst = f.AppendDigit(dst, 0)
switch {
case exp < 0:
dst = append(dst, superMinus...)
exp = -exp
case f.Flags&AlwaysExpSign != 0:
dst = append(dst, superPlus...)
}
b = strconv.AppendUint(buf[:0], uint64(exp), 10)
for i := len(b); i < int(f.MinExponentDigits); i++ {
dst = append(dst, superDigits[0]...)
}
for _, c := range b {
dst = append(dst, superDigits[c-'0']...)
}
} else {
dst = append(dst, exponential...)
switch {
case exp < 0:
dst = append(dst, f.Symbol(SymMinusSign)...)
exp = -exp
case f.Flags&AlwaysExpSign != 0:
dst = append(dst, f.Symbol(SymPlusSign)...)
}
b = strconv.AppendUint(buf[:0], uint64(exp), 10)
for i := len(b); i < int(f.MinExponentDigits); i++ {
dst = f.AppendDigit(dst, 0)
}
for _, c := range b {
dst = f.AppendDigit(dst, c-'0')
}
}
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}
const (
superMinus = "\u207B" // SUPERSCRIPT HYPHEN-MINUS
superPlus = "\u207A" // SUPERSCRIPT PLUS SIGN
)
var (
// Note: the digits are not sequential!!!
superDigits = []string{
"\u2070", // SUPERSCRIPT DIGIT ZERO
"\u00B9", // SUPERSCRIPT DIGIT ONE
"\u00B2", // SUPERSCRIPT DIGIT TWO
"\u00B3", // SUPERSCRIPT DIGIT THREE
"\u2074", // SUPERSCRIPT DIGIT FOUR
"\u2075", // SUPERSCRIPT DIGIT FIVE
"\u2076", // SUPERSCRIPT DIGIT SIX
"\u2077", // SUPERSCRIPT DIGIT SEVEN
"\u2078", // SUPERSCRIPT DIGIT EIGHT
"\u2079", // SUPERSCRIPT DIGIT NINE
}
)
func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
str := f.Affix
if str != "" {
if f.NegOffset > 0 {
if neg {
str = str[f.NegOffset:]
} else {
str = str[:f.NegOffset]
}
}
sufStart := 1 + str[0]
affix = str[1:sufStart]
suffix = str[sufStart+1:]
}
// TODO: introduce a NeedNeg sign to indicate if the left pattern already
// has a sign marked?
if f.NegOffset == 0 && (neg || f.Flags&AlwaysSign != 0) {
affix = "-" + affix
}
return affix, suffix
}
func (f *Formatter) renderSpecial(dst []byte, d *Decimal) (b []byte, ok bool) {
if d.NaN {
return fmtNaN(dst, f), true
}
if d.Inf {
return fmtInfinite(dst, f, d), true
}
return dst, false
}
func fmtNaN(dst []byte, f *Formatter) []byte {
return append(dst, f.Symbol(SymNan)...)
}
func fmtInfinite(dst []byte, f *Formatter, d *Decimal) []byte {
affix, suffix := f.getAffixes(d.Neg)
dst = appendAffix(dst, f, affix, d.Neg)
dst = append(dst, f.Symbol(SymInfinity)...)
dst = appendAffix(dst, f, suffix, d.Neg)
return dst
}
func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte {
quoting := false
escaping := false
for _, r := range affix {
switch {
case escaping:
// escaping occurs both inside and outside of quotes
dst = append(dst, string(r)...)
escaping = false
case r == '\\':
escaping = true
case r == '\'':
quoting = !quoting
case quoting:
dst = append(dst, string(r)...)
case r == '%':
if f.DigitShift == 3 {
dst = append(dst, f.Symbol(SymPerMille)...)
} else {
dst = append(dst, f.Symbol(SymPercentSign)...)
}
case r == '-' || r == '+':
if neg {
dst = append(dst, f.Symbol(SymMinusSign)...)
} else if f.Flags&ElideSign == 0 {
dst = append(dst, f.Symbol(SymPlusSign)...)
} else {
dst = append(dst, ' ')
}
default:
dst = append(dst, string(r)...)
}
}
return dst
}
+508
View File
@@ -0,0 +1,508 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package number
import (
"fmt"
"log"
"testing"
"golang.org/x/text/language"
)
func TestAppendDecimal(t *testing.T) {
type pairs map[string]string // alternates with decimal input and result
testCases := []struct {
pattern string
// We want to be able to test some forms of patterns that cannot be
// represented as a string.
pat *Pattern
test pairs
}{{
pattern: "0",
test: pairs{
"0": "0",
"1": "1",
"-1": "-1",
".00": "0",
"10.": "10",
"12": "12",
"1.2": "1",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "+0;+0",
test: pairs{
"0": "+0",
"1": "+1",
"-1": "-1",
".00": "+0",
"10.": "+10",
"12": "+12",
"1.2": "+1",
"NaN": "NaN",
"-Inf": "-∞",
"Inf": "+∞",
},
}, {
pattern: "0 +;0 +",
test: pairs{
"0": "0 +",
"1": "1 +",
"-1": "1 -",
".00": "0 +",
},
}, {
pattern: "0;0-",
test: pairs{
"-1": "1-",
"NaN": "NaN",
"-Inf": "∞-",
"Inf": "∞",
},
}, {
pattern: "0000",
test: pairs{
"0": "0000",
"1": "0001",
"12": "0012",
"12345": "12345",
},
}, {
pattern: ".0",
test: pairs{
"0": ".0",
"1": "1.0",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#.0",
test: pairs{
"0": ".0",
},
}, {
pattern: "#.0#",
test: pairs{
"0": ".0",
"1": "1.0",
},
}, {
pattern: "0.0#",
test: pairs{
"0": "0.0",
},
}, {
pattern: "#0.###",
test: pairs{
"0": "0",
"1": "1",
"1.2": "1.2",
"1.2345": "1.234", // rounding should have been done earlier
"1234.5": "1234.5",
"1234.567": "1234.567",
},
}, {
pattern: "#0.######",
test: pairs{
"0": "0",
"1234.5678": "1234.5678",
"0.123456789": "0.123456",
"NaN": "NaN",
"Inf": "∞",
},
// Test separators.
}, {
pattern: "#,#.00",
test: pairs{
"100": "1,0,0.00",
},
}, {
pattern: "#,0.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,0",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,##,#.00",
test: pairs{
"1000": "1,00,0.00",
},
}, {
pattern: "#,##0.###",
test: pairs{
"0": "0",
"1234.5678": "1,234.567",
"0.123456789": "0.123",
},
}, {
pattern: "#,##,##0.###",
test: pairs{
"0": "0",
"123456789012": "1,23,45,67,89,012",
"0.123456789": "0.123",
},
}, {
pattern: "0,00,000.###",
test: pairs{
"0": "0,00,000",
"123456789012": "1,23,45,67,89,012",
"12.3456789": "0,00,012.345",
"0.123456789": "0,00,000.123",
},
// Support for ill-formed patterns.
}, {
pattern: "#",
test: pairs{
".00": "", // This is the behavior of fmt.
"0": "", // This is the behavior of fmt.
"1": "1",
"10.": "10",
},
}, {
pattern: ".#",
test: pairs{
"0": "", // This is the behavior of fmt.
"1": "1",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#,#.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,#",
test: pairs{
"10": "1,0",
},
// Special patterns
}, {
pattern: "#,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
},
test: pairs{
"2017": "17",
},
}, {
pattern: "0,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 1,
},
test: pairs{
"2000": "0",
"2001": "1",
"2017": "17",
},
}, {
pattern: "00,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 2,
},
test: pairs{
"2000": "00",
"2001": "01",
"2017": "17",
},
}, {
pattern: "@@@@,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinSignificantDigits: 4,
},
test: pairs{
"2017": "17.00",
"2000": "0.000",
"2001": "1.000",
},
// Significant digits
}, {
pattern: "@@##",
test: pairs{
"1": "1.0",
"0.1": "0.10",
"123": "123",
"1234": "1234",
"12345": "12340",
},
}, {
pattern: "@@@@",
test: pairs{
"1": "1.000",
".1": "0.1000",
".001": "0.001000",
"123": "123.0",
"1234": "1234",
"12345": "12340", // rounding down
"NaN": "NaN",
"-Inf": "-∞",
},
// TODO: rounding
// {"@@@@": "23456": "23460"}, // rounding up
// TODO: padding
// Scientific and Engineering notation
}, {
pattern: "#E0",
test: pairs{
"0": "0\u202f×\u202f10⁰",
"1": "1\u202f×\u202f10⁰",
"123.456": "1\u202f×\u202f10²",
},
}, {
pattern: "#E+0",
test: pairs{
"0": "0\u202f×\u202f10⁺⁰",
"1000": "1\u202f×\u202f10⁺³",
"1E100": "1\u202f×\u202f10⁺¹⁰⁰",
"1E-100": "1\u202f×\u202f10⁻¹⁰⁰",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "##0E00",
test: pairs{
"100": "100\u202f×\u202f10⁰⁰",
"12345": "10\u202f×\u202f10⁰³",
"123.456": "100\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.###E00",
test: pairs{
"100": "100\u202f×\u202f10⁰⁰",
"12345": "12.34\u202f×\u202f10⁰³",
"123.456": "123.4\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.000E00",
test: pairs{
"100": "100.0\u202f×\u202f10⁰⁰",
"12345": "12.34\u202f×\u202f10⁰³",
"123.456": "123.4\u202f×\u202f10⁰⁰",
},
}, {
pattern: "@@E0",
test: pairs{
"0": "0.0\u202f×\u202f10⁰",
"99": "9.9\u202f×\u202f10¹",
"0.99": "9.9\u202f×\u202f10⁻¹",
},
}, {
pattern: "@###E00",
test: pairs{
"0": "0\u202f×\u202f10⁰⁰",
"1": "1\u202f×\u202f10⁰⁰",
"11": "1.1\u202f×\u202f10⁰¹",
"111": "1.11\u202f×\u202f10⁰²",
"1111": "1.111\u202f×\u202f10⁰³",
"11111": "1.111\u202f×\u202f10⁰⁴",
"0.1": "1\u202f×\u202f10⁻⁰¹",
"0.11": "1.1\u202f×\u202f10⁻⁰¹",
"0.001": "1\u202f×\u202f10⁻⁰³",
},
}, {
pattern: "*x##0",
test: pairs{
"0": "xx0",
"10": "x10",
"100": "100",
"1000": "1000",
},
}, {
pattern: "##0*x",
test: pairs{
"0": "0xx",
"10": "10x",
"100": "100",
"1000": "1000",
},
}, {
pattern: "* ###0.000",
test: pairs{
"0": " 0.000",
"123": " 123.000",
"123.456": " 123.456",
"1234.567": "1234.567",
},
}, {
pattern: "**0.0#######E00",
test: pairs{
"0": "***0.0\u202f×\u202f10⁰⁰",
"10": "***1.0\u202f×\u202f10⁰¹",
"11": "***1.1\u202f×\u202f10⁰¹",
"111": "**1.11\u202f×\u202f10⁰²",
"1111": "*1.111\u202f×\u202f10⁰³",
"11111": "1.1111\u202f×\u202f10⁰⁴",
"11110": "*1.111\u202f×\u202f10⁰⁴",
"11100": "**1.11\u202f×\u202f10⁰⁴",
"11000": "***1.1\u202f×\u202f10⁰⁴",
"10000": "***1.0\u202f×\u202f10⁰⁴",
},
}, {
pattern: "*xpre0suf",
test: pairs{
"0": "pre0suf",
"10": "pre10suf",
},
}, {
pattern: "*∞ pre ###0 suf",
test: pairs{
"0": "∞∞∞ pre 0 suf",
"10": "∞∞ pre 10 suf",
"100": "∞ pre 100 suf",
"1000": " pre 1000 suf",
},
}, {
pattern: "pre *∞###0 suf",
test: pairs{
"0": "pre ∞∞∞0 suf",
"10": "pre ∞∞10 suf",
"100": "pre ∞100 suf",
"1000": "pre 1000 suf",
},
}, {
pattern: "pre ###0*∞ suf",
test: pairs{
"0": "pre 0∞∞∞ suf",
"10": "pre 10∞∞ suf",
"100": "pre 100∞ suf",
"1000": "pre 1000 suf",
},
}, {
pattern: "pre ###0 suf *∞",
test: pairs{
"0": "pre 0 suf ∞∞∞",
"10": "pre 10 suf ∞∞",
"100": "pre 100 suf ∞",
"1000": "pre 1000 suf ",
},
}, {
// Take width of positive pattern.
pattern: "**###0;**-#####0x",
test: pairs{
"0": "***0",
"-1": "*-1x",
},
}, {
pattern: "0.00%",
test: pairs{
"0.1": "10.00%",
},
}, {
pattern: "0.##%",
test: pairs{
"0.1": "10%",
"0.11": "11%",
"0.111": "11.1%",
"0.1111": "11.11%",
"0.11111": "11.11%",
},
}, {
pattern: "‰ 0.0#",
test: pairs{
"0.1": "‰ 100.0",
"0.11": "‰ 110.0",
"0.111": "‰ 111.0",
"0.1111": "‰ 111.1",
"0.11111": "‰ 111.11",
"0.111111": "‰ 111.11",
},
}}
// TODO:
// "#,##0.00¤",
// "#,##0.00 ¤;(#,##0.00 ¤)",
for _, tc := range testCases {
pat := tc.pat
if pat == nil {
var err error
if pat, err = ParsePattern(tc.pattern); err != nil {
log.Fatal(err)
}
}
var f Formatter
f.InitPattern(language.English, pat)
for dec, want := range tc.test {
buf := make([]byte, 100)
t.Run(tc.pattern+"/"+dec, func(t *testing.T) {
dec := mkdec(dec)
buf = f.Format(buf[:0], &dec)
if got := string(buf); got != want {
t.Errorf("\n got %[1]q (%[1]s)\nwant %[2]q (%[2]s)", got, want)
}
})
}
}
}
func TestLocales(t *testing.T) {
testCases := []struct {
tag language.Tag
num string
want string
}{
{language.Make("en"), "123456.78", "123,456.78"},
{language.Make("de"), "123456.78", "123.456,78"},
{language.Make("de-CH"), "123456.78", "123’456.78"},
{language.Make("fr"), "123456.78", "123 456,78"},
{language.Make("bn"), "123456.78", "১,২৩,৪৫৬.৭৮"},
}
for _, tc := range testCases {
t.Run(fmt.Sprint(tc.tag, "/", tc.num), func(t *testing.T) {
var f Formatter
f.InitDecimal(tc.tag)
d := mkdec(tc.num)
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
}
})
}
}
func TestFormatters(t *testing.T) {
var f Formatter
testCases := []struct {
init func(t language.Tag)
num string
want string
}{
{f.InitDecimal, "123456.78", "123,456.78"},
{f.InitScientific, "123456.78", "1.23\u202f×\u202f10⁵"},
{f.InitEngineering, "123456.78", "123\u202f×\u202f10³"},
{f.InitPercent, "0.1234", "12.34%"},
{f.InitPerMille, "0.1234", "123.40‰"},
}
for i, tc := range testCases {
t.Run(fmt.Sprint(i, "/", tc.num), func(t *testing.T) {
tc.init(language.English)
f.Pattern.MinFractionDigits = 2
f.Pattern.MaxFractionDigits = 2
d := mkdec(tc.num)
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
}
})
}
}
+9
View File
@@ -121,6 +121,15 @@ func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
return int(n.system.digitSize)
}
// AppendDigit appends the UTF-8 sequence for n corresponding to the given digit
// to dst and reports the number of bytes written. dst must be large enough to
// hold the rune (can be up to utf8.UTFMax bytes).
func (n Info) AppendDigit(dst []byte, digit byte) []byte {
dst = append(dst, n.system.zero[:n.system.digitSize]...)
dst[len(dst)-1] += digit
return dst
}
// Digit returns the digit for the numbering system for the corresponding ASCII
// value. For example, ni.Digit('3') could return '三'. Note that the argument
// is the rune constant '3', which equals 51, not the integer constant 3.
+20 -10
View File
@@ -5,6 +5,7 @@
package number
import (
"fmt"
"testing"
"golang.org/x/text/internal/testtext"
@@ -26,9 +27,9 @@ func TestInfo(t *testing.T) {
// U+096F DEVANAGARI DIGIT NINE ('९')
{"de-BE-u-nu-deva", SymGroup, ".", '\u096f'}, // miss -> latn -> de
{"de-Cyrl-BE", SymGroup, ",", '9'}, // inherits from root
{"de-CH", SymGroup, "'", '9'}, // overrides values in de
{"de-CH-oxendict", SymGroup, "'", '9'}, // inherits from de-CH (no compact index)
{"de-CH-u-nu-deva", SymGroup, "'", '\u096f'}, // miss -> latn -> de-CH
{"de-CH", SymGroup, "’", '9'}, // overrides values in de
{"de-CH-oxendict", SymGroup, "’", '9'}, // inherits from de-CH (no compact index)
{"de-CH-u-nu-deva", SymGroup, "’", '\u096f'}, // miss -> latn -> de-CH
{"pa", SymExponential, "E", '9'},
@@ -51,13 +52,22 @@ func TestInfo(t *testing.T) {
{"en-u-nu-roman", SymPlusSign, "+", '9'},
}
for _, tc := range testCases {
info := InfoFromTag(language.MustParse(tc.lang))
if got := info.Symbol(tc.sym); got != tc.wantSym {
t.Errorf("%s:%v:sym: got %q; want %q", tc.lang, tc.sym, got, tc.wantSym)
}
if got := info.Digit('9'); got != tc.wantNine {
t.Errorf("%s:%v:nine: got %q; want %q", tc.lang, tc.sym, got, tc.wantNine)
}
t.Run(fmt.Sprintf("%s:%v", tc.lang, tc.sym), func(t *testing.T) {
info := InfoFromTag(language.MustParse(tc.lang))
if got := info.Symbol(tc.sym); got != tc.wantSym {
t.Errorf("sym: got %q; want %q", got, tc.wantSym)
}
if got := info.Digit('9'); got != tc.wantNine {
t.Errorf("Digit(9): got %+q; want %+q", got, tc.wantNine)
}
var buf [4]byte
if got := string(buf[:info.WriteDigit(buf[:], '9')]); got != string(tc.wantNine) {
t.Errorf("WriteDigit(9): got %+q; want %+q", got, tc.wantNine)
}
if got := string(info.AppendDigit([]byte{}, 9)); got != string(tc.wantNine) {
t.Errorf("AppendDigit(9): got %+q; want %+q", got, tc.wantNine)
}
})
}
}
+51 -10
View File
@@ -46,16 +46,17 @@ type Pattern struct {
Offset uint16 // Offset into Affix for prefix and suffix
NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
Multiplier uint32
FormatWidth uint16
RoundIncrement uint32 // Use Min*Digits to determine scale
PadRune rune
FormatWidth uint16
DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
GroupingSize [2]uint8
Flags PatternFlag
// Number of digits.
// TODO: consider using uint32
MinIntegerDigits uint8
MaxIntegerDigits uint8
MinFractionDigits uint8
@@ -65,11 +66,32 @@ type Pattern struct {
MinExponentDigits uint8
}
// A PatternFlag is a bit mask for the flag field of a Format.
func (f *Pattern) needsSep(pos int) bool {
p := pos - 1
size := int(f.GroupingSize[0])
if size == 0 || p == 0 {
return false
}
if p == size {
return true
}
if p -= size; p < 0 {
return false
}
// TODO: make second groupingsize the same as first if 0 so that we can
// avoid this check.
if x := int(f.GroupingSize[1]); x != 0 {
size = x
}
return p%size == 0
}
// A PatternFlag is a bit mask for the flag field of a Pattern.
type PatternFlag uint8
const (
AlwaysSign PatternFlag = 1 << iota
ElideSign // Use space instead of plus sign. AlwaysSign must be true.
AlwaysExpSign
AlwaysDecimalSeparator
ParenthesisForNegative // Common pattern. Saves space.
@@ -104,7 +126,8 @@ func (p *parser) setError(err error) {
}
func (p *parser) updateGrouping() {
if p.hasGroup && p.groupingCount < 255 {
if p.hasGroup &&
0 < p.groupingCount && p.groupingCount < 255 {
p.GroupingSize[1] = p.GroupingSize[0]
p.GroupingSize[0] = uint8(p.groupingCount)
}
@@ -163,6 +186,7 @@ func (p *parser) parseSubPattern(s string) string {
s = p.parsePad(s, PadAfterPrefix)
s = p.parse(p.number, s)
p.updateGrouping()
s = p.parsePad(s, PadBeforeSuffix)
s = p.parseAffix(s)
@@ -225,26 +249,41 @@ func (p *parser) affix(r rune) state {
'#', '@', '.', '*', ',', ';':
return nil
case '\'':
return p.escape
p.FormatWidth--
return p.escapeFirst
case '%':
if p.Multiplier != 0 {
if p.DigitShift != 0 {
p.setError(errDuplicatePercentSign)
}
p.Multiplier = 100
p.DigitShift = 2
case '\u2030': // ‰ Per mille
if p.Multiplier != 0 {
if p.DigitShift != 0 {
p.setError(errDuplicatePermilleSign)
}
p.Multiplier = 1000
p.DigitShift = 3
// TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
}
p.buf = append(p.buf, string(r)...)
return p.affix
}
func (p *parser) escapeFirst(r rune) state {
switch r {
case '\'':
p.buf = append(p.buf, "\\'"...)
return p.affix
default:
p.buf = append(p.buf, '\'')
p.buf = append(p.buf, string(r)...)
}
return p.escape
}
func (p *parser) escape(r rune) state {
switch r {
case '\'':
p.FormatWidth--
p.buf = append(p.buf, '\'')
return p.affix
default:
p.buf = append(p.buf, string(r)...)
@@ -294,6 +333,8 @@ func (p *parser) integer(r rune) state {
next = p.exponent
case '.':
next = p.fraction
case ',':
next = p.integer
}
p.updateGrouping()
return next
+73 -12
View File
@@ -25,6 +25,20 @@ var testCases = []struct {
FormatWidth: 1,
MinIntegerDigits: 1,
},
}, {
"+0",
&Pattern{
Affix: "\x01+\x00",
FormatWidth: 2,
MinIntegerDigits: 1,
},
}, {
"0+",
&Pattern{
Affix: "\x00\x01+",
FormatWidth: 2,
MinIntegerDigits: 1,
},
}, {
"0000",
&Pattern{
@@ -51,6 +65,22 @@ var testCases = []struct {
MinIntegerDigits: 1,
MaxFractionDigits: 6,
},
}, {
"#,0",
&Pattern{
FormatWidth: 3,
GroupingSize: [2]uint8{1, 0},
MinIntegerDigits: 1,
},
}, {
"#,0.00",
&Pattern{
FormatWidth: 6,
GroupingSize: [2]uint8{1, 0},
MinIntegerDigits: 1,
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
"#,##0.###",
&Pattern{
@@ -83,6 +113,11 @@ var testCases = []struct {
MaxIntegerDigits: 1,
MinExponentDigits: 1,
},
}, {
// At least one exponent digit is required. As long as this is true, one can
// determine that scientific rendering is needed if MinExponentDigits > 0.
"#E#",
nil,
}, {
"0E0",
&Pattern{
@@ -176,7 +211,7 @@ var testCases = []struct {
MaxFractionDigits: 3,
},
}, {
// Rounding increments
// Rounding increment
"1.05",
&Pattern{
RoundIncrement: 105,
@@ -185,11 +220,22 @@ var testCases = []struct {
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
// Rounding increment with grouping
"1,05",
&Pattern{
RoundIncrement: 105,
FormatWidth: 4,
GroupingSize: [2]uint8{2, 0},
MinIntegerDigits: 3,
MinFractionDigits: 0,
MaxFractionDigits: 0,
},
}, {
"0.0%",
&Pattern{
Affix: "\x00\x01%",
Multiplier: 100,
DigitShift: 2,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
@@ -199,7 +245,7 @@ var testCases = []struct {
"0.0‰",
&Pattern{
Affix: "\x00\x03‰",
Multiplier: 1000,
DigitShift: 3,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
@@ -219,7 +265,7 @@ var testCases = []struct {
"#,##0.00 ¤;(#,##0.00 ¤)",
&Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
NegOffset: 6,
Multiplier: 0,
DigitShift: 0,
FormatWidth: 10,
GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1,
@@ -272,6 +318,19 @@ var testCases = []struct {
FormatWidth: 7,
Flags: PadAfterSuffix,
},
}, {
`* #0 o''clock`,
&Pattern{Affix: "\x00\x09 o\\'clock",
FormatWidth: 10,
PadRune: 32,
MinIntegerDigits: 0x1},
}, {
`'123'* #0'456'`,
&Pattern{Affix: "\x05'123'\x05'456'",
FormatWidth: 8,
PadRune: 32,
MinIntegerDigits: 0x1,
Flags: PadAfterPrefix},
}, {
// no duplicate padding
"*xpre#suf*x", nil,
@@ -282,19 +341,21 @@ var testCases = []struct {
func TestParsePattern(t *testing.T) {
for i, tc := range testCases {
f, err := ParsePattern(tc.pat)
if !reflect.DeepEqual(f, tc.want) {
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
}
if got, want := err != nil, tc.want == nil; got != want {
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
}
t.Run(tc.pat, func(t *testing.T) {
f, err := ParsePattern(tc.pat)
if !reflect.DeepEqual(f, tc.want) {
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
}
if got, want := err != nil, tc.want == nil; got != want {
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
}
})
}
}
func TestPatternSize(t *testing.T) {
if sz := unsafe.Sizeof(Pattern{}); sz > 48 {
t.Errorf("got %d; want 48", sz)
t.Errorf("got %d; want <= 48", sz)
}
}
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "stringer -type RoundingMode"; DO NOT EDIT.
package number
import "fmt"
const _RoundingMode_name = "ToNearestEvenToNearestZeroToNearestAwayToPositiveInfToNegativeInfToZeroAwayFromZeronumModes"
var _RoundingMode_index = [...]uint8{0, 13, 26, 39, 52, 65, 71, 83, 91}
func (i RoundingMode) String() string {
if i >= RoundingMode(len(_RoundingMode_index)-1) {
return fmt.Sprintf("RoundingMode(%d)", i)
}
return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
}
+283 -280
View File
@@ -5,7 +5,7 @@ package number
import "golang.org/x/text/internal/stringset"
// CLDRVersion is the CLDR version from which the tables in this package are derived.
const CLDRVersion = "30"
const CLDRVersion = "31"
var numSysData = []systemData{ // 58 elements
0: {id: 0x0, digitSize: 0x1, zero: [4]uint8{0x30, 0x0, 0x0, 0x0}},
@@ -255,82 +255,81 @@ var symIndex = [][12]uint8{ // 71 elements
22: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0x1d, 0xb},
23: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0x1e, 0x0},
24: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
25: [12]uint8{0x0, 0x1f, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
25: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
26: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
27: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb},
27: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x1f, 0xb},
28: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
29: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x21, 0xb},
30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x22, 0xb},
31: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x13, 0x8, 0x9, 0x23, 0xb},
32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x23, 0xb},
33: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x24, 0xb},
34: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb},
35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
36: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
29: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb},
30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x21, 0xb},
31: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x13, 0x8, 0x9, 0x22, 0xb},
32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x22, 0xb},
33: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x23, 0xb},
34: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x24, 0xb},
35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb},
36: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
38: [12]uint8{0x1, 0x0, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb},
40: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2a, 0xb},
41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2b, 0x13, 0x8, 0x9, 0x23, 0xb},
39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
40: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb},
41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2a, 0x13, 0x8, 0x9, 0x22, 0xb},
42: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0},
43: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
44: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x2c, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0x0},
46: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2e, 0xb},
47: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb},
48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x30, 0x7, 0x8, 0x9, 0xa, 0xb},
49: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb},
50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x32, 0xb},
51: [12]uint8{0x1, 0x1f, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
52: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x33, 0xb},
53: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
54: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0x3c, 0xb},
55: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
56: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x38, 0x3d, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
57: [12]uint8{0x34, 0xc, 0x36, 0x37, 0x38, 0x3e, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0x0},
58: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x3e, 0x3a, 0x7, 0x3f, 0x9, 0x23, 0xb},
59: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x40, 0x41, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
60: [12]uint8{0x34, 0x35, 0x36, 0x43, 0xe, 0x1c, 0x42, 0x7, 0x3b, 0x9, 0x1d, 0xb},
61: [12]uint8{0x34, 0x35, 0x36, 0x11, 0xe, 0x1c, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
62: [12]uint8{0x1, 0xc, 0x36, 0x11, 0x40, 0x44, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x0},
63: [12]uint8{0x34, 0x1, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
64: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x40, 0x44, 0x42, 0x7, 0x3b, 0x9, 0x23, 0xb},
65: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x40, 0x41, 0x42, 0x7, 0x8, 0x9, 0xa, 0x34},
66: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0x31, 0x34},
67: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0x32, 0x34},
68: [12]uint8{0x0, 0x1, 0x45, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
69: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x46, 0xb},
70: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x47, 0x48, 0xb},
44: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2b, 0x0},
46: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2c, 0xb},
47: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0xb},
48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x2e, 0x7, 0x8, 0x9, 0xa, 0xb},
49: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb},
50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x30, 0xb},
51: [12]uint8{0x1, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
52: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb},
53: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
54: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0x3a, 0xb},
55: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
56: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x36, 0x3b, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
57: [12]uint8{0x32, 0xc, 0x34, 0x35, 0x36, 0x3c, 0x38, 0x7, 0x39, 0x9, 0xa, 0x0},
58: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x3c, 0x38, 0x7, 0x3d, 0x9, 0x22, 0xb},
59: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x3e, 0x3f, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
60: [12]uint8{0x32, 0x33, 0x34, 0x41, 0xe, 0x1c, 0x40, 0x7, 0x39, 0x9, 0x1d, 0xb},
61: [12]uint8{0x32, 0x33, 0x34, 0x11, 0xe, 0x1c, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
62: [12]uint8{0x1, 0xc, 0x34, 0x11, 0x3e, 0x42, 0x40, 0x7, 0x39, 0x9, 0xa, 0x0},
63: [12]uint8{0x32, 0x1, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
64: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x3e, 0x42, 0x40, 0x7, 0x39, 0x9, 0x22, 0xb},
65: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x3e, 0x3f, 0x40, 0x7, 0x8, 0x9, 0xa, 0x32},
66: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0x2f, 0x32},
67: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0x30, 0x32},
68: [12]uint8{0x0, 0x1, 0x43, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
69: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x44, 0xb},
70: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x45, 0x46, 0xb},
} // Size: 876 bytes
var symData = stringset.Set{
Data: "" + // Size: 584 bytes
Data: "" + // Size: 580 bytes
".,;%+-E׉∞NaN:\u00a0\u200e%\u200e\u200e+\u200e-ليس\u00a0رقمًا٪ND·Терхьаш" +
"\u00a0дац'mnne×10^0/00INF−\u200e−ناعددepäluku’ՈչԹარ\u00a0არის\u00a0რიცხვ" +
"იсан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်းမဟု" +
"တ်သောННне\u00a0числочыыһыла\u00a0буотах·10^–epilohosan\u00a0dälTFЕhaqi" +
"qiy\u00a0son\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值٫٬؛٪\u061c\u061c+" +
"\u061c-اس؉ليس\u00a0رقم\u200f−\u061c−؉\u200f\u200e+\u200e\u200e-\u200e×۱۰" +
"^\u200e٪\u200e−\u200e၊ཨང་མེན་གྲངས་མེདཨང་མད",
Index: []uint16{ // 74 elements
"\u00a0дац’mnne×10^0/00INF−\u200e−ناعددepälukuՈչԹარ\u00a0არის\u00a0რიცხვი" +
"сан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်းမဟုတ်" +
"သောННне\u00a0числочыыһыла\u00a0буотах·10^epilohosan\u00a0dälTFЕhaqiqiy" +
"\u00a0son\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值٫٬؛٪\u061c\u061c+\u061c-" +
"اس؉ليس\u00a0رقم\u200f−\u061c−؉\u200f\u200e+\u200e\u200e-\u200e×۱۰^" +
"\u200e٪\u200e−\u200e၊ཨང་མེན་གྲངས་མེདཨང་མད",
Index: []uint16{ // 72 elements
// Entry 0 - 3F
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0009, 0x000c, 0x000f, 0x0012, 0x0013, 0x0015, 0x001c, 0x0020,
0x0024, 0x0036, 0x0038, 0x003a, 0x003c, 0x0052, 0x0053, 0x0056,
0x0057, 0x005c, 0x0060, 0x0063, 0x0066, 0x006c, 0x0076, 0x007e,
0x0081, 0x0087, 0x00af, 0x00bf, 0x00c5, 0x00d5, 0x0102, 0x0104,
0x012b, 0x012f, 0x013f, 0x015b, 0x0160, 0x0163, 0x016a, 0x0173,
0x0175, 0x0177, 0x0189, 0x01a9, 0x01b2, 0x01b4, 0x01b6, 0x01b8,
0x01bc, 0x01bf, 0x01c2, 0x01c6, 0x01c8, 0x01d6, 0x01dc, 0x01e1,
0x0024, 0x0036, 0x0038, 0x003a, 0x003c, 0x0052, 0x0055, 0x0058,
0x0059, 0x005e, 0x0062, 0x0065, 0x0068, 0x006e, 0x0078, 0x0080,
0x0086, 0x00ae, 0x00be, 0x00c4, 0x00d4, 0x0101, 0x0103, 0x012a,
0x012e, 0x013e, 0x015a, 0x015f, 0x0166, 0x016f, 0x0171, 0x0173,
0x0185, 0x01a5, 0x01ae, 0x01b0, 0x01b2, 0x01b4, 0x01b8, 0x01bb,
0x01be, 0x01c2, 0x01c4, 0x01d2, 0x01d8, 0x01dd, 0x01e2, 0x01e9,
// Entry 40 - 7F
0x01e6, 0x01ed, 0x01f4, 0x01fb, 0x0200, 0x0209, 0x020c, 0x0221,
0x0239, 0x0248,
0x01f0, 0x01f7, 0x01fc, 0x0205, 0x0208, 0x021d, 0x0235, 0x0244,
},
} // Size: 772 bytes
} // Size: 764 bytes
// langToDefaults maps a compact language index to the default numbering system
// and default symbol set
var langToDefaults = [752]uint8{
var langToDefaults = [754]uint8{
// Entry 0 - 3F
0x80, 0x06, 0x13, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x83, 0x02, 0x02, 0x02,
@@ -365,79 +364,80 @@ var langToDefaults = [752]uint8{
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x14,
0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x01,
0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
0x06, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
0x01, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00,
// Entry 100 - 13F
0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06,
0x00, 0x00, 0x06, 0x06, 0x15, 0x15, 0x06, 0x06,
0x01, 0x01, 0x97, 0x16, 0x16, 0x01, 0x01, 0x01,
0x01, 0x01, 0x17, 0x17, 0x00, 0x00, 0x18, 0x18,
0x18, 0x9a, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01,
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x06, 0x00, 0x00, 0x06, 0x06, 0x15, 0x15, 0x06,
0x06, 0x01, 0x01, 0x97, 0x16, 0x16, 0x01, 0x01,
0x01, 0x01, 0x01, 0x17, 0x17, 0x00, 0x00, 0x18,
0x18, 0x18, 0x9a, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 140 - 17F
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x9d, 0x00,
0x06, 0x06, 0x19, 0x19, 0x19, 0x19, 0xa0, 0x00,
0x01, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x9d,
0x00, 0x06, 0x06, 0x19, 0x19, 0x19, 0x19, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0x00, 0x06,
0x06, 0x06, 0x0b, 0x0b, 0x01, 0x01, 0x1b, 0x1b,
0x0a, 0x0a, 0xa2, 0x00, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0x00,
0x06, 0x06, 0x06, 0x0b, 0x0b, 0x01, 0x01, 0x1b,
0x1b, 0x0a, 0x0a, 0xa2, 0x00, 0x00, 0x00, 0x06,
// Entry 180 - 1BF
0x06, 0x1c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x00, 0x1d, 0x1d, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x0d, 0x0d, 0x00, 0x00, 0x1e, 0x1e, 0x06,
0x06, 0x1f, 0x1f, 0x00, 0x00, 0x06, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x1a,
0x00, 0x00, 0x01, 0x01, 0x20, 0x20, 0x00, 0x00,
0x00, 0x21, 0x21, 0x00, 0x00, 0x06, 0x06, 0x00,
0x06, 0x06, 0x1c, 0x06, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x1d,
0x1d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x0d, 0x0d, 0x00, 0x00, 0x1e,
0x1e, 0x06, 0x06, 0x1f, 0x1f, 0x00, 0x00, 0x06,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa5, 0x1a, 0x00, 0x00, 0x01, 0x01, 0x20, 0x20,
0x00, 0x00, 0x00, 0x21, 0x21, 0x00, 0x00, 0x06,
// Entry 1C0 - 1FF
0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
0x22, 0x22, 0xa7, 0x00, 0x00, 0x15, 0x15, 0x06,
0x06, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0xa9, 0x00, 0x00, 0x06, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0xaa, 0x24, 0xac, 0x00,
0x00, 0x00, 0x00, 0xad, 0x14, 0x14, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
0x06, 0x06, 0x22, 0x22, 0xa7, 0x00, 0x00, 0x15,
0x15, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x23,
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d,
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0xaa, 0x24,
0xac, 0x00, 0x00, 0x00, 0x00, 0xad, 0x14, 0x14,
// Entry 200 - 23F
0x06, 0x06, 0x06, 0xb0, 0x00, 0x00, 0xb1, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01,
0x14, 0x14, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x06, 0xb0, 0x00, 0x00,
0xb1, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x01, 0x01, 0x14, 0x14, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x25, 0x25, 0x25, 0xb4, 0xb6, 0x1a,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xb8,
0x26, 0x06, 0x01, 0x06, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x25, 0x25, 0x25, 0xb4,
0xb6, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0xb8, 0x26, 0x06, 0x01, 0x06, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 240 - 27F
0x00, 0x00, 0x19, 0x19, 0x06, 0x06, 0x06, 0x06,
0x06, 0x00, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27,
0x27, 0x27, 0x06, 0x06, 0x00, 0x00, 0x28, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x29, 0x29,
0x29, 0x06, 0x06, 0x0d, 0x0d, 0x06, 0x06, 0x01,
0x01, 0x01, 0x01, 0x01, 0x2a, 0x2a, 0x2b, 0x2b,
0x2c, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x06, 0x00, 0x00, 0x19, 0x19, 0x06, 0x06,
0x06, 0x06, 0x06, 0x00, 0x00, 0x27, 0x27, 0x27,
0x27, 0x27, 0x27, 0x27, 0x06, 0x06, 0x00, 0x00,
0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
0x29, 0x29, 0x29, 0x06, 0x06, 0x0d, 0x0d, 0x06,
0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2a, 0x2a,
0x2b, 0x2b, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x2d,
0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 280 - 2BF
0x01, 0x01, 0x01, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
0x00, 0xba, 0x20, 0x20, 0x20, 0x00, 0x06, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x00, 0x00, 0x00, 0xba, 0x20, 0x20, 0x20, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x2f, 0x2f,
0x06, 0x06, 0x06, 0x00, 0x0d, 0x0d, 0x01, 0x01,
0x00, 0x00, 0x30, 0x30, 0xbd, 0xbf, 0x1a, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00,
0x2f, 0x2f, 0x06, 0x06, 0x06, 0x00, 0x0d, 0x0d,
0x01, 0x01, 0x00, 0x00, 0x30, 0x30, 0xbd, 0xbf,
// Entry 2C0 - 2FF
0xc2, 0x26, 0xc4, 0x32, 0x31, 0x31, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x34, 0x34, 0x01, 0x01, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x34, 0x34, 0x34, 0x34, 0x00, 0x00,
} // Size: 752 bytes
0x1a, 0xc0, 0xc2, 0x26, 0xc4, 0x32, 0x31, 0x31,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x34, 0x34, 0x01, 0x01, 0xc6, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x34,
0x00, 0x00,
} // Size: 754 bytes
// langToAlt is a list of numbering system and symbol set pairs, sorted and
// marked by compact language index.
@@ -464,59 +464,59 @@ var langToAlt = []altSymData{ // 73 elements
20: {compactTag: 0x63, system: 0x3, symIndex: 0x35},
21: {compactTag: 0x7b, system: 0x36, symIndex: 0x46},
22: {compactTag: 0x7b, system: 0x0, symIndex: 0x0},
23: {compactTag: 0x112, system: 0x4, symIndex: 0x3c},
24: {compactTag: 0x112, system: 0x0, symIndex: 0x16},
25: {compactTag: 0x112, system: 0x3, symIndex: 0x37},
26: {compactTag: 0x121, system: 0x0, symIndex: 0x1},
27: {compactTag: 0x121, system: 0x3, symIndex: 0x38},
28: {compactTag: 0x121, system: 0x4, symIndex: 0x3d},
29: {compactTag: 0x156, system: 0x0, symIndex: 0x0},
30: {compactTag: 0x156, system: 0x3, symIndex: 0x37},
31: {compactTag: 0x156, system: 0x4, symIndex: 0x3b},
32: {compactTag: 0x15e, system: 0x0, symIndex: 0x0},
33: {compactTag: 0x15e, system: 0x3, symIndex: 0x35},
34: {compactTag: 0x17a, system: 0x0, symIndex: 0x0},
35: {compactTag: 0x17a, system: 0x3, symIndex: 0x35},
36: {compactTag: 0x17a, system: 0x4, symIndex: 0x3b},
37: {compactTag: 0x1ae, system: 0x4, symIndex: 0x3b},
38: {compactTag: 0x1ae, system: 0x0, symIndex: 0x1a},
39: {compactTag: 0x1ca, system: 0x4, symIndex: 0x3b},
40: {compactTag: 0x1ca, system: 0x0, symIndex: 0x0},
41: {compactTag: 0x1ea, system: 0xb, symIndex: 0x0},
42: {compactTag: 0x1f4, system: 0x23, symIndex: 0x44},
43: {compactTag: 0x1f4, system: 0x0, symIndex: 0x24},
44: {compactTag: 0x1f6, system: 0x4, symIndex: 0x3b},
45: {compactTag: 0x1fb, system: 0x0, symIndex: 0x14},
46: {compactTag: 0x1fb, system: 0x3, symIndex: 0x39},
47: {compactTag: 0x1fb, system: 0x4, symIndex: 0x3e},
48: {compactTag: 0x203, system: 0xb, symIndex: 0x0},
49: {compactTag: 0x206, system: 0x0, symIndex: 0x6},
50: {compactTag: 0x206, system: 0x3, symIndex: 0x35},
51: {compactTag: 0x206, system: 0x4, symIndex: 0x3b},
52: {compactTag: 0x225, system: 0x0, symIndex: 0x0},
53: {compactTag: 0x225, system: 0x4, symIndex: 0x3f},
54: {compactTag: 0x226, system: 0x4, symIndex: 0x3b},
55: {compactTag: 0x226, system: 0x0, symIndex: 0x1a},
56: {compactTag: 0x22f, system: 0x4, symIndex: 0x3b},
57: {compactTag: 0x22f, system: 0x0, symIndex: 0x26},
58: {compactTag: 0x291, system: 0x0, symIndex: 0x20},
59: {compactTag: 0x291, system: 0x3, symIndex: 0x3a},
60: {compactTag: 0x291, system: 0x4, symIndex: 0x40},
61: {compactTag: 0x2bc, system: 0x0, symIndex: 0x1a},
62: {compactTag: 0x2bc, system: 0x4, symIndex: 0x41},
63: {compactTag: 0x2bd, system: 0x4, symIndex: 0x41},
64: {compactTag: 0x2bf, system: 0x0, symIndex: 0x31},
65: {compactTag: 0x2bf, system: 0x4, symIndex: 0x42},
66: {compactTag: 0x2c0, system: 0x4, symIndex: 0x3b},
67: {compactTag: 0x2c0, system: 0x0, symIndex: 0x26},
68: {compactTag: 0x2c2, system: 0x0, symIndex: 0x32},
69: {compactTag: 0x2c2, system: 0x4, symIndex: 0x43},
70: {compactTag: 0x2e4, system: 0x0, symIndex: 0x0},
71: {compactTag: 0x2e4, system: 0x3, symIndex: 0x35},
72: {compactTag: 0x2e4, system: 0x4, symIndex: 0x3b},
23: {compactTag: 0x113, system: 0x4, symIndex: 0x3c},
24: {compactTag: 0x113, system: 0x0, symIndex: 0x16},
25: {compactTag: 0x113, system: 0x3, symIndex: 0x37},
26: {compactTag: 0x122, system: 0x0, symIndex: 0x1},
27: {compactTag: 0x122, system: 0x3, symIndex: 0x38},
28: {compactTag: 0x122, system: 0x4, symIndex: 0x3d},
29: {compactTag: 0x157, system: 0x0, symIndex: 0x0},
30: {compactTag: 0x157, system: 0x3, symIndex: 0x37},
31: {compactTag: 0x157, system: 0x4, symIndex: 0x3b},
32: {compactTag: 0x15f, system: 0x0, symIndex: 0x0},
33: {compactTag: 0x15f, system: 0x3, symIndex: 0x35},
34: {compactTag: 0x17b, system: 0x0, symIndex: 0x0},
35: {compactTag: 0x17b, system: 0x3, symIndex: 0x35},
36: {compactTag: 0x17b, system: 0x4, symIndex: 0x3b},
37: {compactTag: 0x1b0, system: 0x4, symIndex: 0x3b},
38: {compactTag: 0x1b0, system: 0x0, symIndex: 0x1a},
39: {compactTag: 0x1cc, system: 0x4, symIndex: 0x3b},
40: {compactTag: 0x1cc, system: 0x0, symIndex: 0x0},
41: {compactTag: 0x1ec, system: 0xb, symIndex: 0x0},
42: {compactTag: 0x1f6, system: 0x23, symIndex: 0x44},
43: {compactTag: 0x1f6, system: 0x0, symIndex: 0x24},
44: {compactTag: 0x1f8, system: 0x4, symIndex: 0x3b},
45: {compactTag: 0x1fd, system: 0x0, symIndex: 0x14},
46: {compactTag: 0x1fd, system: 0x3, symIndex: 0x39},
47: {compactTag: 0x1fd, system: 0x4, symIndex: 0x3e},
48: {compactTag: 0x205, system: 0xb, symIndex: 0x0},
49: {compactTag: 0x208, system: 0x0, symIndex: 0x6},
50: {compactTag: 0x208, system: 0x3, symIndex: 0x35},
51: {compactTag: 0x208, system: 0x4, symIndex: 0x3b},
52: {compactTag: 0x227, system: 0x0, symIndex: 0x0},
53: {compactTag: 0x227, system: 0x4, symIndex: 0x3f},
54: {compactTag: 0x228, system: 0x4, symIndex: 0x3b},
55: {compactTag: 0x228, system: 0x0, symIndex: 0x1a},
56: {compactTag: 0x231, system: 0x4, symIndex: 0x3b},
57: {compactTag: 0x231, system: 0x0, symIndex: 0x26},
58: {compactTag: 0x293, system: 0x0, symIndex: 0x20},
59: {compactTag: 0x293, system: 0x3, symIndex: 0x3a},
60: {compactTag: 0x293, system: 0x4, symIndex: 0x40},
61: {compactTag: 0x2be, system: 0x0, symIndex: 0x1a},
62: {compactTag: 0x2be, system: 0x4, symIndex: 0x41},
63: {compactTag: 0x2bf, system: 0x4, symIndex: 0x41},
64: {compactTag: 0x2c1, system: 0x0, symIndex: 0x31},
65: {compactTag: 0x2c1, system: 0x4, symIndex: 0x42},
66: {compactTag: 0x2c2, system: 0x4, symIndex: 0x3b},
67: {compactTag: 0x2c2, system: 0x0, symIndex: 0x26},
68: {compactTag: 0x2c4, system: 0x0, symIndex: 0x32},
69: {compactTag: 0x2c4, system: 0x4, symIndex: 0x43},
70: {compactTag: 0x2e6, system: 0x0, symIndex: 0x0},
71: {compactTag: 0x2e6, system: 0x3, symIndex: 0x35},
72: {compactTag: 0x2e6, system: 0x4, symIndex: 0x3b},
} // Size: 316 bytes
var tagToDecimal = []uint8{ // 752 elements
var tagToDecimal = []uint8{ // 754 elements
// Entry 0 - 3F
0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -566,10 +566,10 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 180 - 1BF
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -577,16 +577,16 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 1C0 - 1FF
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 200 - 23F
@@ -594,8 +594,8 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x05,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 240 - 27F
@@ -611,7 +611,7 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -623,9 +623,10 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
} // Size: 776 bytes
0x01, 0x01,
} // Size: 778 bytes
var tagToScientific = []uint8{ // 752 elements
var tagToScientific = []uint8{ // 754 elements
// Entry 0 - 3F
0x02, 0x02, 0x09, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
@@ -675,10 +676,10 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0d,
0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 180 - 1BF
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
@@ -691,11 +692,11 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 1C0 - 1FF
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x0e, 0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x0e, 0x0e, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 200 - 23F
@@ -703,8 +704,8 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x0d, 0x02, 0x02,
0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0d,
0x02, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 240 - 27F
@@ -713,7 +714,7 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e, 0x0e,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 280 - 2BF
@@ -732,9 +733,10 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
} // Size: 776 bytes
0x02, 0x02,
} // Size: 778 bytes
var tagToPercent = []uint8{ // 752 elements
var tagToPercent = []uint8{ // 754 elements
// Entry 0 - 3F
0x04, 0x04, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
@@ -769,87 +771,88 @@ var tagToPercent = []uint8{ // 752 elements
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03,
0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04,
0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
// Entry 100 - 13F
0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x0b, 0x0b,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03,
0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x0b,
0x0b, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
// Entry 140 - 17F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06,
0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 180 - 1BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
// Entry 1C0 - 1FF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04,
// Entry 200 - 23F
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x06, 0x06, 0x04, 0x04, 0x04, 0x06, 0x04, 0x04,
0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
// Entry 240 - 27F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
0x03, 0x03, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 280 - 2BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04,
0x0f, 0x0f, 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x04,
// Entry 2C0 - 2FF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
// Entry 1C0 - 1FF
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03,
// Entry 200 - 23F
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
} // Size: 776 bytes
0x04, 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x06,
0x04, 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 240 - 27F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 280 - 2BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x0f, 0x0f, 0x0f, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
// Entry 2C0 - 2FF
0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04,
} // Size: 778 bytes
var formats = []Pattern{Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x0,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x0,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -863,10 +866,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -880,10 +883,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x3,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x3,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -897,10 +900,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -914,10 +917,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x6,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x6,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -931,10 +934,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0xc,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xc,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -948,10 +951,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -965,10 +968,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0xa,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xa,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -982,10 +985,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -999,13 +1002,13 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0xd,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xd,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x2,
Flags: 0x4,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x6,
@@ -1016,10 +1019,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x3,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x3,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1033,11 +1036,11 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x03%\u00a0\x00",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
GroupingSize: [2]uint8{0x0,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
MinIntegerDigits: 0x1,
@@ -1050,10 +1053,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
Offset: 0x0,
NegOffset: 0x5,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -1067,10 +1070,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x01[\x01]",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x5,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x5,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1084,10 +1087,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x1,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x1,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1101,11 +1104,11 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x01%\x00",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x6,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x6,
GroupingSize: [2]uint8{0x0,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
MinIntegerDigits: 0x1,
@@ -1116,4 +1119,4 @@ var formats = []Pattern{Pattern{Affix: "",
MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}}
// Total table size 7101 bytes (6KiB); checksum: A4A81DF0
// Total table size 7101 bytes (6KiB); checksum: 5190D0B3
+63 -62
View File
@@ -4,7 +4,7 @@ package internal
// Parent maps a compact index of a tag to the compact index of the parent of
// this tag.
var Parent = []uint16{ // 752 elements
var Parent = []uint16{ // 754 elements
// Entry 0 - 3F
0x0000, 0x0053, 0x00e5, 0x0000, 0x0003, 0x0003, 0x0000, 0x0006,
0x0000, 0x0008, 0x0000, 0x000a, 0x0000, 0x000c, 0x000c, 0x000c,
@@ -40,77 +40,78 @@ var Parent = []uint16{ // 752 elements
0x0086, 0x0086, 0x0086, 0x0086, 0x0085, 0x0085, 0x0086, 0x0086,
0x0085, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0000, 0x00ee,
0x0000, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f0, 0x00f0, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f0, 0x00f0, 0x00f1,
// Entry 100 - 13F
0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x0000, 0x010c, 0x0000, 0x010e,
0x0000, 0x0110, 0x0000, 0x0112, 0x0112, 0x0000, 0x0115, 0x0115,
0x0115, 0x0115, 0x0000, 0x011a, 0x0000, 0x011c, 0x0000, 0x011e,
0x011e, 0x0000, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x00f1, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x0000, 0x010d, 0x0000,
0x010f, 0x0000, 0x0111, 0x0000, 0x0113, 0x0113, 0x0000, 0x0116,
0x0116, 0x0116, 0x0116, 0x0000, 0x011b, 0x0000, 0x011d, 0x0000,
0x011f, 0x011f, 0x0000, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
// Entry 140 - 17F
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
0x0000, 0x0158, 0x0000, 0x015a, 0x015a, 0x015a, 0x0000, 0x015e,
0x0000, 0x0000, 0x0161, 0x0000, 0x0163, 0x0000, 0x0165, 0x0165,
0x0165, 0x0000, 0x0169, 0x0000, 0x016b, 0x0000, 0x016d, 0x0000,
0x016f, 0x016f, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0000, 0x0151, 0x0000, 0x0153, 0x0000, 0x0155, 0x0000,
0x0157, 0x0000, 0x0159, 0x0000, 0x015b, 0x015b, 0x015b, 0x0000,
0x015f, 0x0000, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
0x0166, 0x0166, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
0x0000, 0x0170, 0x0170, 0x0000, 0x0173, 0x0000, 0x0175, 0x0000,
0x0177, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
// Entry 180 - 1BF
0x0000, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000, 0x0185, 0x0000,
0x0000, 0x0188, 0x0000, 0x018a, 0x0000, 0x0000, 0x018d, 0x0000,
0x018f, 0x0000, 0x0000, 0x0192, 0x0000, 0x0000, 0x0195, 0x0000,
0x017f, 0x0000, 0x0181, 0x0181, 0x0181, 0x0181, 0x0000, 0x0000,
0x0187, 0x0000, 0x0000, 0x018a, 0x0000, 0x018c, 0x0000, 0x0000,
0x018f, 0x0000, 0x0191, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000,
0x0197, 0x0000, 0x0199, 0x0000, 0x019b, 0x0000, 0x019d, 0x0000,
0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000,
0x01a7, 0x0000, 0x01a9, 0x01a9, 0x0000, 0x01ac, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x0000,
0x01b7, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x01ab, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x01b6,
0x0000, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
// Entry 1C0 - 1FF
0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x01c3, 0x01c3, 0x01c3,
0x0000, 0x01c8, 0x0000, 0x01ca, 0x01ca, 0x0000, 0x01cd, 0x0000,
0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x01c5,
0x01c5, 0x01c5, 0x0000, 0x01ca, 0x0000, 0x01cc, 0x01cc, 0x0000,
0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
0x01d7, 0x01d7, 0x0000, 0x01da, 0x0000, 0x01dc, 0x0000, 0x01de,
0x01d7, 0x0000, 0x01d9, 0x01d9, 0x0000, 0x01dc, 0x0000, 0x01de,
0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x01ec, 0x01ec,
0x0000, 0x01f0, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x01f6,
0x0000, 0x0000, 0x01f9, 0x0000, 0x01fb, 0x01fb, 0x0000, 0x01fe,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
0x01ee, 0x01ee, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x01f6,
0x0000, 0x01f8, 0x0000, 0x0000, 0x01fb, 0x0000, 0x01fd, 0x01fd,
// Entry 200 - 23F
0x0000, 0x0200, 0x0200, 0x0000, 0x0203, 0x0203, 0x0000, 0x0206,
0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0000, 0x020e,
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0218, 0x0000, 0x0000, 0x021b, 0x0000, 0x021d, 0x021d,
0x0000, 0x0220, 0x0000, 0x0222, 0x0222, 0x0000, 0x0000, 0x0226,
0x0225, 0x0225, 0x0000, 0x0000, 0x022b, 0x0000, 0x022d, 0x0000,
0x022f, 0x0000, 0x023b, 0x0231, 0x023b, 0x023b, 0x023b, 0x023b,
0x023b, 0x023b, 0x023b, 0x0231, 0x023b, 0x023b, 0x0000, 0x023e,
0x0000, 0x0200, 0x0000, 0x0202, 0x0202, 0x0000, 0x0205, 0x0205,
0x0000, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208,
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x021a, 0x0000, 0x0000, 0x021d, 0x0000,
0x021f, 0x021f, 0x0000, 0x0222, 0x0000, 0x0224, 0x0224, 0x0000,
0x0000, 0x0228, 0x0227, 0x0227, 0x0000, 0x0000, 0x022d, 0x0000,
0x022f, 0x0000, 0x0231, 0x0000, 0x023d, 0x0233, 0x023d, 0x023d,
0x023d, 0x023d, 0x023d, 0x023d, 0x023d, 0x0233, 0x023d, 0x023d,
// Entry 240 - 27F
0x023e, 0x023e, 0x0000, 0x0242, 0x0000, 0x0244, 0x0000, 0x0246,
0x0246, 0x0000, 0x0249, 0x0000, 0x024b, 0x024b, 0x024b, 0x024b,
0x024b, 0x024b, 0x0000, 0x0252, 0x0000, 0x0254, 0x0000, 0x0256,
0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x0000, 0x025d, 0x025d,
0x025d, 0x0000, 0x0261, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
0x0000, 0x0268, 0x0267, 0x0267, 0x0000, 0x026c, 0x0000, 0x026e,
0x0000, 0x0270, 0x0000, 0x0000, 0x0000, 0x0000, 0x0275, 0x0000,
0x0000, 0x0278, 0x0000, 0x027a, 0x027a, 0x027a, 0x027a, 0x0000,
0x0000, 0x0240, 0x0240, 0x0240, 0x0000, 0x0244, 0x0000, 0x0246,
0x0000, 0x0248, 0x0248, 0x0000, 0x024b, 0x0000, 0x024d, 0x024d,
0x024d, 0x024d, 0x024d, 0x024d, 0x0000, 0x0254, 0x0000, 0x0256,
0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x025c, 0x0000, 0x0000,
0x025f, 0x025f, 0x025f, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
0x0267, 0x0000, 0x0000, 0x026a, 0x0269, 0x0269, 0x0000, 0x026e,
0x0000, 0x0270, 0x0000, 0x0272, 0x0000, 0x0000, 0x0000, 0x0000,
0x0277, 0x0000, 0x0000, 0x027a, 0x0000, 0x027c, 0x027c, 0x027c,
// Entry 280 - 2BF
0x027f, 0x027f, 0x027f, 0x0000, 0x0283, 0x0283, 0x0283, 0x0283,
0x0283, 0x0000, 0x0289, 0x0289, 0x0289, 0x0289, 0x0000, 0x0000,
0x0000, 0x0000, 0x0291, 0x0291, 0x0291, 0x0000, 0x0295, 0x0295,
0x0295, 0x0295, 0x0000, 0x0000, 0x029b, 0x029b, 0x029b, 0x029b,
0x0000, 0x02a0, 0x0000, 0x02a2, 0x02a2, 0x0000, 0x02a5, 0x0000,
0x02a7, 0x02a7, 0x0000, 0x0000, 0x02ab, 0x0000, 0x0000, 0x02ae,
0x0000, 0x02b0, 0x02b0, 0x0000, 0x0000, 0x02b4, 0x0000, 0x02b6,
0x0000, 0x02b8, 0x0000, 0x02ba, 0x0000, 0x02bc, 0x02bc, 0x0000,
0x027c, 0x0000, 0x0281, 0x0281, 0x0281, 0x0000, 0x0285, 0x0285,
0x0285, 0x0285, 0x0285, 0x0000, 0x028b, 0x028b, 0x028b, 0x028b,
0x0000, 0x0000, 0x0000, 0x0000, 0x0293, 0x0293, 0x0293, 0x0000,
0x0297, 0x0297, 0x0297, 0x0297, 0x0000, 0x0000, 0x029d, 0x029d,
0x029d, 0x029d, 0x0000, 0x02a2, 0x0000, 0x02a4, 0x02a4, 0x0000,
0x02a7, 0x0000, 0x02a9, 0x02a9, 0x0000, 0x0000, 0x02ad, 0x0000,
0x0000, 0x02b0, 0x0000, 0x02b2, 0x02b2, 0x0000, 0x0000, 0x02b6,
0x0000, 0x02b8, 0x0000, 0x02ba, 0x0000, 0x02bc, 0x0000, 0x02be,
// Entry 2C0 - 2FF
0x0000, 0x02c0, 0x0000, 0x02c2, 0x02bf, 0x02bf, 0x0000, 0x0000,
0x02c7, 0x02c6, 0x02c6, 0x0000, 0x0000, 0x02cc, 0x0000, 0x02ce,
0x0000, 0x02d0, 0x0000, 0x0000, 0x02d3, 0x0000, 0x0000, 0x0000,
0x02d7, 0x0000, 0x02d9, 0x0000, 0x02db, 0x0000, 0x02dd, 0x02dd,
0x0000, 0x02e0, 0x0000, 0x02e2, 0x0000, 0x02e4, 0x02e4, 0x02e4,
0x02e4, 0x02e4, 0x0000, 0x02ea, 0x02eb, 0x02ea, 0x0000, 0x02ee,
} // Size: 1528 bytes
0x02be, 0x0000, 0x0000, 0x02c2, 0x0000, 0x02c4, 0x02c1, 0x02c1,
0x0000, 0x0000, 0x02c9, 0x02c8, 0x02c8, 0x0000, 0x0000, 0x02ce,
0x0000, 0x02d0, 0x0000, 0x02d2, 0x0000, 0x0000, 0x02d5, 0x0000,
0x0000, 0x0000, 0x02d9, 0x0000, 0x02db, 0x0000, 0x02dd, 0x0000,
0x02df, 0x02df, 0x0000, 0x02e2, 0x0000, 0x02e4, 0x0000, 0x02e6,
0x02e6, 0x02e6, 0x02e6, 0x02e6, 0x0000, 0x02ec, 0x02ed, 0x02ec,
0x0000, 0x02f0,
} // Size: 1532 bytes
// Total table size 1528 bytes (1KiB); checksum: B99CF952
// Total table size 1532 bytes (1KiB); checksum: 90718A2
+4605 -4614
View File
File diff suppressed because it is too large Load Diff
@@ -806,10 +806,10 @@ func (b *builder) writeLanguage() {
}
}
// Complete canonialized language tags.
// Complete canonicalized language tags.
lang.freeze()
for i, v := range lang.s {
// We can avoid these manual entries by using the IANI registry directly.
// We can avoid these manual entries by using the IANA registry directly.
// Seems easier to update the list manually, as changes are rare.
// The panic in this loop will trigger if we miss an entry.
add := ""
@@ -916,7 +916,7 @@ func (b *builder) writeRegion() {
i := b.region.index(s)
for _, d := range e.description {
if strings.Contains(d, "Private use") {
regionTypes[i] = iso3166UserAssgined
regionTypes[i] = iso3166UserAssigned
}
}
regionTypes[i] |= bcp47Region
@@ -1073,7 +1073,7 @@ const (
)
const (
iso3166UserAssgined = 1 << iota
iso3166UserAssigned = 1 << iota
ccTLD
bcp47Region
)
@@ -1363,42 +1363,23 @@ func (b *builder) writeLikelyData() {
type mutualIntelligibility struct {
want, have uint16
conf uint8
distance uint8
oneway bool
}
type scriptIntelligibility struct {
lang uint16 // langID or 0 if *
want, have uint8
conf uint8
wantLang, haveLang uint16
wantScript, haveScript uint8
distance uint8
// Always oneway
}
type sortByConf []mutualIntelligibility
func (l sortByConf) Less(a, b int) bool {
return l[a].conf > l[b].conf
}
func (l sortByConf) Swap(a, b int) {
l[a], l[b] = l[b], l[a]
}
func (l sortByConf) Len() int {
return len(l)
}
// toConf converts a percentage value [0, 100] to a confidence class.
func toConf(pct uint8) uint8 {
switch {
case pct == 100:
return 3 // Exact
case pct >= 90:
return 2 // High
case pct > 50:
return 1 // Low
default:
return 0 // No
}
type regionIntelligibility struct {
lang uint16 // compact language id
script uint8 // 0 means any
group uint8 // 0 means any; if bit 7 is set it means inverse
distance uint8
// Always twoway.
}
// writeMatchData writes tables with languages and scripts for which there is
@@ -1408,13 +1389,50 @@ func toConf(pct uint8) uint8 {
// We also drop all region-related data as we use a different algorithm to
// determine region equivalence.
func (b *builder) writeMatchData() {
lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written_new")
regionHierarchy := map[string][]string{}
for _, g := range b.supp.TerritoryContainment.Group {
regions := strings.Split(g.Contains, " ")
regionHierarchy[g.Type] = append(regionHierarchy[g.Type], regions...)
}
regionToGroups := make([]uint8, len(b.region.s))
idToIndex := map[string]uint8{}
for i, mv := range lm[0].MatchVariable {
if i > 6 {
log.Fatalf("Too many groups: %d", i)
}
idToIndex[mv.Id] = uint8(i + 1)
// TODO: also handle '-'
for _, r := range strings.Split(mv.Value, "+") {
todo := []string{r}
for k := 0; k < len(todo); k++ {
r := todo[k]
regionToGroups[b.region.index(r)] |= 1 << uint8(i)
todo = append(todo, regionHierarchy[r]...)
}
}
}
b.writeSlice("regionToGroups", regionToGroups)
b.writeType(mutualIntelligibility{})
b.writeType(scriptIntelligibility{})
lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written")
b.writeType(regionIntelligibility{})
matchLang := []mutualIntelligibility{}
matchLang := []mutualIntelligibility{{
// TODO: remove once CLDR is fixed.
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("hr")),
distance: uint8(5),
}, {
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("bs")),
distance: uint8(5),
}}
matchScript := []scriptIntelligibility{}
matchRegion := []regionIntelligibility{}
// Convert the languageMatch entries in lists keyed by desired language.
for _, m := range lm[0].LanguageMatch {
// Different versions of CLDR use different separators.
@@ -1422,33 +1440,38 @@ func (b *builder) writeMatchData() {
supported := strings.Replace(m.Supported, "-", "_", -1)
d := strings.Split(desired, "_")
s := strings.Split(supported, "_")
if len(d) != len(s) || len(d) > 2 {
// Skip all entries with regions and work around CLDR bug.
if len(d) != len(s) {
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
pct, _ := strconv.ParseInt(m.Percent, 10, 8)
if len(d) == 2 && d[0] == s[0] && len(d[1]) == 4 {
// language-script pair.
lang := uint16(0)
if d[0] != "*" {
lang = uint16(b.langIndex(d[0]))
distance, _ := strconv.ParseInt(m.Distance, 10, 8)
switch len(d) {
case 2:
if desired == supported && desired == "*_*" {
continue
}
// language-script pair.
matchScript = append(matchScript, scriptIntelligibility{
lang: lang,
want: uint8(b.script.index(d[1])),
have: uint8(b.script.index(s[1])),
conf: toConf(uint8(pct)),
wantLang: uint16(b.langIndex(d[0])),
haveLang: uint16(b.langIndex(s[0])),
wantScript: uint8(b.script.index(d[1])),
haveScript: uint8(b.script.index(s[1])),
distance: uint8(distance),
})
if m.Oneway != "true" {
matchScript = append(matchScript, scriptIntelligibility{
lang: lang,
want: uint8(b.script.index(s[1])),
have: uint8(b.script.index(d[1])),
conf: toConf(uint8(pct)),
wantLang: uint16(b.langIndex(s[0])),
haveLang: uint16(b.langIndex(d[0])),
wantScript: uint8(b.script.index(s[1])),
haveScript: uint8(b.script.index(d[1])),
distance: uint8(distance),
})
}
} else if len(d) == 1 && d[0] != "*" {
if pct == 100 {
case 1:
if desired == supported && desired == "*" {
continue
}
if distance == 1 {
// nb == no is already handled by macro mapping. Check there
// really is only this case.
if d[0] != "no" || s[0] != "nb" {
@@ -1456,28 +1479,57 @@ func (b *builder) writeMatchData() {
}
continue
}
// TODO: consider dropping oneway field and just doubling the entry.
matchLang = append(matchLang, mutualIntelligibility{
want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])),
conf: uint8(pct),
oneway: m.Oneway == "true",
want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])),
distance: uint8(distance),
oneway: m.Oneway == "true",
})
} else {
// TODO: Handle other mappings.
a := []string{"*;*", "*_*;*_*", "es_MX;es_419"}
s := strings.Join([]string{desired, supported}, ";")
if i := sort.SearchStrings(a, s); i == len(a) || a[i] != s {
log.Printf("%q not handled", s)
case 3:
if desired == supported && desired == "*_*_*" {
continue
}
if desired != supported { // (Weird but correct.)
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
ri := regionIntelligibility{
lang: b.langIndex(d[0]),
distance: uint8(distance),
}
if d[1] != "*" {
ri.script = uint8(b.script.index(d[1]))
}
switch {
case d[2] == "*":
ri.group = 0x80 // not contained in anything
case strings.HasPrefix(d[2], "$!"):
ri.group = 0x80
d[2] = "$" + d[2][len("$!"):]
fallthrough
case strings.HasPrefix(d[2], "$"):
ri.group |= idToIndex[d[2]]
}
matchRegion = append(matchRegion, ri)
default:
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
}
}
sort.Stable(sortByConf(matchLang))
// collapse percentage into confidence classes
for i, m := range matchLang {
matchLang[i].conf = toConf(m.conf)
}
sort.SliceStable(matchLang, func(i, j int) bool {
return matchLang[i].distance < matchLang[j].distance
})
b.writeSlice("matchLang", matchLang)
sort.SliceStable(matchScript, func(i, j int) bool {
return matchScript[i].distance < matchScript[j].distance
})
b.writeSlice("matchScript", matchScript)
sort.SliceStable(matchRegion, func(i, j int) bool {
return matchRegion[i].distance < matchRegion[j].distance
})
b.writeSlice("matchRegion", matchRegion)
}
func (b *builder) writeRegionInclusionData() {
@@ -1521,7 +1573,6 @@ func (b *builder) writeRegionInclusionData() {
for _, v := range l {
regionContainment[g] |= 1 << v
}
// log.Printf("%d: %X", g, regionContainment[g])
}
b.writeSlice("regionContainment", regionContainment)
+755 -753
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run maketables.go gen_common.go -output tables.go
//go:generate go run gen.go gen_common.go -output tables.go
//go:generate go run gen_index.go
// Package language implements BCP 47 language tags and related functionality.
+16 -4
View File
@@ -440,8 +440,10 @@ func makeHaveTag(tag Tag, index int) (haveTag, langID) {
// script to map to another and we rely on this to keep the code simple.
func altScript(l langID, s scriptID) scriptID {
for _, alt := range matchScript {
if (alt.lang == 0 || langID(alt.lang) == l) && scriptID(alt.have) == s {
return scriptID(alt.want)
// TODO: also match cases where language is not the same.
if (langID(alt.wantLang) == l || langID(alt.haveLang) == l) &&
scriptID(alt.haveScript) == s {
return scriptID(alt.wantScript)
}
}
return 0
@@ -486,6 +488,16 @@ func (m *matcher) header(l langID) *matchHeader {
return h
}
func toConf(d uint8) Confidence {
if d <= 10 {
return High
}
if d < 30 {
return Low
}
return No
}
// newMatcher builds an index for the given supported tags and returns it as
// a matcher. It also expands the index by considering various equivalence classes
// for a given tag.
@@ -537,9 +549,9 @@ func newMatcher(supported []Tag) *matcher {
// Add entries for languages with mutual intelligibility as defined by CLDR's
// languageMatch data.
for _, ml := range matchLang {
update(ml.want, ml.have, Confidence(ml.conf), false)
update(ml.want, ml.have, toConf(ml.distance), false)
if !ml.oneway {
update(ml.have, ml.want, Confidence(ml.conf), false)
update(ml.have, ml.want, toConf(ml.distance), false)
}
}
+2279 -2172
View File
File diff suppressed because it is too large Load Diff
+9 -94
View File
@@ -8,106 +8,21 @@ package message
// Documentation and method names will reflect this by using the exported name.
import (
"sync"
"golang.org/x/text/internal"
"golang.org/x/text/internal/format"
"golang.org/x/text/language"
"golang.org/x/text/message/catalog"
)
// DefaultCatalog is used by SetString.
var DefaultCatalog *Catalog = newCatalog()
var DefaultCatalog *catalog.Catalog = defaultCatalog
// SetString calls SetString on the default Catalog.
var defaultCatalog = catalog.New()
// SetString calls SetString on the initial default Catalog.
func SetString(tag language.Tag, key string, msg string) error {
return DefaultCatalog.SetString(tag, key, msg)
return defaultCatalog.SetString(tag, key, msg)
}
// TODO:
// // SetSelect is a shorthand for DefaultCatalog.SetSelect.
// func SetSelect(tag language.Tag, key string, s ...format.Statement) error {
// return DefaultCatalog.SetSelect(tag, key, s...)
// }
type msgMap map[string]format.Statement
// A Catalog holds translations for messages for supported languages.
type Catalog struct {
index map[language.Tag]msgMap
mutex sync.Mutex // For locking all operations.
}
// Printer creates a Printer that uses c.
func (c *Catalog) Printer(tag language.Tag) *Printer {
// TODO: pre-create indexes for tag lookup.
return &Printer{
tag: tag,
cat: c,
}
}
// NewCatalog returns a new Catalog. If a message is not present in a Catalog,
// the fallback Catalogs will be used in order as an alternative source.
func newCatalog(fallback ...*Catalog) *Catalog {
// TODO: implement fallback.
return &Catalog{
index: map[language.Tag]msgMap{},
}
}
// Languages returns a slice of all languages for which the Catalog contains
// variants.
func (c *Catalog) Languages() []language.Tag {
c.mutex.Lock()
defer c.mutex.Unlock()
tags := []language.Tag{}
for t, _ := range c.index {
tags = append(tags, t)
}
internal.SortTags(tags)
return tags
}
// SetString sets the translation for the given language and key.
func (c *Catalog) SetString(tag language.Tag, key string, msg string) error {
return c.set(tag, key, format.String(msg))
}
func (c *Catalog) get(tag language.Tag, key string) (msg string, ok bool) {
c.mutex.Lock()
defer c.mutex.Unlock()
for ; ; tag = tag.Parent() {
if msgs, ok := c.index[tag]; ok {
if statement, ok := msgs[key]; ok {
// TODO: use type switches when we implement selecting.
msg := string(statement.(format.String))
return msg, true
}
}
if tag == language.Und {
break
}
}
return "", false
}
func (c *Catalog) set(tag language.Tag, key string, s ...format.Statement) error {
if len(s) != 1 {
// TODO: handle errors properly when we process statement sequences.
panic("statement sequence should be of length 1")
}
c.mutex.Lock()
defer c.mutex.Unlock()
m := c.index[tag]
if m == nil {
m = map[string]format.Statement{}
c.index[tag] = m
}
m[key] = s[0]
return nil
// Set calls Set on the initial default Catalog.
func Set(tag language.Tag, key string, msg ...catalog.Message) error {
return defaultCatalog.Set(tag, key, msg...)
}
+292
View File
@@ -0,0 +1,292 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package catalog defines collections of translated format strings.
//
// This package mostly defines types for populating catalogs with messages. The
// catmsg package contains further definitions for creating custom message and
// dictionary types as well as packages that use Catalogs.
//
// Package catalog defines various interfaces: Dictionary, Loader, and Message.
// A Dictionary maintains a set of translations of format strings for a single
// language. The Loader interface defines a source of dictionaries. A
// translation of a format string is represented by a Message.
//
//
// Catalogs
//
// A Catalog defines a programmatic interface for setting message translations.
// It maintains a set of per-language dictionaries with translations for a set
// of keys. For message translation to function properly, a translation should
// be defined for each key for each supported language. A dictionary may be
// underspecified, though, if there is a parent language that already defines
// the key. For example, a Dictionary for "en-GB" could leave out entries that
// are identical to those in a dictionary for "en".
//
//
// Messages
//
// A Message is a format string which varies on the value of substitution
// variables. For instance, to indicate the number of results one could want "no
// results" if there are none, "1 result" if there is 1, and "%d results" for
// any other number. Catalog is agnostic to the kind of format strings that are
// used: for instance, messages can follow either the printf-style substitution
// from package fmt or use templates.
//
// A Message does not substitute arguments in the format string. This job is
// reserved for packages that render strings, such as message, that use Catalogs
// to selected string. This separation of concerns allows Catalog to be used to
// store any kind of formatting strings.
//
//
// Selecting messages based on linguistic features of substitution arguments
//
// Messages may vary based on any linguistic features of the argument values.
// The most common one is plural form, but others exist.
//
// Selection messages are provided in packages that provide support for a
// specific linguistic feature. The following snippet uses plural.Select:
//
// catalog.Set(language.English, "You are %d minute(s) late.",
// plural.Select(1,
// "one", "You are 1 minute late.",
// "other", "You are %d minutes late."))
//
// In this example, a message is stored in the Catalog where one of two messages
// is selected based on the first argument, a number. The first message is
// selected if the argument is singular (identified by the selector "one") and
// the second message is selected in all other cases. The selectors are defined
// by the plural rules defined in CLDR. The selector "other" is special and will
// always match. Each language always defines one of the linguistic categories
// to be "other." For English, singular is "one" and plural is "other".
//
// Selects can be nested. This allows selecting sentences based on features of
// multiple arguments or multiple linguistic properties of a single argument.
//
//
// String interpolation
//
// There is often a lot of commonality between the possible variants of a
// message. For instance, in the example above the word "minute" varies based on
// the plural catogory of the argument, but the rest of the sentence is
// identical. Using interpolation the above message can be rewritten as:
//
// catalog.Set(language.English, "You are %d minute(s) late.",
// catalog.Var("minutes",
// plural.Select(1, "one", "minute", "other", "minutes")),
// catalog.String("You are %[1]d ${minutes} late."))
//
// Var is defined to return the variable name if the message does not yield a
// match. This allows us to further simplify this snippet to
//
// catalog.Set(language.English, "You are %d minute(s) late.",
// catalog.Var("minutes", plural.Select(1, "one", "minute")),
// catalog.String("You are %d ${minutes} late."))
//
// Overall this is still only a minor improvement, but things can get a lot more
// unwieldy if more than one linguistic feature is used to determine a message
// variant. Consider the following example:
//
// // argument 1: list of hosts, argument 2: list of guests
// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
// catalog.Var("their",
// plural.Select(1,
// "one", gender.Select(1, "female", "her", "other", "his"))),
// catalog.Var("invites", plural.Select(1, "one", "invite"))
// catalog.String("%[1]v ${invites} %[2]v to ${their} party.")),
//
// Without variable substitution, this would have to be written as
//
// // argument 1: list of hosts, argument 2: list of guests
// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
// plural.Select(1,
// "one", gender.Select(1,
// "female", "%[1]v invites %[2]v to her party."
// "other", "%[1]v invites %[2]v to his party."),
// "other", "%[1]v invites %[2]v to their party.")
//
// Not necessarily shorter, but using variables there is less duplication and
// the messages are more maintenance friendly. Moreover, languages may have up
// to six plural forms. This makes the use of variables more welcome.
//
// Different messages using the same inflections can reuse variables by moving
// them to macros. Using macros we can rewrite the message as:
//
// // argument 1: list of hosts, argument 2: list of guests
// catalog.SetString(language.English, "%[1]v invite(s) %[2]v to their party.",
// "%[1]v ${invites(1)} %[2]v to ${their(1)} party.")
//
// Where the following macros were defined separately.
//
// catalog.SetMacro(language.English, "invites", plural.Select(1, "one", "invite"))
// catalog.SetMacro(language.English, "their", plural.Select(1,
// "one", gender.Select(1, "female", "her", "other", "his"))),
//
// Placeholders use parentheses and the arguments to invoke a macro.
//
//
// Looking up messages
//
// Message lookup using Catalogs is typically only done by specialized packages
// and is not something the user should be concerned with. For instance, to
// express the tardiness of a user using the related message we defined earlier,
// the user may use the package message like so:
//
// p := message.NewPrinter(language.English)
// p.Printf("You are %d minute(s) late.", 5)
//
// Which would print:
// You are 5 minutes late.
//
//
// This package is UNDER CONSTRUCTION and its API may change.
package catalog // import "golang.org/x/text/message/catalog"
// TODO:
// Some way to freeze a catalog.
// - Locking on each lockup turns out to be about 50% of the total running time
// for some of the benchmarks in the message package.
// Consider these:
// - Sequence type to support sequences in user-defined messages.
// - Garbage collection: Remove dictionaries that can no longer be reached
// as other dictionaries have been added that cover all possible keys.
import (
"errors"
"fmt"
"golang.org/x/text/internal/catmsg"
"golang.org/x/text/language"
)
// A Catalog holds translations for messages for supported languages.
type Catalog struct {
options
index store
macros store
}
type options struct{}
// An Option configures Catalog behavior.
type Option func(*options)
// TODO:
// // Catalogs specifies one or more sources for a Catalog.
// // Lookups are in order.
// // This can be changed inserting a Catalog used for setting, which implements
// // Loader, used for setting in the chain.
// func Catalogs(d ...Loader) Option {
// return nil
// }
//
// func Delims(start, end string) Option {}
//
// func Dict(tag language.Tag, d ...Dictionary) Option
// New returns a new Catalog.
func New(opts ...Option) *Catalog {
c := &Catalog{}
for _, o := range opts {
o(&c.options)
}
return c
}
// Languages returns all languages for which the Catalog contains variants.
func (c *Catalog) Languages() []language.Tag {
return c.index.languages()
}
// SetString is shorthand for Set(tag, key, String(msg)).
func (c *Catalog) SetString(tag language.Tag, key string, msg string) error {
return c.set(tag, key, &c.index, String(msg))
}
// Set sets the translation for the given language and key.
//
// When evaluation this message, the first Message in the sequence to msgs to
// evaluate to a string will be the message returned.
func (c *Catalog) Set(tag language.Tag, key string, msg ...Message) error {
return c.set(tag, key, &c.index, msg...)
}
// SetMacro defines a Message that may be substituted in another message.
// The arguments to a macro Message are passed as arguments in the
// placeholder the form "${foo(arg1, arg2)}".
func (c *Catalog) SetMacro(tag language.Tag, name string, msg ...Message) error {
return c.set(tag, name, &c.macros, msg...)
}
// ErrNotFound indicates there was no message for the given key.
var ErrNotFound = errors.New("catalog: message not found")
// A Message holds a collection of translations for the same phrase that may
// vary based on the values of substitution arguments.
type Message interface {
catmsg.Message
}
// String specifies a plain message string. It can be used as fallback if no
// other strings match or as a simple standalone message.
//
// It is an error to pass more than one String in a message sequence.
func String(name string) Message {
return catmsg.String(name)
}
// Var sets a variable that may be substituted in formatting patterns using
// named substitution of the form "${name}". The name argument is used as a
// fallback if the statements do not produce a match. The statement sequence may
// not contain any Var calls.
//
// The name passed to a Var must be unique within message sequence.
func Var(name string, msg ...Message) Message {
return &catmsg.Var{Name: name, Message: firstInSequence(msg)}
}
// firstInSequence is a message type that prints the first message in the
// sequence that resolves to a match for the given substitution arguments.
type firstInSequence []Message
func (s firstInSequence) Compile(e *catmsg.Encoder) error {
e.EncodeMessageType(catmsg.First)
err := catmsg.ErrIncomplete
for i, m := range s {
if err == nil {
return fmt.Errorf("catalog: message argument %d is complete and blocks subsequent messages", i-1)
}
err = e.EncodeMessage(m)
}
return err
}
// Context returns a Context for formatting messages.
// Only one Message may be formatted per context at any given time.
func (c *Catalog) Context(tag language.Tag, r catmsg.Renderer) *Context {
return &Context{
cat: c,
tag: tag,
dec: catmsg.NewDecoder(tag, r, &dict{&c.macros, tag}),
}
}
// A Context is used for evaluating Messages.
// Only one Message may be formatted per context at any given time.
type Context struct {
cat *Catalog
tag language.Tag
dec *catmsg.Decoder
}
// Execute looks up and executes the message with the given key.
// It returns ErrNotFound if no message could be found in the index.
func (c *Context) Execute(key string) error {
data, ok := c.cat.index.lookup(c.tag, key)
if !ok {
return ErrNotFound
}
return c.dec.Execute(data)
}
+194
View File
@@ -0,0 +1,194 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package catalog
import (
"bytes"
"fmt"
"reflect"
"testing"
"golang.org/x/text/internal"
"golang.org/x/text/internal/catmsg"
"golang.org/x/text/language"
)
type entry struct {
tag, key string
msg interface{}
}
var testCases = []struct {
desc string
cat []entry
lookup []entry
}{{
desc: "empty catalog",
lookup: []entry{
{"en", "key", ""},
{"en", "", ""},
{"nl", "", ""},
},
}, {
desc: "one entry",
cat: []entry{
{"en", "hello", "Hello!"},
},
lookup: []entry{
{"und", "hello", ""},
{"nl", "hello", ""},
{"en", "hello", "Hello!"},
{"en-US", "hello", "Hello!"},
{"en-GB", "hello", "Hello!"},
{"en-oxendict", "hello", "Hello!"},
{"en-oxendict-u-ms-metric", "hello", "Hello!"},
},
}, {
desc: "hierarchical languages",
cat: []entry{
{"en", "hello", "Hello!"},
{"en-GB", "hello", "Hellø!"},
{"en-US", "hello", "Howdy!"},
{"en", "greetings", "Greetings!"},
},
lookup: []entry{
{"und", "hello", ""},
{"nl", "hello", ""},
{"en", "hello", "Hello!"},
{"en-US", "hello", "Howdy!"},
{"en-GB", "hello", "Hellø!"},
{"en-oxendict", "hello", "Hello!"},
{"en-US-oxendict-u-ms-metric", "hello", "Howdy!"},
{"und", "greetings", ""},
{"nl", "greetings", ""},
{"en", "greetings", "Greetings!"},
{"en-US", "greetings", "Greetings!"},
{"en-GB", "greetings", "Greetings!"},
{"en-oxendict", "greetings", "Greetings!"},
{"en-US-oxendict-u-ms-metric", "greetings", "Greetings!"},
},
}, {
desc: "variables",
cat: []entry{
{"en", "hello %s", []Message{
Var("person", String("Jane")),
String("Hello ${person}!"),
}},
{"en", "hello error", []Message{
Var("person", String("Jane")),
noMatchMessage{}, // trigger sequence path.
String("Hello ${person."),
}},
{"en", "fallback to var value", []Message{
Var("you", noMatchMessage{}, noMatchMessage{}),
String("Hello ${you}."),
}},
{"en", "scopes", []Message{
Var("person1", String("Mark")),
Var("person2", String("Jane")),
Var("couple",
Var("person1", String("Joe")),
String("${person1} and ${person2}")),
String("Hello ${couple}."),
}},
{"en", "missing var", String("Hello ${missing}.")},
},
lookup: []entry{
{"en", "hello %s", "Hello Jane!"},
{"en", "hello error", "Hello $!(MISSINGBRACE)"},
{"en", "fallback to var value", "Hello you."},
{"en", "scopes", "Hello Joe and Jane."},
{"en", "missing var", "Hello missing."},
},
}, {
desc: "macros",
cat: []entry{
{"en", "macro1", String("Hello ${macro1(1)}.")},
{"en", "macro2", String("Hello ${ macro1(2) }!")},
{"en", "macroWS", String("Hello ${ macro1( 2 ) }!")},
{"en", "missing", String("Hello ${ missing(1 }.")},
{"en", "badnum", String("Hello ${ badnum(1b) }.")},
{"en", "undefined", String("Hello ${ undefined(1) }.")},
{"en", "macroU", String("Hello ${ macroU(2) }!")},
},
lookup: []entry{
{"en", "macro1", "Hello Joe."},
{"en", "macro2", "Hello Joe!"},
{"en-US", "macroWS", "Hello Joe!"},
{"en-NL", "missing", "Hello $!(MISSINGPAREN)."},
{"en", "badnum", "Hello $!(BADNUM)."},
{"en", "undefined", "Hello undefined."},
{"en", "macroU", "Hello macroU!"},
}}}
func initCat(entries []entry) (*Catalog, []language.Tag) {
tags := []language.Tag{}
cat := New()
for _, e := range entries {
tag := language.MustParse(e.tag)
tags = append(tags, tag)
switch msg := e.msg.(type) {
case string:
cat.SetString(tag, e.key, msg)
case Message:
cat.Set(tag, e.key, msg)
case []Message:
cat.Set(tag, e.key, msg...)
}
}
return cat, internal.UniqueTags(tags)
}
func TestCatalog(t *testing.T) {
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s", tc.desc), func(t *testing.T) {
cat, wantTags := initCat(tc.cat)
cat.SetMacro(language.English, "macro1", String("Joe"))
cat.SetMacro(language.Und, "macro2", String("${macro1(1)}"))
cat.SetMacro(language.English, "macroU", noMatchMessage{})
if got := cat.Languages(); !reflect.DeepEqual(got, wantTags) {
t.Errorf("%s:Languages: got %v; want %v", tc.desc, got, wantTags)
}
for _, e := range tc.lookup {
t.Run(fmt.Sprintf("%s/%s", e.tag, e.key), func(t *testing.T) {
tag := language.MustParse(e.tag)
buf := testRenderer{}
ctx := cat.Context(tag, &buf)
want := e.msg.(string)
err := ctx.Execute(e.key)
gotFound := err != ErrNotFound
wantFound := want != ""
if gotFound != wantFound {
t.Fatalf("err: got %v (%v); want %v", gotFound, err, wantFound)
}
if got := buf.buf.String(); got != want {
t.Errorf("Lookup:\ngot %q\nwant %q", got, want)
}
})
}
})
}
}
type testRenderer struct {
buf bytes.Buffer
}
func (f *testRenderer) Arg(i int) interface{} { return nil }
func (f *testRenderer) Render(s string) { f.buf.WriteString(s) }
var msgNoMatch = catmsg.Register("no match", func(d *catmsg.Decoder) bool {
return false // no match
})
type noMatchMessage struct{}
func (noMatchMessage) Compile(e *catmsg.Encoder) error {
e.EncodeMessageType(msgNoMatch)
return catmsg.ErrIncomplete
}
+90
View File
@@ -0,0 +1,90 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package catalog
import (
"sync"
"golang.org/x/text/internal"
"golang.org/x/text/internal/catmsg"
"golang.org/x/text/language"
)
// TODO:
// Dictionary returns a Dictionary that returns the first Message, using the
// given language tag, that matches:
// 1. the last one registered by one of the Set methods
// 2. returned by one of the Loaders
// 3. repeat from 1. using the parent language
// This approach allows messages to be underspecified.
// func (c *Catalog) Dictionary(tag language.Tag) (Dictionary, error) {
// // TODO: verify dictionary exists.
// return &dict{&c.index, tag}, nil
// }
type dict struct {
s *store
tag language.Tag // TODO: make compact tag.
}
func (d *dict) Lookup(key string) (data string, ok bool) {
return d.s.lookup(d.tag, key)
}
func (c *Catalog) set(tag language.Tag, key string, s *store, msg ...Message) error {
data, err := catmsg.Compile(tag, &dict{&c.macros, tag}, firstInSequence(msg))
s.mutex.Lock()
defer s.mutex.Unlock()
m := s.index[tag]
if m == nil {
m = msgMap{}
if s.index == nil {
s.index = map[language.Tag]msgMap{}
}
s.index[tag] = m
}
m[key] = data
return err
}
type store struct {
mutex sync.RWMutex
index map[language.Tag]msgMap
}
type msgMap map[string]string
func (s *store) lookup(tag language.Tag, key string) (data string, ok bool) {
s.mutex.RLock()
defer s.mutex.RUnlock()
for ; ; tag = tag.Parent() {
if msgs, ok := s.index[tag]; ok {
if msg, ok := msgs[key]; ok {
return msg, true
}
}
if tag == language.Und {
break
}
}
return "", false
}
// Languages returns all languages for which the store contains variants.
func (s *store) languages() []language.Tag {
s.mutex.RLock()
defer s.mutex.RUnlock()
tags := make([]language.Tag, 0, len(s.index))
for t := range s.index {
tags = append(tags, t)
}
internal.SortTags(tags)
return tags
}
-98
View File
@@ -1,98 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package message
import (
"reflect"
"testing"
"golang.org/x/text/internal"
"golang.org/x/text/language"
)
type entry struct{ tag, key, msg string }
var testCases = []struct {
desc string
cat []entry
lookup []entry
}{{
desc: "empty catalog",
lookup: []entry{
{"en", "key", ""},
{"en", "", ""},
{"nl", "", ""},
},
}, {
desc: "one entry",
cat: []entry{
{"en", "hello", "Hello!"},
},
lookup: []entry{
{"und", "hello", ""},
{"nl", "hello", ""},
{"en", "hello", "Hello!"},
{"en-US", "hello", "Hello!"},
{"en-GB", "hello", "Hello!"},
{"en-oxendict", "hello", "Hello!"},
{"en-oxendict-u-ms-metric", "hello", "Hello!"},
},
}, {
desc: "hierarchical languages",
cat: []entry{
{"en", "hello", "Hello!"},
{"en-GB", "hello", "Hellø!"},
{"en-US", "hello", "Howdy!"},
{"en", "greetings", "Greetings!"},
},
lookup: []entry{
{"und", "hello", ""},
{"nl", "hello", ""},
{"en", "hello", "Hello!"},
{"en-US", "hello", "Howdy!"},
{"en-GB", "hello", "Hellø!"},
{"en-oxendict", "hello", "Hello!"},
{"en-US-oxendict-u-ms-metric", "hello", "Howdy!"},
{"und", "greetings", ""},
{"nl", "greetings", ""},
{"en", "greetings", "Greetings!"},
{"en-US", "greetings", "Greetings!"},
{"en-GB", "greetings", "Greetings!"},
{"en-oxendict", "greetings", "Greetings!"},
{"en-US-oxendict-u-ms-metric", "greetings", "Greetings!"},
},
}}
func initCat(entries []entry) (*Catalog, []language.Tag) {
tags := []language.Tag{}
cat := newCatalog()
for _, e := range entries {
tag := language.MustParse(e.tag)
tags = append(tags, tag)
cat.SetString(tag, e.key, e.msg)
}
return cat, internal.UniqueTags(tags)
}
func TestCatalog(t *testing.T) {
for _, tc := range testCases {
cat, wantTags := initCat(tc.cat)
// languages
if got := cat.Languages(); !reflect.DeepEqual(got, wantTags) {
t.Errorf("%s:Languages: got %v; want %v", tc.desc, got, wantTags)
}
// Lookup
for _, e := range tc.lookup {
tag := language.MustParse(e.tag)
msg, ok := cat.get(tag, e.key)
if okWant := e.msg != ""; ok != okWant || msg != e.msg {
t.Errorf("%s:Lookup(%s, %s) = %s, %v; want %s, %v", tc.desc, tag, e.key, msg, ok, e.msg, okWant)
}
}
}
}
+1891
View File
File diff suppressed because it is too large Load Diff
+532
View File
@@ -0,0 +1,532 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package message
import (
"bytes"
"strconv"
"unicode/utf8"
)
const (
ldigits = "0123456789abcdefx"
udigits = "0123456789ABCDEFX"
)
const (
signed = true
unsigned = false
)
// flags placed in a separate struct for easy clearing.
type fmtFlags struct {
widPresent bool
precPresent bool
minus bool
plus bool
sharp bool
space bool
zero bool
// For the formats %+v %#v, we set the plusV/sharpV flags
// and clear the plus/sharp flags since %+v and %#v are in effect
// different, flagless formats set at the top level.
plusV bool
sharpV bool
}
// A formatInfo is the raw formatter used by Printf etc.
// It prints into a buffer that must be set up separately.
type formatInfo struct {
buf *bytes.Buffer
fmtFlags
wid int // width
prec int // precision
// intbuf is large enough to store %b of an int64 with a sign and
// avoids padding at the end of the struct on 32 bit architectures.
intbuf [68]byte
}
func (f *formatInfo) clearflags() {
f.fmtFlags = fmtFlags{}
}
func (f *formatInfo) init(buf *bytes.Buffer) {
f.buf = buf
f.clearflags()
}
// writePadding generates n bytes of padding.
func (f *formatInfo) writePadding(n int) {
if n <= 0 { // No padding bytes needed.
return
}
f.buf.Grow(n)
// Decide which byte the padding should be filled with.
padByte := byte(' ')
if f.zero {
padByte = byte('0')
}
// Fill padding with padByte.
for i := 0; i < n; i++ {
f.buf.WriteByte(padByte) // TODO: make more efficient.
}
}
// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
func (f *formatInfo) pad(b []byte) {
if !f.widPresent || f.wid == 0 {
f.buf.Write(b)
return
}
width := f.wid - utf8.RuneCount(b)
if !f.minus {
// left padding
f.writePadding(width)
f.buf.Write(b)
} else {
// right padding
f.buf.Write(b)
f.writePadding(width)
}
}
// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
func (f *formatInfo) padString(s string) {
if !f.widPresent || f.wid == 0 {
f.buf.WriteString(s)
return
}
width := f.wid - utf8.RuneCountInString(s)
if !f.minus {
// left padding
f.writePadding(width)
f.buf.WriteString(s)
} else {
// right padding
f.buf.WriteString(s)
f.writePadding(width)
}
}
// fmt_boolean formats a boolean.
func (f *formatInfo) fmt_boolean(v bool) {
if v {
f.padString("true")
} else {
f.padString("false")
}
}
// fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
func (f *formatInfo) fmt_unicode(u uint64) {
buf := f.intbuf[0:]
// With default precision set the maximum needed buf length is 18
// for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
// into the already allocated intbuf with a capacity of 68 bytes.
prec := 4
if f.precPresent && f.prec > 4 {
prec = f.prec
// Compute space needed for "U+" , number, " '", character, "'".
width := 2 + prec + 2 + utf8.UTFMax + 1
if width > len(buf) {
buf = make([]byte, width)
}
}
// Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
i := len(buf)
// For %#U we want to add a space and a quoted character at the end of the buffer.
if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
i--
buf[i] = '\''
i -= utf8.RuneLen(rune(u))
utf8.EncodeRune(buf[i:], rune(u))
i--
buf[i] = '\''
i--
buf[i] = ' '
}
// Format the Unicode code point u as a hexadecimal number.
for u >= 16 {
i--
buf[i] = udigits[u&0xF]
prec--
u >>= 4
}
i--
buf[i] = udigits[u]
prec--
// Add zeros in front of the number until requested precision is reached.
for prec > 0 {
i--
buf[i] = '0'
prec--
}
// Add a leading "U+".
i--
buf[i] = '+'
i--
buf[i] = 'U'
oldZero := f.zero
f.zero = false
f.pad(buf[i:])
f.zero = oldZero
}
// fmt_integer formats signed and unsigned integers.
func (f *formatInfo) fmt_integer(u uint64, base int, isSigned bool, digits string) {
negative := isSigned && int64(u) < 0
if negative {
u = -u
}
buf := f.intbuf[0:]
// The already allocated f.intbuf with a capacity of 68 bytes
// is large enough for integer formatting when no precision or width is set.
if f.widPresent || f.precPresent {
// Account 3 extra bytes for possible addition of a sign and "0x".
width := 3 + f.wid + f.prec // wid and prec are always positive.
if width > len(buf) {
// We're going to need a bigger boat.
buf = make([]byte, width)
}
}
// Two ways to ask for extra leading zero digits: %.3d or %03d.
// If both are specified the f.zero flag is ignored and
// padding with spaces is used instead.
prec := 0
if f.precPresent {
prec = f.prec
// Precision of 0 and value of 0 means "print nothing" but padding.
if prec == 0 && u == 0 {
oldZero := f.zero
f.zero = false
f.writePadding(f.wid)
f.zero = oldZero
return
}
} else if f.zero && f.widPresent {
prec = f.wid
if negative || f.plus || f.space {
prec-- // leave room for sign
}
}
// Because printing is easier right-to-left: format u into buf, ending at buf[i].
// We could make things marginally faster by splitting the 32-bit case out
// into a separate block but it's not worth the duplication, so u has 64 bits.
i := len(buf)
// Use constants for the division and modulo for more efficient code.
// Switch cases ordered by popularity.
switch base {
case 10:
for u >= 10 {
i--
next := u / 10
buf[i] = byte('0' + u - next*10)
u = next
}
case 16:
for u >= 16 {
i--
buf[i] = digits[u&0xF]
u >>= 4
}
case 8:
for u >= 8 {
i--
buf[i] = byte('0' + u&7)
u >>= 3
}
case 2:
for u >= 2 {
i--
buf[i] = byte('0' + u&1)
u >>= 1
}
default:
panic("fmt: unknown base; can't happen")
}
i--
buf[i] = digits[u]
for i > 0 && prec > len(buf)-i {
i--
buf[i] = '0'
}
// Various prefixes: 0x, -, etc.
if f.sharp {
switch base {
case 8:
if buf[i] != '0' {
i--
buf[i] = '0'
}
case 16:
// Add a leading 0x or 0X.
i--
buf[i] = digits[16]
i--
buf[i] = '0'
}
}
if negative {
i--
buf[i] = '-'
} else if f.plus {
i--
buf[i] = '+'
} else if f.space {
i--
buf[i] = ' '
}
// Left padding with zeros has already been handled like precision earlier
// or the f.zero flag is ignored due to an explicitly set precision.
oldZero := f.zero
f.zero = false
f.pad(buf[i:])
f.zero = oldZero
}
// truncate truncates the string to the specified precision, if present.
func (f *formatInfo) truncate(s string) string {
if f.precPresent {
n := f.prec
for i := range s {
n--
if n < 0 {
return s[:i]
}
}
}
return s
}
// fmt_s formats a string.
func (f *formatInfo) fmt_s(s string) {
s = f.truncate(s)
f.padString(s)
}
// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
func (f *formatInfo) fmt_sbx(s string, b []byte, digits string) {
length := len(b)
if b == nil {
// No byte slice present. Assume string s should be encoded.
length = len(s)
}
// Set length to not process more bytes than the precision demands.
if f.precPresent && f.prec < length {
length = f.prec
}
// Compute width of the encoding taking into account the f.sharp and f.space flag.
width := 2 * length
if width > 0 {
if f.space {
// Each element encoded by two hexadecimals will get a leading 0x or 0X.
if f.sharp {
width *= 2
}
// Elements will be separated by a space.
width += length - 1
} else if f.sharp {
// Only a leading 0x or 0X will be added for the whole string.
width += 2
}
} else { // The byte slice or string that should be encoded is empty.
if f.widPresent {
f.writePadding(f.wid)
}
return
}
// Handle padding to the left.
if f.widPresent && f.wid > width && !f.minus {
f.writePadding(f.wid - width)
}
// Write the encoding directly into the output buffer.
buf := f.buf
if f.sharp {
// Add leading 0x or 0X.
buf.WriteByte('0')
buf.WriteByte(digits[16])
}
var c byte
for i := 0; i < length; i++ {
if f.space && i > 0 {
// Separate elements with a space.
buf.WriteByte(' ')
if f.sharp {
// Add leading 0x or 0X for each element.
buf.WriteByte('0')
buf.WriteByte(digits[16])
}
}
if b != nil {
c = b[i] // Take a byte from the input byte slice.
} else {
c = s[i] // Take a byte from the input string.
}
// Encode each byte as two hexadecimal digits.
buf.WriteByte(digits[c>>4])
buf.WriteByte(digits[c&0xF])
}
// Handle padding to the right.
if f.widPresent && f.wid > width && f.minus {
f.writePadding(f.wid - width)
}
}
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
func (f *formatInfo) fmt_sx(s, digits string) {
f.fmt_sbx(s, nil, digits)
}
// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
func (f *formatInfo) fmt_bx(b []byte, digits string) {
f.fmt_sbx("", b, digits)
}
// fmt_q formats a string as a double-quoted, escaped Go string constant.
// If f.sharp is set a raw (backquoted) string may be returned instead
// if the string does not contain any control characters other than tab.
func (f *formatInfo) fmt_q(s string) {
s = f.truncate(s)
if f.sharp && strconv.CanBackquote(s) {
f.padString("`" + s + "`")
return
}
buf := f.intbuf[:0]
if f.plus {
f.pad(strconv.AppendQuoteToASCII(buf, s))
} else {
f.pad(strconv.AppendQuote(buf, s))
}
}
// fmt_c formats an integer as a Unicode character.
// If the character is not valid Unicode, it will print '\ufffd'.
func (f *formatInfo) fmt_c(c uint64) {
r := rune(c)
if c > utf8.MaxRune {
r = utf8.RuneError
}
buf := f.intbuf[:0]
w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
f.pad(buf[:w])
}
// fmt_qc formats an integer as a single-quoted, escaped Go character constant.
// If the character is not valid Unicode, it will print '\ufffd'.
func (f *formatInfo) fmt_qc(c uint64) {
r := rune(c)
if c > utf8.MaxRune {
r = utf8.RuneError
}
buf := f.intbuf[:0]
if f.plus {
f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
} else {
f.pad(strconv.AppendQuoteRune(buf, r))
}
}
// fmt_float formats a float64. It assumes that verb is a valid format specifier
// for strconv.AppendFloat and therefore fits into a byte.
func (f *formatInfo) fmt_float(v float64, size int, verb rune, prec int) {
// Explicit precision in format specifier overrules default precision.
if f.precPresent {
prec = f.prec
}
// Format number, reserving space for leading + sign if needed.
num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
if num[1] == '-' || num[1] == '+' {
num = num[1:]
} else {
num[0] = '+'
}
// f.space means to add a leading space instead of a "+" sign unless
// the sign is explicitly asked for by f.plus.
if f.space && num[0] == '+' && !f.plus {
num[0] = ' '
}
// Special handling for infinities and NaN,
// which don't look like a number so shouldn't be padded with zeros.
if num[1] == 'I' || num[1] == 'N' {
oldZero := f.zero
f.zero = false
// Remove sign before NaN if not asked for.
if num[1] == 'N' && !f.space && !f.plus {
num = num[1:]
}
f.pad(num)
f.zero = oldZero
return
}
// The sharp flag forces printing a decimal point for non-binary formats
// and retains trailing zeros, which we may need to restore.
if f.sharp && verb != 'b' {
digits := 0
switch verb {
case 'v', 'g', 'G':
digits = prec
// If no precision is set explicitly use a precision of 6.
if digits == -1 {
digits = 6
}
}
// Buffer pre-allocated with enough room for
// exponent notations of the form "e+123".
var tailBuf [5]byte
tail := tailBuf[:0]
hasDecimalPoint := false
// Starting from i = 1 to skip sign at num[0].
for i := 1; i < len(num); i++ {
switch num[i] {
case '.':
hasDecimalPoint = true
case 'e', 'E':
tail = append(tail, num[i:]...)
num = num[:i]
default:
digits--
}
}
if !hasDecimalPoint {
num = append(num, '.')
}
for digits > 0 {
num = append(num, '0')
digits--
}
num = append(num, tail...)
}
// We want a sign if asked for and if the sign is not positive.
if f.plus || num[0] != '+' {
// If we're zero padding to the left we want the sign before the leading zeros.
// Achieve this by writing the sign out and then padding the unsigned number.
if f.zero && f.widPresent && f.wid > len(num) {
f.buf.WriteByte(num[0])
f.writePadding(f.wid - len(num))
f.buf.Write(num[1:])
return
}
f.pad(num)
return
}
// No sign to show and the number is positive; just print the unsigned number.
f.pad(num[1:])
}
+87 -95
View File
@@ -5,95 +5,132 @@
// Package message implements formatted I/O for localized strings with functions
// analogous to the fmt's print functions.
//
// These are the important differences with fmt:
// - Output varies per locale.
// - The '#' flag is used to bypass localization.
//
// NOTE: Under construction. See https://golang.org/design/12750-localization
// and its corresponding proposal issue https://golang.org/issues/12750.
package message // import "golang.org/x/text/message"
import (
"fmt"
"io"
"strings"
"os"
"golang.org/x/text/internal/format"
"golang.org/x/text/language"
"golang.org/x/text/message/catalog"
)
// TODO: allow more than one goroutine per printer. This will allow porting from
// fmt much less error prone.
// A Printer implements language-specific formatted I/O analogous to the fmt
// package. Only one goroutine may use a Printer at the same time.
type Printer struct {
tag language.Tag
cat *Catalog
// Wrap the fields in a hidden type to hide some of the implemented methods.
printer printer
// NOTE: limiting one goroutine per Printer allows for many optimizations
// and simplifications. We can consider removing this restriction down the
// road if it the benefits do not seem to outweigh the disadvantages.
}
type options struct {
cat *catalog.Catalog
// TODO:
// - allow %s to print integers in written form (tables are likely too large
// to enable this by default).
// - list behavior
//
}
// An Option defines an option of a Printer.
type Option func(o *options)
// Catalog defines the catalog to be used.
func Catalog(c *catalog.Catalog) Option {
return func(o *options) { o.cat = c }
}
// NewPrinter returns a Printer that formats messages tailored to language t.
func NewPrinter(t language.Tag) *Printer {
return DefaultCatalog.Printer(t)
func NewPrinter(t language.Tag, opts ...Option) *Printer {
options := &options{
cat: defaultCatalog,
}
for _, o := range opts {
o(options)
}
p := &Printer{printer{
tag: t,
}}
p.printer.toDecimal.InitDecimal(t)
p.printer.toScientific.InitScientific(t)
p.printer.catContext = options.cat.Context(t, &p.printer)
return p
}
// Sprint is like fmt.Sprint, but using language-specific formatting.
func (p *Printer) Sprint(a ...interface{}) string {
return fmt.Sprint(p.bindArgs(a)...)
p.printer.reset()
p.printer.doPrint(a)
return p.printer.String()
}
// Fprint is like fmt.Fprint, but using language-specific formatting.
func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprint(w, p.bindArgs(a)...)
p.printer.reset()
p.printer.doPrint(a)
n64, err := io.Copy(w, &p.printer.Buffer)
return int(n64), err
}
// Print is like fmt.Print, but using language-specific formatting.
func (p *Printer) Print(a ...interface{}) (n int, err error) {
return fmt.Print(p.bindArgs(a)...)
return p.Fprint(os.Stdout, a...)
}
// Sprintln is like fmt.Sprintln, but using language-specific formatting.
func (p *Printer) Sprintln(a ...interface{}) string {
return fmt.Sprintln(p.bindArgs(a)...)
p.printer.reset()
p.printer.doPrintln(a)
return p.printer.String()
}
// Fprintln is like fmt.Fprintln, but using language-specific formatting.
func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprintln(w, p.bindArgs(a)...)
p.printer.reset()
p.printer.doPrintln(a)
n64, err := io.Copy(w, &p.printer.Buffer)
return int(n64), err
}
// Println is like fmt.Println, but using language-specific formatting.
func (p *Printer) Println(a ...interface{}) (n int, err error) {
return fmt.Println(p.bindArgs(a)...)
return p.Fprintln(os.Stdout, a...)
}
// Sprintf is like fmt.Sprintf, but using language-specific formatting.
func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
msg, hasSub := p.lookup(key)
if !hasSub {
return fmt.Sprintf(msg) // work around limitation of fmt
}
return fmt.Sprintf(msg, p.bindArgs(a)...)
lookupAndFormat(p, key, a)
return p.printer.String()
}
// Fprintf is like fmt.Fprintf, but using language-specific formatting.
func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
msg, hasSub := p.lookup(key)
if !hasSub {
return fmt.Fprintf(w, msg) // work around limitation of fmt
}
return fmt.Fprintf(w, msg, p.bindArgs(a)...)
lookupAndFormat(p, key, a)
return w.Write(p.printer.Bytes())
}
// Printf is like fmt.Printf, but using language-specific formatting.
func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
msg, hasSub := p.lookup(key)
if !hasSub {
return fmt.Printf(msg) // work around limitation of fmt
}
return fmt.Printf(msg, p.bindArgs(a)...)
lookupAndFormat(p, key, a)
return os.Stdout.Write(p.printer.Bytes())
}
func (p *Printer) lookup(r Reference) (msg string, hasSub bool) {
var id string
func lookupAndFormat(p *Printer, r Reference, a []interface{}) {
p.printer.reset()
p.printer.args = a
var id, msg string
switch v := r.(type) {
case string:
id, msg = v, v
@@ -102,33 +139,31 @@ func (p *Printer) lookup(r Reference) (msg string, hasSub bool) {
default:
panic("key argument is not a Reference")
}
if s, ok := p.cat.get(p.tag, id); ok {
msg = s
}
// fmt does not allow all arguments to be dropped in a format string. It
// only allows arguments to be dropped if at least one of the substitutions
// uses the positional marker (e.g. %[1]s). This hack works around this.
// TODO: This is only an approximation of the parsing of substitution
// patterns. Make more precise once we know if we can get by with fmt's
// formatting, which may not be the case.
for i := 0; i < len(msg)-1; i++ {
if msg[i] == '%' {
for i++; i < len(msg); i++ {
if strings.IndexByte("[]#+- *01234567890.", msg[i]) < 0 {
break
}
}
if i < len(msg) && msg[i] != '%' {
hasSub = true
break
}
if p.printer.catContext.Execute(id) == catalog.ErrNotFound {
if p.printer.catContext.Execute(msg) == catalog.ErrNotFound {
p.printer.Render(msg)
return
}
}
return msg, hasSub
}
// Arg implements catmsg.Renderer.
func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
if uint(i) < uint(len(p.args)) {
return p.args[i]
}
return nil
}
// Render implements catmsg.Renderer.
func (p *printer) Render(msg string) {
p.doPrintf(msg)
}
// A Reference is a string or a message reference.
type Reference interface {
// TODO: also allow []string
}
// Key creates a message Reference for a message where the given id is used for
@@ -140,46 +175,3 @@ func Key(id string, fallback string) Reference {
type key struct {
id, fallback string
}
// bindArgs wraps arguments with implementation of fmt.Formatter, if needed.
func (p *Printer) bindArgs(a []interface{}) []interface{} {
out := make([]interface{}, len(a))
for i, x := range a {
switch v := x.(type) {
case fmt.Formatter:
// Wrap the value with a Formatter that augments the State with
// language-specific attributes.
out[i] = &value{v, p}
// NOTE: as we use fmt.Formatter, we can't distinguish between
// regular and localized formatters, so we always need to wrap it.
// TODO: handle
// - numbers
// - lists
// - time?
default:
out[i] = x
}
}
return out
}
// state implements "golang.org/x/text/internal/format".State.
type state struct {
fmt.State
p *Printer
}
func (s *state) Language() language.Tag { return s.p.tag }
var _ format.State = &state{}
type value struct {
x fmt.Formatter
p *Printer
}
func (v *value) Format(s fmt.State, verb rune) {
v.x.Format(&state{s, v.p}, verb)
}
+45 -13
View File
@@ -10,8 +10,10 @@ import (
"io"
"testing"
"golang.org/x/text/internal"
"golang.org/x/text/internal/format"
"golang.org/x/text/language"
"golang.org/x/text/message/catalog"
)
type formatFunc func(s fmt.State, v rune)
@@ -48,13 +50,14 @@ func TestBinding(t *testing.T) {
}
}
func TestFormatSelection(t *testing.T) {
func TestLocalization(t *testing.T) {
type test struct {
tag string
key Reference
args []interface{}
want string
}
args := func(x ...interface{}) []interface{} { return x }
empty := []interface{}{}
joe := []interface{}{"Joe"}
joeAndMary := []interface{}{"Joe", "Mary"}
@@ -124,26 +127,55 @@ func TestFormatSelection(t *testing.T) {
{"und", "hello %+%%s", joeAndMary, "hello %Joe%!(EXTRA string=Mary)"},
{"und", "hello %-42%%s ", joeAndMary, "hello %Joe %!(EXTRA string=Mary)"},
},
}, {
desc: "number formatting", // work around limitation of fmt
cat: []entry{
{"und", "files", "%d files left"},
{"und", "meters", "%.2f meters"},
{"de", "files", "%d Dateien übrig"},
},
test: []test{
{"en", "meters", args(3000.2), "3,000.20 meters"},
{"en-u-nu-gujr", "files", args(123456), "૧૨૩,૪૫૬ files left"},
{"de", "files", args(1234), "1.234 Dateien übrig"},
{"de-CH", "files", args(1234), "1’234 Dateien übrig"},
{"de-CH-u-nu-mong", "files", args(1234), "᠑’᠒᠓᠔ Dateien übrig"},
},
}}
for _, tc := range testCases {
cat, _ := initCat(tc.cat)
for i, pt := range tc.test {
p := cat.Printer(language.MustParse(pt.tag))
t.Run(fmt.Sprintf("%s:%d", tc.desc, i), func(t *testing.T) {
p := NewPrinter(language.MustParse(pt.tag), Catalog(cat))
if got := p.Sprintf(pt.key, pt.args...); got != pt.want {
t.Errorf("%s:%d:Sprintf(%s, %v) = %s; want %s",
tc.desc, i, pt.key, pt.args, got, pt.want)
continue // Next error will likely be the same.
}
if got := p.Sprintf(pt.key, pt.args...); got != pt.want {
t.Errorf("Sprintf(%q, %v) = %s; want %s",
pt.key, pt.args, got, pt.want)
return // Next error will likely be the same.
}
w := &bytes.Buffer{}
p.Fprintf(w, pt.key, pt.args...)
if got := w.String(); got != pt.want {
t.Errorf("%s:%d:Fprintf(%s, %v) = %s; want %s",
tc.desc, i, pt.key, pt.args, got, pt.want)
}
w := &bytes.Buffer{}
p.Fprintf(w, pt.key, pt.args...)
if got := w.String(); got != pt.want {
t.Errorf("Fprintf(%q, %v) = %s; want %s",
pt.key, pt.args, got, pt.want)
}
})
}
}
}
type entry struct{ tag, key, msg string }
func initCat(entries []entry) (*catalog.Catalog, []language.Tag) {
tags := []language.Tag{}
cat := catalog.New()
for _, e := range entries {
tag := language.MustParse(e.tag)
tags = append(tags, tag)
cat.SetString(tag, e.key, e.msg)
}
return cat, internal.UniqueTags(tags)
}
+1185
View File
File diff suppressed because it is too large Load Diff
+73
View File
@@ -5,12 +5,14 @@
package precis
import (
"bytes"
"fmt"
"reflect"
"testing"
"golang.org/x/text/internal/testtext"
"golang.org/x/text/secure/bidirule"
"golang.org/x/text/transform"
)
type testCase struct {
@@ -113,6 +115,8 @@ var enforceTestCases = []struct {
{"α͵α", "α͵α", nil},
{"͵͵α", "͵͵α", nil}, // The numeric sign is itself Greek.
{"α͵͵α", "α͵͵α", nil},
{"α͵͵", "", errContext},
{"α͵͵a", "", errContext},
}},
{"Context Rule 5+6", NewFreeform(), []testCase{
@@ -318,3 +322,72 @@ func TestTransformMallocs(t *testing.T) {
t.Errorf("got %f allocs, want 0", n)
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
// TestTransformerShortBuffers tests that the precis.Transformer implements the
// spirit, not just the letter (the method signatures), of the
// transform.Transformer interface.
//
// In particular, it tests that, if one or both of the dst or src buffers are
// short, so that multiple Transform calls are required to complete the overall
// transformation, the end result is identical to one Transform call with
// sufficiently long buffers.
func TestTransformerShortBuffers(t *testing.T) {
srcUnit := []byte("a\u0300cce\u0301nts") // NFD normalization form.
wantUnit := []byte("àccénts") // NFC normalization form.
src := bytes.Repeat(srcUnit, 16)
want := bytes.Repeat(wantUnit, 16)
const long = 4096
dst := make([]byte, long)
// 5, 7, 9, 11, 13, 16 and 17 are all pair-wise co-prime, which means that
// slicing the dst and src buffers into 5, 7, 13 and 17 byte chunks will
// fall at different places inside the repeated srcUnit's and wantUnit's.
if len(srcUnit) != 11 || len(wantUnit) != 9 || len(src) > long || len(want) > long {
t.Fatal("inconsistent lengths")
}
tr := NewFreeform().NewTransformer()
for _, deltaD := range []int{5, 7, 13, 17, long} {
loop:
for _, deltaS := range []int{5, 7, 13, 17, long} {
tr.Reset()
d0 := 0
s0 := 0
for {
d1 := min(len(dst), d0+deltaD)
s1 := min(len(src), s0+deltaS)
nDst, nSrc, err := tr.Transform(dst[d0:d1:d1], src[s0:s1:s1], s1 == len(src))
d0 += nDst
s0 += nSrc
if err == nil {
break
}
if err == transform.ErrShortDst || err == transform.ErrShortSrc {
continue
}
t.Errorf("deltaD=%d, deltaS=%d: %v", deltaD, deltaS, err)
continue loop
}
if s0 != len(src) {
t.Errorf("deltaD=%d, deltaS=%d: s0: got %d, want %d", deltaD, deltaS, s0, len(src))
continue
}
if d0 != len(want) {
t.Errorf("deltaD=%d, deltaS=%d: d0: got %d, want %d", deltaD, deltaS, d0, len(want))
continue
}
got := dst[:d0]
if !bytes.Equal(got, want) {
t.Errorf("deltaD=%d, deltaS=%d:\ngot %q\nwant %q", deltaD, deltaS, got, want)
continue
}
}
}
}
+19 -29
View File
@@ -322,33 +322,35 @@ func (c *checker) span(src []byte, atEOF bool) (n int, err error) {
}
return n, errDisallowedRune
}
doLookAhead := false
if property(e) < c.p.class.validFrom {
if d.rule == nil {
return n, errDisallowedRune
}
doLookAhead, err := d.rule(c.beforeBits)
doLookAhead, err = d.rule(c.beforeBits)
if err != nil {
return n, err
}
if doLookAhead {
c.beforeBits &= d.keep
c.beforeBits |= d.set
// We may still have a lookahead rule which we will require to
// complete (by checking termBits == 0) before setting the new
// bits.
if c.termBits != 0 && (!c.checkLookahead() || c.termBits == 0) {
return n, err
}
c.termBits = d.term
c.acceptBits = d.accept
n += sz
continue
}
}
c.beforeBits &= d.keep
c.beforeBits |= d.set
if c.termBits != 0 && !c.checkLookahead() {
return n, errContext
if c.termBits != 0 {
// We are currently in an unterminated lookahead.
if c.beforeBits&c.termBits != 0 {
c.termBits = 0
c.acceptBits = 0
} else if c.beforeBits&c.acceptBits == 0 {
// Invalid continuation of the unterminated lookahead sequence.
return n, errContext
}
}
if doLookAhead {
if c.termBits != 0 {
// A previous lookahead run has not been terminated yet.
return n, errContext
}
c.termBits = d.term
c.acceptBits = d.accept
}
n += sz
}
@@ -358,18 +360,6 @@ func (c *checker) span(src []byte, atEOF bool) (n int, err error) {
return n, err
}
func (c *checker) checkLookahead() bool {
switch {
case c.beforeBits&c.termBits != 0:
c.termBits = 0
c.acceptBits = 0
case c.beforeBits&c.acceptBits != 0:
default:
return false
}
return true
}
// TODO: we may get rid of this transform if transform.Chain understands
// something like a Spanner interface.
func (c checker) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+34 -3
View File
@@ -126,6 +126,7 @@ type SupplementalData struct {
Population string `xml:"population,attr"`
LanguagePopulation []*struct {
Common
LiteracyPercent string `xml:"literacyPercent,attr"`
WritingPercent string `xml:"writingPercent,attr"`
PopulationPercent string `xml:"populationPercent,attr"`
OfficialStatus string `xml:"officialStatus,attr"`
@@ -517,12 +518,22 @@ type SupplementalData struct {
Common
LanguageMatches []*struct {
Common
ParadigmLocales []*struct {
Common
Locales string `xml:"locales,attr"`
} `xml:"paradigmLocales"`
MatchVariable []*struct {
Common
Id string `xml:"id,attr"`
Value string `xml:"value,attr"`
} `xml:"matchVariable"`
LanguageMatch []*struct {
Common
Desired string `xml:"desired,attr"`
Oneway string `xml:"oneway,attr"`
Percent string `xml:"percent,attr"`
Supported string `xml:"supported,attr"`
Percent string `xml:"percent,attr"`
Distance string `xml:"distance,attr"`
Oneway string `xml:"oneway,attr"`
} `xml:"languageMatch"`
} `xml:"languageMatches"`
} `xml:"languageMatching"`
@@ -695,6 +706,15 @@ type LDML struct {
Common
Registry string `xml:"registry,attr"`
} `xml:"mapping"`
ParseLenients []*struct {
Common
Scope string `xml:"scope,attr"`
Level string `xml:"level,attr"`
ParseLenient []*struct {
Common
Sample string `xml:"sample,attr"`
} `xml:"parseLenient"`
} `xml:"parseLenients"`
} `xml:"characters"`
Delimiters *struct {
Common
@@ -1450,7 +1470,18 @@ type Numbers struct {
Count string `xml:"count,attr"`
} `xml:"pattern"`
} `xml:"miscPatterns"`
MinimalPairs []*struct {
Common
PluralMinimalPairs []*struct {
Common
Count string `xml:"count,attr"`
} `xml:"pluralMinimalPairs"`
OrdinalMinimalPairs []*struct {
Common
Ordinal string `xml:"ordinal,attr"`
} `xml:"ordinalMinimalPairs"`
} `xml:"minimalPairs"`
}
// Version is the version of CLDR from which the XML definitions are generated.
const Version = "30"
const Version = "31"
+1 -1
View File
@@ -1,4 +1,4 @@
// Code generated by "stringer -type=Kind"; DO NOT EDIT
// Code generated by "stringer -type=Kind"; DO NOT EDIT.
package width