...
1
2
3
4
5 package cldrtree
6
7 import (
8 "log"
9 "strconv"
10 )
11
12
13 type enumIndex int
14
15
16 type enum struct {
17 name string
18 rename func(string) string
19 keyMap map[string]enumIndex
20 keys []string
21 }
22
23
24
25 func (e *enum) lookup(s string) enumIndex {
26 if e.rename != nil {
27 s = e.rename(s)
28 }
29 x, ok := e.keyMap[s]
30 if !ok {
31 if e.keyMap == nil {
32 e.keyMap = map[string]enumIndex{}
33 }
34 u, err := strconv.ParseUint(s, 10, 32)
35 if err == nil {
36 for len(e.keys) <= int(u) {
37 x := enumIndex(len(e.keys))
38 s := strconv.Itoa(int(x))
39 e.keyMap[s] = x
40 e.keys = append(e.keys, s)
41 }
42 if e.keyMap[s] != enumIndex(u) {
43
44 log.Fatalf("cldrtree: mix of integer and non-integer for %q %v", s, e.keys)
45 }
46 return enumIndex(u)
47 }
48 x = enumIndex(len(e.keys))
49 e.keyMap[s] = x
50 e.keys = append(e.keys, s)
51 }
52 return x
53 }
54
55
56
57 type typeInfo struct {
58 enum *enum
59 entries map[enumIndex]*typeInfo
60 keyTypeInfo *typeInfo
61 shareKeys bool
62 }
63
64 func (t *typeInfo) sharedKeys() bool {
65 return t.shareKeys
66 }
67
68 func (t *typeInfo) lookupSubtype(s string, opts *options) (x enumIndex, sub *typeInfo) {
69 if t.enum == nil {
70 if t.enum = opts.sharedEnums; t.enum == nil {
71 t.enum = &enum{}
72 }
73 }
74 if opts.sharedEnums != nil && t.enum != opts.sharedEnums {
75 panic("incompatible enums defined")
76 }
77 x = t.enum.lookup(s)
78 if t.entries == nil {
79 t.entries = map[enumIndex]*typeInfo{}
80 }
81 sub, ok := t.entries[x]
82 if !ok {
83 sub = opts.sharedType
84 if sub == nil {
85 sub = &typeInfo{}
86 }
87 t.entries[x] = sub
88 }
89 t.shareKeys = opts.sharedType != nil
90 return x, sub
91 }
92
93
94
95
96 type metaData struct {
97 b *Builder
98
99 parent *metaData
100
101 index enumIndex
102 key string
103 elem string
104 typeInfo *typeInfo
105
106 lookup map[enumIndex]*metaData
107 subs []*metaData
108
109 inheritOffset int
110 inheritIndex string
111
112 }
113
114 func (m *metaData) sub(key string, opts *options) *metaData {
115 if m.lookup == nil {
116 m.lookup = map[enumIndex]*metaData{}
117 }
118 enum, info := m.typeInfo.lookupSubtype(key, opts)
119 sub := m.lookup[enum]
120 if sub == nil {
121 sub = &metaData{
122 b: m.b,
123 parent: m,
124
125 index: enum,
126 key: key,
127 typeInfo: info,
128 }
129 m.lookup[enum] = sub
130 m.subs = append(m.subs, sub)
131 }
132 return sub
133 }
134
135 func (m *metaData) validate() {
136 for _, s := range m.subs {
137 s.validate()
138 }
139 }
140
View as plain text