github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/internal/decoder/number.go (about) 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 }