...
1
2
3
4
5 package text
6
7
8 func (d *Decoder) parseNumberValue() (Token, bool) {
9 in := d.in
10 num := parseNumber(in)
11 if num.size == 0 {
12 return Token{}, false
13 }
14 numAttrs := num.kind
15 if num.neg {
16 numAttrs |= isNegative
17 }
18 tok := Token{
19 kind: Scalar,
20 attrs: numberValue,
21 pos: len(d.orig) - len(d.in),
22 raw: d.in[:num.size],
23 str: num.string(d.in),
24 numAttrs: numAttrs,
25 }
26 d.consume(num.size)
27 return tok, true
28 }
29
30 const (
31 numDec uint8 = (1 << iota) / 2
32 numHex
33 numOct
34 numFloat
35 )
36
37
38
39
40 type number struct {
41 kind uint8
42 neg bool
43 size int
44
45
46 sep int
47 }
48
49 func (num number) string(data []byte) string {
50 strSize := num.size
51 last := num.size - 1
52 if num.kind == numFloat && (data[last] == 'f' || data[last] == 'F') {
53 strSize = last
54 }
55 if num.neg && num.sep > 0 {
56
57 strLen := strSize - num.sep
58 str := make([]byte, strLen)
59 str[0] = data[0]
60 copy(str[1:], data[num.sep+1:strSize])
61 return string(str)
62 }
63 return string(data[:strSize])
64
65 }
66
67
68
69
70
71
72
73
74
75 func parseNumber(input []byte) number {
76 kind := numDec
77 var size int
78 var neg bool
79
80 s := input
81 if len(s) == 0 {
82 return number{}
83 }
84
85
86 var sep int
87 if s[0] == '-' {
88 neg = true
89 s = s[1:]
90 size++
91
92
93 lenBefore := len(s)
94 s = consume(s, 0)
95 sep = lenBefore - len(s)
96 size += sep
97 if len(s) == 0 {
98 return number{}
99 }
100 }
101
102 switch {
103 case s[0] == '0':
104 if len(s) > 1 {
105 switch {
106 case s[1] == 'x' || s[1] == 'X':
107
108 kind = numHex
109 n := 2
110 s = s[2:]
111 for len(s) > 0 && (('0' <= s[0] && s[0] <= '9') ||
112 ('a' <= s[0] && s[0] <= 'f') ||
113 ('A' <= s[0] && s[0] <= 'F')) {
114 s = s[1:]
115 n++
116 }
117 if n == 2 {
118 return number{}
119 }
120 size += n
121
122 case '0' <= s[1] && s[1] <= '7':
123
124 kind = numOct
125 n := 2
126 s = s[2:]
127 for len(s) > 0 && '0' <= s[0] && s[0] <= '7' {
128 s = s[1:]
129 n++
130 }
131 size += n
132 }
133
134 if kind&(numHex|numOct) > 0 {
135 if len(s) > 0 && !isDelim(s[0]) {
136 return number{}
137 }
138 return number{kind: kind, neg: neg, size: size, sep: sep}
139 }
140 }
141 s = s[1:]
142 size++
143
144 case '1' <= s[0] && s[0] <= '9':
145 n := 1
146 s = s[1:]
147 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
148 s = s[1:]
149 n++
150 }
151 size += n
152
153 case s[0] == '.':
154
155
156 kind = numFloat
157
158 default:
159 return number{}
160 }
161
162
163 if len(s) > 0 && s[0] == '.' {
164 n := 1
165 s = s[1:]
166
167
168 if len(s) == 0 && kind == numFloat {
169 return number{}
170 }
171 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
172 s = s[1:]
173 n++
174 }
175 size += n
176 kind = numFloat
177 }
178
179
180 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
181 kind = numFloat
182 s = s[1:]
183 n := 1
184 if s[0] == '+' || s[0] == '-' {
185 s = s[1:]
186 n++
187 if len(s) == 0 {
188 return number{}
189 }
190 }
191 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
192 s = s[1:]
193 n++
194 }
195 size += n
196 }
197
198
199 if len(s) > 0 && (s[0] == 'f' || s[0] == 'F') {
200 kind = numFloat
201 s = s[1:]
202 size++
203 }
204
205
206 if len(s) > 0 && !isDelim(s[0]) {
207 return number{}
208 }
209
210 return number{kind: kind, neg: neg, size: size, sep: sep}
211 }
212
View as plain text