podman

Форк
0
342 строки · 7.5 Кб
1
package jsoniter
2

3
import (
4
	"encoding/json"
5
	"io"
6
	"math/big"
7
	"strconv"
8
	"strings"
9
	"unsafe"
10
)
11

12
var floatDigits []int8
13

14
const invalidCharForNumber = int8(-1)
15
const endOfNumber = int8(-2)
16
const dotInNumber = int8(-3)
17

18
func init() {
19
	floatDigits = make([]int8, 256)
20
	for i := 0; i < len(floatDigits); i++ {
21
		floatDigits[i] = invalidCharForNumber
22
	}
23
	for i := int8('0'); i <= int8('9'); i++ {
24
		floatDigits[i] = i - int8('0')
25
	}
26
	floatDigits[','] = endOfNumber
27
	floatDigits[']'] = endOfNumber
28
	floatDigits['}'] = endOfNumber
29
	floatDigits[' '] = endOfNumber
30
	floatDigits['\t'] = endOfNumber
31
	floatDigits['\n'] = endOfNumber
32
	floatDigits['.'] = dotInNumber
33
}
34

35
// ReadBigFloat read big.Float
36
func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
37
	str := iter.readNumberAsString()
38
	if iter.Error != nil && iter.Error != io.EOF {
39
		return nil
40
	}
41
	prec := 64
42
	if len(str) > prec {
43
		prec = len(str)
44
	}
45
	val, _, err := big.ParseFloat(str, 10, uint(prec), big.ToZero)
46
	if err != nil {
47
		iter.Error = err
48
		return nil
49
	}
50
	return val
51
}
52

53
// ReadBigInt read big.Int
54
func (iter *Iterator) ReadBigInt() (ret *big.Int) {
55
	str := iter.readNumberAsString()
56
	if iter.Error != nil && iter.Error != io.EOF {
57
		return nil
58
	}
59
	ret = big.NewInt(0)
60
	var success bool
61
	ret, success = ret.SetString(str, 10)
62
	if !success {
63
		iter.ReportError("ReadBigInt", "invalid big int")
64
		return nil
65
	}
66
	return ret
67
}
68

69
//ReadFloat32 read float32
70
func (iter *Iterator) ReadFloat32() (ret float32) {
71
	c := iter.nextToken()
72
	if c == '-' {
73
		return -iter.readPositiveFloat32()
74
	}
75
	iter.unreadByte()
76
	return iter.readPositiveFloat32()
77
}
78

79
func (iter *Iterator) readPositiveFloat32() (ret float32) {
80
	i := iter.head
81
	// first char
82
	if i == iter.tail {
83
		return iter.readFloat32SlowPath()
84
	}
85
	c := iter.buf[i]
86
	i++
87
	ind := floatDigits[c]
88
	switch ind {
89
	case invalidCharForNumber:
90
		return iter.readFloat32SlowPath()
91
	case endOfNumber:
92
		iter.ReportError("readFloat32", "empty number")
93
		return
94
	case dotInNumber:
95
		iter.ReportError("readFloat32", "leading dot is invalid")
96
		return
97
	case 0:
98
		if i == iter.tail {
99
			return iter.readFloat32SlowPath()
100
		}
101
		c = iter.buf[i]
102
		switch c {
103
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
104
			iter.ReportError("readFloat32", "leading zero is invalid")
105
			return
106
		}
107
	}
108
	value := uint64(ind)
109
	// chars before dot
110
non_decimal_loop:
111
	for ; i < iter.tail; i++ {
112
		c = iter.buf[i]
113
		ind := floatDigits[c]
114
		switch ind {
115
		case invalidCharForNumber:
116
			return iter.readFloat32SlowPath()
117
		case endOfNumber:
118
			iter.head = i
119
			return float32(value)
120
		case dotInNumber:
121
			break non_decimal_loop
122
		}
123
		if value > uint64SafeToMultiple10 {
124
			return iter.readFloat32SlowPath()
125
		}
126
		value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
127
	}
128
	// chars after dot
129
	if c == '.' {
130
		i++
131
		decimalPlaces := 0
132
		if i == iter.tail {
133
			return iter.readFloat32SlowPath()
134
		}
135
		for ; i < iter.tail; i++ {
136
			c = iter.buf[i]
137
			ind := floatDigits[c]
138
			switch ind {
139
			case endOfNumber:
140
				if decimalPlaces > 0 && decimalPlaces < len(pow10) {
141
					iter.head = i
142
					return float32(float64(value) / float64(pow10[decimalPlaces]))
143
				}
144
				// too many decimal places
145
				return iter.readFloat32SlowPath()
146
			case invalidCharForNumber, dotInNumber:
147
				return iter.readFloat32SlowPath()
148
			}
149
			decimalPlaces++
150
			if value > uint64SafeToMultiple10 {
151
				return iter.readFloat32SlowPath()
152
			}
153
			value = (value << 3) + (value << 1) + uint64(ind)
154
		}
155
	}
156
	return iter.readFloat32SlowPath()
157
}
158

159
func (iter *Iterator) readNumberAsString() (ret string) {
160
	strBuf := [16]byte{}
161
	str := strBuf[0:0]
162
load_loop:
163
	for {
164
		for i := iter.head; i < iter.tail; i++ {
165
			c := iter.buf[i]
166
			switch c {
167
			case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
168
				str = append(str, c)
169
				continue
170
			default:
171
				iter.head = i
172
				break load_loop
173
			}
174
		}
175
		if !iter.loadMore() {
176
			break
177
		}
178
	}
179
	if iter.Error != nil && iter.Error != io.EOF {
180
		return
181
	}
182
	if len(str) == 0 {
183
		iter.ReportError("readNumberAsString", "invalid number")
184
	}
185
	return *(*string)(unsafe.Pointer(&str))
186
}
187

188
func (iter *Iterator) readFloat32SlowPath() (ret float32) {
189
	str := iter.readNumberAsString()
190
	if iter.Error != nil && iter.Error != io.EOF {
191
		return
192
	}
193
	errMsg := validateFloat(str)
194
	if errMsg != "" {
195
		iter.ReportError("readFloat32SlowPath", errMsg)
196
		return
197
	}
198
	val, err := strconv.ParseFloat(str, 32)
199
	if err != nil {
200
		iter.Error = err
201
		return
202
	}
203
	return float32(val)
204
}
205

206
// ReadFloat64 read float64
207
func (iter *Iterator) ReadFloat64() (ret float64) {
208
	c := iter.nextToken()
209
	if c == '-' {
210
		return -iter.readPositiveFloat64()
211
	}
212
	iter.unreadByte()
213
	return iter.readPositiveFloat64()
214
}
215

216
func (iter *Iterator) readPositiveFloat64() (ret float64) {
217
	i := iter.head
218
	// first char
219
	if i == iter.tail {
220
		return iter.readFloat64SlowPath()
221
	}
222
	c := iter.buf[i]
223
	i++
224
	ind := floatDigits[c]
225
	switch ind {
226
	case invalidCharForNumber:
227
		return iter.readFloat64SlowPath()
228
	case endOfNumber:
229
		iter.ReportError("readFloat64", "empty number")
230
		return
231
	case dotInNumber:
232
		iter.ReportError("readFloat64", "leading dot is invalid")
233
		return
234
	case 0:
235
		if i == iter.tail {
236
			return iter.readFloat64SlowPath()
237
		}
238
		c = iter.buf[i]
239
		switch c {
240
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
241
			iter.ReportError("readFloat64", "leading zero is invalid")
242
			return
243
		}
244
	}
245
	value := uint64(ind)
246
	// chars before dot
247
non_decimal_loop:
248
	for ; i < iter.tail; i++ {
249
		c = iter.buf[i]
250
		ind := floatDigits[c]
251
		switch ind {
252
		case invalidCharForNumber:
253
			return iter.readFloat64SlowPath()
254
		case endOfNumber:
255
			iter.head = i
256
			return float64(value)
257
		case dotInNumber:
258
			break non_decimal_loop
259
		}
260
		if value > uint64SafeToMultiple10 {
261
			return iter.readFloat64SlowPath()
262
		}
263
		value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
264
	}
265
	// chars after dot
266
	if c == '.' {
267
		i++
268
		decimalPlaces := 0
269
		if i == iter.tail {
270
			return iter.readFloat64SlowPath()
271
		}
272
		for ; i < iter.tail; i++ {
273
			c = iter.buf[i]
274
			ind := floatDigits[c]
275
			switch ind {
276
			case endOfNumber:
277
				if decimalPlaces > 0 && decimalPlaces < len(pow10) {
278
					iter.head = i
279
					return float64(value) / float64(pow10[decimalPlaces])
280
				}
281
				// too many decimal places
282
				return iter.readFloat64SlowPath()
283
			case invalidCharForNumber, dotInNumber:
284
				return iter.readFloat64SlowPath()
285
			}
286
			decimalPlaces++
287
			if value > uint64SafeToMultiple10 {
288
				return iter.readFloat64SlowPath()
289
			}
290
			value = (value << 3) + (value << 1) + uint64(ind)
291
			if value > maxFloat64 {
292
				return iter.readFloat64SlowPath()
293
			}
294
		}
295
	}
296
	return iter.readFloat64SlowPath()
297
}
298

299
func (iter *Iterator) readFloat64SlowPath() (ret float64) {
300
	str := iter.readNumberAsString()
301
	if iter.Error != nil && iter.Error != io.EOF {
302
		return
303
	}
304
	errMsg := validateFloat(str)
305
	if errMsg != "" {
306
		iter.ReportError("readFloat64SlowPath", errMsg)
307
		return
308
	}
309
	val, err := strconv.ParseFloat(str, 64)
310
	if err != nil {
311
		iter.Error = err
312
		return
313
	}
314
	return val
315
}
316

317
func validateFloat(str string) string {
318
	// strconv.ParseFloat is not validating `1.` or `1.e1`
319
	if len(str) == 0 {
320
		return "empty number"
321
	}
322
	if str[0] == '-' {
323
		return "-- is not valid"
324
	}
325
	dotPos := strings.IndexByte(str, '.')
326
	if dotPos != -1 {
327
		if dotPos == len(str)-1 {
328
			return "dot can not be last character"
329
		}
330
		switch str[dotPos+1] {
331
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
332
		default:
333
			return "missing digit after dot"
334
		}
335
	}
336
	return ""
337
}
338

339
// ReadNumber read json.Number
340
func (iter *Iterator) ReadNumber() (ret json.Number) {
341
	return json.Number(iter.readNumberAsString())
342
}
343

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.