1 package decoder
2
3 import (
4 "encoding/json"
5 "strconv"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/errors"
9 )
10
11 type numberDecoder struct {
12 stringDecoder *stringDecoder
13 op func(unsafe.Pointer, json.Number)
14 structName string
15 fieldName string
16 }
17
18 func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
19 return &numberDecoder{
20 stringDecoder: newStringDecoder(structName, fieldName),
21 op: op,
22 structName: structName,
23 fieldName: fieldName,
24 }
25 }
26
27 func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
28 bytes, err := d.decodeStreamByte(s)
29 if err != nil {
30 return err
31 }
32 if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
33 return errors.ErrSyntax(err.Error(), s.totalOffset())
34 }
35 d.op(p, json.Number(string(bytes)))
36 s.reset()
37 return nil
38 }
39
40 func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
41 bytes, c, err := d.decodeByte(ctx.Buf, cursor)
42 if err != nil {
43 return 0, err
44 }
45 if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
46 return 0, errors.ErrSyntax(err.Error(), c)
47 }
48 cursor = c
49 s := *(*string)(unsafe.Pointer(&bytes))
50 d.op(p, json.Number(s))
51 return cursor, nil
52 }
53
54 func (d *numberDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
55 bytes, c, err := d.decodeByte(ctx.Buf, cursor)
56 if err != nil {
57 return nil, 0, err
58 }
59 if bytes == nil {
60 return [][]byte{nullbytes}, c, nil
61 }
62 return [][]byte{bytes}, c, nil
63 }
64
65 func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
66 start := s.cursor
67 for {
68 switch s.char() {
69 case ' ', '\n', '\t', '\r':
70 s.cursor++
71 continue
72 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
73 return floatBytes(s), nil
74 case 'n':
75 if err := nullBytes(s); err != nil {
76 return nil, err
77 }
78 return nil, nil
79 case '"':
80 return d.stringDecoder.decodeStreamByte(s)
81 case nul:
82 if s.read() {
83 continue
84 }
85 goto ERROR
86 default:
87 goto ERROR
88 }
89 }
90 ERROR:
91 if s.cursor == start {
92 return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
93 }
94 return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
95 }
96
97 func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
98 for {
99 switch buf[cursor] {
100 case ' ', '\n', '\t', '\r':
101 cursor++
102 continue
103 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
104 start := cursor
105 cursor++
106 for floatTable[buf[cursor]] {
107 cursor++
108 }
109 num := buf[start:cursor]
110 return num, cursor, nil
111 case 'n':
112 if err := validateNull(buf, cursor); err != nil {
113 return nil, 0, err
114 }
115 cursor += 4
116 return nil, cursor, nil
117 case '"':
118 return d.stringDecoder.decodeByte(buf, cursor)
119 default:
120 return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
121 }
122 }
123 }
124
View as plain text